From 3699fdc69b4b2606ef5beb5b6ccfb56d9cad26b5 Mon Sep 17 00:00:00 2001 From: Ben Karl Date: Wed, 22 Apr 2026 18:49:41 +0000 Subject: [PATCH] Changes for release 24_0. --- ChangeLog | 7 + .../account_management/create_customer.py | 9 +- .../get_account_hierarchy.py | 10 +- .../account_management/get_change_details.py | 8 +- .../account_management/get_change_summary.py | 9 +- .../invite_user_with_access_role.py | 11 +- .../link_manager_to_client.py | 18 +- .../list_accessible_customers.py | 7 +- .../account_management/update_user_access.py | 12 +- .../verify_advertiser_identity.py | 9 +- .../advanced_operations/add_ad_customizer.py | 17 +- .../add_ad_group_bid_modifier.py | 13 +- .../advanced_operations/add_app_campaign.py | 31 +- .../add_bidding_data_exclusion.py | 9 +- .../add_bidding_seasonality_adjustment.py | 9 +- .../add_demand_gen_campaign.py | 10 +- .../add_display_upload_ad.py | 18 +- .../add_dynamic_page_feed_asset.py | 39 +- .../add_dynamic_search_ads.py | 39 +- .../add_performance_max_campaign.py | 34 +- .../add_responsive_search_ad_full.py | 58 +- .../advanced_operations/add_smart_campaign.py | 50 +- .../create_and_attach_shared_keyword_set.py | 25 +- ...ind_and_remove_criteria_from_shared_set.py | 21 +- .../get_ad_group_bid_modifiers.py | 9 +- examples/advanced_operations/upload_video.py | 20 +- .../use_cross_account_bidding_strategy.py | 23 +- .../use_portfolio_bidding_strategy.py | 23 +- examples/assets/add_call.py | 13 +- examples/assets/add_hotel_callout.py | 11 +- examples/assets/add_lead_form_asset.py | 17 +- examples/assets/add_prices.py | 17 +- examples/assets/add_sitelinks.py | 10 +- examples/assets/upload_image_asset.py | 7 +- examples/asyncio/async_add_campaigns.py | 26 +- examples/asyncio/async_search.py | 11 +- examples/asyncio/async_search_stream.py | 7 +- .../generate_audience_insights.py | 12 +- examples/basic_operations/add_ad_groups.py | 11 +- examples/basic_operations/add_campaigns.py | 20 +- examples/basic_operations/get_campaigns.py | 7 +- .../get_responsive_search_ads.py | 10 +- examples/basic_operations/pause_ad.py | 9 +- examples/basic_operations/remove_campaign.py | 7 +- .../search_for_google_ads_fields.py | 9 +- examples/basic_operations/update_ad_group.py | 11 +- examples/basic_operations/update_campaign.py | 9 +- .../update_responsive_search_ad.py | 11 +- .../billing/add_account_budget_proposal.py | 3 +- examples/billing/add_billing_setup.py | 3 +- examples/billing/get_invoices.py | 15 +- .../add_campaign_labels.py | 12 +- .../add_complete_campaigns_using_batch_job.py | 26 +- .../campaign_management/create_experiment.py | 20 +- .../get_all_disapproved_ads.py | 13 +- .../campaign_management/set_ad_parameters.py | 11 +- .../update_campaign_criterion_bid_modifier.py | 8 +- examples/campaign_management/validate_ad.py | 17 +- .../get_campaigns.py | 10 +- .../handle_keyword_policy_violations.py | 8 +- .../error_handling/handle_partial_failure.py | 9 +- .../handle_rate_exceeded_error.py | 11 +- ..._responsive_search_ad_policy_violations.py | 16 +- examples/incentives/apply_incentive.py | 16 +- examples/incentives/fetch_incentives.py | 18 +- examples/misc/add_ad_group_image_asset.py | 9 +- examples/misc/campaign_report_to_csv.py | 8 +- examples/misc/set_custom_client_timeouts.py | 8 +- examples/misc/upload_image_asset.py | 9 +- examples/planning/forecast_reach.py | 14 +- .../planning/generate_forecast_metrics.py | 65 +- .../planning/generate_historical_metrics.py | 10 +- examples/planning/generate_keyword_ideas.py | 15 +- ..._ad_group_criterion_cpc_bid_simulations.py | 10 +- .../detect_and_apply_recommendations.py | 7 +- .../recommendations/dismiss_recommendation.py | 7 +- .../generate_budget_recommendations.py | 9 +- .../get_recommendation_impact_metrics.py | 9 +- examples/remarketing/add_conversion_action.py | 9 +- .../add_conversion_based_user_list.py | 12 +- examples/remarketing/add_custom_audience.py | 11 +- .../add_customer_match_user_list.py | 24 +- .../add_dynamic_remarketing_asset.py | 31 +- .../add_flexible_rule_user_list.py | 10 +- examples/remarketing/add_logical_user_list.py | 10 +- ...ant_center_dynamic_remarketing_campaign.py | 37 +- .../set_up_advanced_remarketing.py | 12 +- examples/remarketing/set_up_remarketing.py | 27 +- .../update_audience_target_restriction.py | 17 +- .../remarketing/upload_call_conversion.py | 7 +- .../upload_conversion_adjustment.py | 13 +- .../upload_enhanced_conversions_for_leads.py | 13 +- .../upload_enhanced_conversions_for_web.py | 5 +- .../remarketing/upload_offline_conversion.py | 9 +- .../upload_store_sales_transactions.py | 20 +- .../reporting/parallel_report_download.py | 8 +- examples/shopping_ads/add_listing_scope.py | 16 +- ...formance_max_product_listing_group_tree.py | 14 +- .../add_performance_max_retail_campaign.py | 44 +- .../shopping_ads/add_shopping_product_ad.py | 33 +- ...add_shopping_product_listing_group_tree.py | 18 +- .../get_product_category_constants.py | 9 +- .../add_campaign_targeting_criteria.py | 15 +- .../add_customer_negative_criteria.py | 9 +- .../add_demographic_targeting_criteria.py | 11 +- .../get_geo_target_constants_by_names.py | 9 +- examples/travel/add_hotel_ad.py | 27 +- .../add_hotel_ad_group_bid_modifiers.py | 13 +- .../travel/add_hotel_listing_group_tree.py | 13 +- ...rformance_max_for_travel_goals_campaign.py | 36 +- examples/travel/add_things_to_do_ad.py | 27 +- google/ads/googleads/__init__.py | 2 +- google/ads/googleads/client.py | 2 +- google/ads/googleads/v24/__init__.py | 141 + google/ads/googleads/v24/actions/__init__.py | 151 + .../v24/actions/services/__init__.py | 15 + .../googleads/v24/actions/types/__init__.py | 44 + .../v24/actions/types/book_campaigns.py | 96 + .../types/generate_shareable_previews.py | 215 + .../v24/actions/types/quote_campaigns.py | 104 + google/ads/googleads/v24/common/__init__.py | 843 +++ .../googleads/v24/common/services/__init__.py | 15 + .../googleads/v24/common/types/__init__.py | 790 +++ .../googleads/v24/common/types/ad_asset.py | 334 ++ .../v24/common/types/ad_type_infos.py | 1852 ++++++ .../types/additional_application_info.py | 68 + .../v24/common/types/asset_policy.py | 154 + .../v24/common/types/asset_set_types.py | 366 ++ .../googleads/v24/common/types/asset_types.py | 2601 +++++++++ .../googleads/v24/common/types/asset_usage.py | 58 + .../types/audience_insights_attribute.py | 676 +++ .../googleads/v24/common/types/audiences.py | 478 ++ .../ads/googleads/v24/common/types/bidding.py | 599 ++ .../common/types/campaign_goal_settings.py | 69 + .../types/campaign_reservation_quote.py | 76 + .../v24/common/types/click_location.py | 91 + .../ads/googleads/v24/common/types/consent.py | 59 + .../googleads/v24/common/types/criteria.py | 2556 +++++++++ .../types/criterion_category_availability.py | 176 + .../v24/common/types/custom_parameter.py | 61 + .../v24/common/types/customizer_value.py | 61 + .../ads/googleads/v24/common/types/dates.py | 111 + .../googleads/v24/common/types/extensions.py | 225 + .../googleads/v24/common/types/feed_common.py | 60 + .../v24/common/types/final_app_url.py | 71 + .../v24/common/types/frequency_cap.py | 120 + .../googleads/v24/common/types/goal_common.py | 67 + .../v24/common/types/goal_setting.py | 53 + .../v24/common/types/keyword_plan_common.py | 337 ++ .../v24/common/types/lifecycle_goals.py | 67 + .../v24/common/types/local_services.py | 51 + .../googleads/v24/common/types/metric_goal.py | 62 + .../ads/googleads/v24/common/types/metrics.py | 3376 +++++++++++ .../v24/common/types/offline_user_data.py | 798 +++ .../ads/googleads/v24/common/types/policy.py | 515 ++ .../v24/common/types/policy_summary.py | 73 + .../common/types/real_time_bidding_setting.py | 53 + .../googleads/v24/common/types/segments.py | 1704 ++++++ .../googleads/v24/common/types/simulation.py | 763 +++ .../googleads/v24/common/types/tag_snippet.py | 87 + .../v24/common/types/targeting_setting.py | 155 + .../googleads/v24/common/types/text_label.py | 63 + .../types/third_party_integration_partners.py | 420 ++ .../v24/common/types/url_collection.py | 73 + .../googleads/v24/common/types/user_lists.py | 644 +++ .../ads/googleads/v24/common/types/value.py | 91 + google/ads/googleads/v24/enums/__init__.py | 1085 ++++ .../googleads/v24/enums/services/__init__.py | 15 + .../ads/googleads/v24/enums/types/__init__.py | 1506 +++++ .../enums/types/access_invitation_status.py | 65 + .../v24/enums/types/access_reason.py | 67 + .../googleads/v24/enums/types/access_role.py | 65 + .../types/account_budget_proposal_status.py | 69 + .../types/account_budget_proposal_type.py | 64 + .../v24/enums/types/account_budget_status.py | 59 + .../v24/enums/types/account_link_status.py | 77 + .../v24/enums/types/ad_destination_type.py | 83 + .../v24/enums/types/ad_format_type.py | 125 + .../enums/types/ad_group_ad_primary_status.py | 72 + .../ad_group_ad_primary_status_reason.py | 121 + .../enums/types/ad_group_ad_rotation_mode.py | 60 + .../v24/enums/types/ad_group_ad_status.py | 62 + .../ad_group_criterion_approval_status.py | 63 + .../ad_group_criterion_primary_status.py | 70 + ...d_group_criterion_primary_status_reason.py | 143 + .../enums/types/ad_group_criterion_status.py | 59 + .../enums/types/ad_group_primary_status.py | 70 + .../types/ad_group_primary_status_reason.py | 123 + .../v24/enums/types/ad_group_status.py | 62 + .../v24/enums/types/ad_group_type.py | 113 + .../v24/enums/types/ad_network_type.py | 83 + .../types/ad_serving_optimization_status.py | 71 + .../googleads/v24/enums/types/ad_strength.py | 67 + .../types/ad_strength_action_item_type.py | 53 + .../v24/enums/types/ad_sub_network_type.py | 63 + .../ads/googleads/v24/enums/types/ad_type.py | 149 + .../types/advertising_channel_sub_type.py | 120 + .../enums/types/advertising_channel_type.py | 88 + .../v24/enums/types/age_range_type.py | 74 + .../types/android_privacy_interaction_type.py | 57 + .../types/android_privacy_network_type.py | 57 + .../v24/enums/types/app_bidding_goal.py | 92 + .../v24/enums/types/app_campaign_app_store.py | 55 + ...app_campaign_bidding_strategy_goal_type.py | 94 + .../v24/enums/types/app_payment_model_type.py | 52 + .../types/app_url_operating_system_type.py | 55 + .../v24/enums/types/application_instance.py | 55 + .../enums/types/asset_automation_status.py | 57 + .../v24/enums/types/asset_automation_type.py | 113 + ...coverage_video_aspect_ratio_requirement.py | 62 + .../v24/enums/types/asset_field_type.py | 185 + .../enums/types/asset_group_primary_status.py | 73 + .../asset_group_primary_status_reason.py | 95 + .../asset_group_signal_approval_status.py | 70 + .../v24/enums/types/asset_group_status.py | 61 + .../enums/types/asset_link_primary_status.py | 78 + .../types/asset_link_primary_status_reason.py | 79 + .../v24/enums/types/asset_link_status.py | 61 + .../asset_offline_evaluation_error_reasons.py | 82 + .../v24/enums/types/asset_orientation.py | 60 + .../enums/types/asset_performance_label.py | 77 + .../v24/enums/types/asset_set_asset_status.py | 58 + .../v24/enums/types/asset_set_link_status.py | 61 + .../v24/enums/types/asset_set_status.py | 58 + .../v24/enums/types/asset_set_type.py | 105 + .../googleads/v24/enums/types/asset_source.py | 60 + .../googleads/v24/enums/types/asset_type.py | 139 + .../v24/enums/types/async_action_status.py | 67 + .../v24/enums/types/attribution_model.py | 87 + .../types/audience_insights_dimension.py | 98 + .../audience_insights_marketing_objective.py | 63 + .../v24/enums/types/audience_scope.py | 56 + .../v24/enums/types/audience_status.py | 57 + .../v24/enums/types/batch_job_status.py | 58 + .../types/benchmarks_marketing_objective.py | 62 + .../v24/enums/types/benchmarks_source_type.py | 53 + .../types/benchmarks_time_granularity.py | 62 + .../v24/enums/types/bid_modifier_source.py | 57 + .../v24/enums/types/bidding_source.py | 62 + .../enums/types/bidding_strategy_status.py | 56 + .../types/bidding_strategy_system_status.py | 162 + .../v24/enums/types/bidding_strategy_type.py | 168 + .../v24/enums/types/billing_setup_status.py | 65 + .../v24/enums/types/booking_status.py | 69 + .../types/brand_request_rejection_reason.py | 67 + .../enums/types/brand_safety_suitability.py | 93 + .../googleads/v24/enums/types/brand_state.py | 79 + .../budget_campaign_association_status.py | 59 + .../v24/enums/types/budget_delivery_method.py | 60 + .../v24/enums/types/budget_period.py | 58 + .../v24/enums/types/budget_status.py | 55 + .../googleads/v24/enums/types/budget_type.py | 80 + .../business_message_call_to_action_type.py | 77 + .../enums/types/business_message_provider.py | 58 + .../types/call_conversion_reporting_state.py | 64 + .../v24/enums/types/call_to_action_type.py | 100 + .../types/call_tracking_display_location.py | 59 + .../googleads/v24/enums/types/call_type.py | 58 + .../enums/types/campaign_criterion_status.py | 59 + .../v24/enums/types/campaign_draft_status.py | 78 + .../enums/types/campaign_experiment_type.py | 65 + .../v24/enums/types/campaign_group_status.py | 55 + .../types/campaign_keyword_match_type.py | 52 + .../enums/types/campaign_primary_status.py | 88 + .../types/campaign_primary_status_reason.py | 225 + .../enums/types/campaign_serving_status.py | 65 + .../enums/types/campaign_shared_set_status.py | 59 + .../v24/enums/types/campaign_status.py | 61 + .../enums/types/chain_relationship_type.py | 58 + .../v24/enums/types/change_client_type.py | 104 + .../enums/types/change_event_resource_type.py | 110 + .../enums/types/change_status_operation.py | 61 + .../types/change_status_resource_type.py | 116 + .../googleads/v24/enums/types/click_type.py | 244 + .../enums/types/combined_audience_status.py | 57 + .../v24/enums/types/consent_status.py | 55 + .../v24/enums/types/content_label_type.py | 153 + .../enums/types/conversion_action_category.py | 143 + .../types/conversion_action_counting_type.py | 60 + .../enums/types/conversion_action_status.py | 62 + .../v24/enums/types/conversion_action_type.py | 269 + .../enums/types/conversion_adjustment_type.py | 63 + .../conversion_attribution_event_type.py | 63 + .../conversion_custom_variable_status.py | 69 + .../enums/types/conversion_customer_type.py | 57 + .../types/conversion_environment_enum.py | 58 + .../v24/enums/types/conversion_lag_bucket.py | 129 + .../conversion_or_adjustment_lag_bucket.py | 221 + .../v24/enums/types/conversion_origin.py | 76 + .../types/conversion_tracking_status_enum.py | 69 + ...conversion_value_rule_primary_dimension.py | 84 + .../types/conversion_value_rule_set_status.py | 64 + .../types/conversion_value_rule_status.py | 64 + ...er_prior_engagement_type_and_ltv_bucket.py | 65 + ...rion_category_channel_availability_mode.py | 69 + ...erion_category_locale_availability_mode.py | 71 + .../types/criterion_system_serving_status.py | 57 + .../v24/enums/types/criterion_type.py | 195 + .../types/custom_audience_member_type.py | 64 + .../v24/enums/types/custom_audience_status.py | 57 + .../v24/enums/types/custom_audience_type.py | 64 + .../types/custom_conversion_goal_status.py | 58 + .../types/custom_interest_member_type.py | 55 + .../v24/enums/types/custom_interest_status.py | 57 + .../v24/enums/types/custom_interest_type.py | 57 + .../customer_acquisition_optimization_mode.py | 65 + .../customer_lifecycle_optimization_mode.py | 61 + .../types/customer_match_upload_key_type.py | 65 + ...r_conversion_eligibility_failure_reason.py | 78 + .../v24/enums/types/customer_status.py | 69 + .../types/customizer_attribute_status.py | 58 + .../enums/types/customizer_attribute_type.py | 66 + .../enums/types/customizer_value_status.py | 58 + .../enums/types/data_driven_model_status.py | 71 + .../v24/enums/types/data_link_status.py | 71 + .../v24/enums/types/data_link_type.py | 51 + .../googleads/v24/enums/types/day_of_week.py | 72 + .../enums/types/demand_gen_channel_config.py | 59 + .../types/demand_gen_channel_strategy.py | 57 + .../ads/googleads/v24/enums/types/device.py | 66 + .../enums/types/display_ad_format_setting.py | 59 + .../types/display_upload_product_type.py | 105 + .../v24/enums/types/distance_bucket.py | 134 + .../types/eu_political_advertising_status.py | 65 + .../v24/enums/types/experiment_metric.py | 94 + .../types/experiment_metric_direction.py | 71 + .../v24/enums/types/experiment_status.py | 74 + .../v24/enums/types/experiment_type.py | 86 + .../enums/types/external_conversion_source.py | 193 + .../v24/enums/types/fixed_cpm_goal.py | 61 + .../fixed_cpm_target_frequency_time_unit.py | 58 + .../enums/types/frequency_cap_event_type.py | 59 + .../v24/enums/types/frequency_cap_level.py | 62 + .../enums/types/frequency_cap_time_unit.py | 61 + .../googleads/v24/enums/types/gender_type.py | 61 + .../enums/types/geo_target_constant_status.py | 57 + .../v24/enums/types/geo_targeting_type.py | 55 + .../v24/enums/types/goal_config_level.py | 59 + .../types/goal_optimization_eligibility.py | 61 + .../googleads/v24/enums/types/goal_type.py | 54 + .../enums/types/google_ads_field_category.py | 70 + .../enums/types/google_ads_field_data_type.py | 114 + .../enums/types/google_voice_call_status.py | 58 + .../types/hotel_asset_suggestion_status.py | 63 + .../enums/types/hotel_date_selection_type.py | 58 + .../v24/enums/types/hotel_price_bucket.py | 67 + .../v24/enums/types/hotel_rate_type.py | 69 + .../types/hotel_reconciliation_status.py | 71 + .../types/identity_verification_program.py | 52 + .../identity_verification_program_status.py | 61 + .../v24/enums/types/incentive_state.py | 75 + .../v24/enums/types/income_range_type.py | 74 + ...hts_knowledge_graph_entity_capabilities.py | 59 + .../v24/enums/types/insights_trend.py | 60 + .../v24/enums/types/interaction_event_type.py | 76 + .../v24/enums/types/interaction_type.py | 52 + .../googleads/v24/enums/types/invoice_type.py | 57 + .../v24/enums/types/keyword_match_type.py | 58 + .../keyword_plan_aggregate_metric_type.py | 52 + .../types/keyword_plan_competition_level.py | 67 + .../types/keyword_plan_concept_group_type.py | 70 + .../types/keyword_plan_forecast_interval.py | 61 + .../types/keyword_plan_keyword_annotation.py | 55 + .../v24/enums/types/keyword_plan_network.py | 57 + .../googleads/v24/enums/types/label_status.py | 55 + .../v24/enums/types/landing_page_source.py | 63 + .../types/lead_form_call_to_action_type.py | 92 + .../enums/types/lead_form_desired_intent.py | 57 + .../types/lead_form_field_user_input_type.py | 704 +++ ...ad_form_post_submit_call_to_action_type.py | 65 + .../types/legacy_app_install_ad_app_store.py | 67 + .../v24/enums/types/linked_account_type.py | 57 + .../v24/enums/types/linked_product_type.py | 69 + ...ing_group_filter_custom_attribute_index.py | 67 + .../listing_group_filter_listing_source.py | 65 + ...ing_group_filter_product_category_level.py | 67 + .../listing_group_filter_product_channel.py | 55 + .../listing_group_filter_product_condition.py | 58 + ...listing_group_filter_product_type_level.py | 64 + .../types/listing_group_filter_type_enum.py | 62 + .../v24/enums/types/listing_group_type.py | 58 + .../googleads/v24/enums/types/listing_type.py | 52 + ...ess_registration_check_rejection_reason.py | 85 + ...cal_services_business_registration_type.py | 59 + .../types/local_services_conversation_type.py | 74 + .../types/local_services_employee_status.py | 60 + .../types/local_services_employee_type.py | 58 + ...cal_services_insurance_rejection_reason.py | 107 + ..._services_lead_credit_issuance_decision.py | 70 + .../types/local_services_lead_credit_state.py | 61 + .../enums/types/local_services_lead_status.py | 75 + .../local_services_lead_survey_answer.py | 67 + ...ervices_lead_survey_dissatisfied_reason.py | 79 + ...l_services_lead_survey_satisfied_reason.py | 71 + .../enums/types/local_services_lead_type.py | 58 + ...local_services_license_rejection_reason.py | 79 + .../types/local_services_participant_type.py | 58 + ...l_services_verification_artifact_status.py | 69 + ...cal_services_verification_artifact_type.py | 66 + .../local_services_verification_status.py | 77 + .../types/location_group_radius_units.py | 62 + .../enums/types/location_ownership_type.py | 60 + .../v24/enums/types/location_source_type.py | 57 + .../types/location_string_filter_type.py | 55 + .../enums/types/lookalike_expansion_level.py | 63 + .../v24/enums/types/manager_link_status.py | 70 + .../googleads/v24/enums/types/match_type.py | 64 + .../googleads/v24/enums/types/media_type.py | 68 + .../enums/types/messaging_restriction_type.py | 56 + .../googleads/v24/enums/types/mime_type.py | 86 + .../v24/enums/types/minute_of_hour.py | 60 + .../v24/enums/types/mobile_app_vendor.py | 58 + .../v24/enums/types/mobile_device_type.py | 55 + .../v24/enums/types/month_of_year.py | 87 + .../enums/types/negative_geo_target_type.py | 61 + .../enums/types/non_skippable_max_duration.py | 65 + .../enums/types/non_skippable_min_duration.py | 69 + ...fline_conversion_diagnostic_status_enum.py | 68 + .../types/offline_event_upload_client_enum.py | 59 + .../offline_user_data_job_failure_reason.py | 76 + .../offline_user_data_job_match_rate_range.py | 87 + .../types/offline_user_data_job_status.py | 73 + .../enums/types/offline_user_data_job_type.py | 64 + .../operating_system_version_operator_type.py | 56 + .../v24/enums/types/optimization_goal_type.py | 66 + .../v24/enums/types/parental_status_type.py | 61 + .../enums/types/partnership_opportunity.py | 79 + .../googleads/v24/enums/types/payment_mode.py | 74 + .../types/performance_max_upgrade_status.py | 66 + .../v24/enums/types/placement_type.py | 73 + .../v24/enums/types/policy_approval_status.py | 70 + .../v24/enums/types/policy_review_status.py | 69 + .../enums/types/policy_topic_entry_type.py | 76 + ..._evidence_destination_mismatch_url_type.py | 71 + ...evidence_destination_not_working_device.py | 63 + ..._destination_not_working_dns_error_type.py | 64 + .../enums/types/positive_geo_target_type.py | 67 + .../googleads/v24/enums/types/preview_type.py | 58 + .../types/price_extension_price_qualifier.py | 61 + .../enums/types/price_extension_price_unit.py | 67 + .../v24/enums/types/price_extension_type.py | 83 + .../v24/enums/types/product_availability.py | 58 + .../v24/enums/types/product_category_level.py | 64 + .../v24/enums/types/product_category_state.py | 56 + .../v24/enums/types/product_channel.py | 55 + .../types/product_channel_exclusivity.py | 59 + .../v24/enums/types/product_condition.py | 58 + .../types/product_custom_attribute_index.py | 67 + .../v24/enums/types/product_issue_severity.py | 57 + .../types/product_link_invitation_status.py | 80 + .../v24/enums/types/product_status.py | 63 + .../v24/enums/types/product_type_level.py | 64 + .../v24/enums/types/promotion_barcode_type.py | 101 + .../promotion_extension_discount_modifier.py | 55 + .../types/promotion_extension_occasion.py | 165 + .../v24/enums/types/proximity_radius_units.py | 55 + .../v24/enums/types/quality_score_bucket.py | 58 + .../v24/enums/types/reach_plan_age_range.py | 141 + .../enums/types/reach_plan_buying_method.py | 55 + .../types/reach_plan_conversion_rate_model.py | 68 + .../v24/enums/types/reach_plan_cost_model.py | 63 + .../types/reach_plan_marketing_objective.py | 69 + .../v24/enums/types/reach_plan_network.py | 59 + .../reach_plan_plannable_user_list_status.py | 58 + .../v24/enums/types/reach_plan_surface.py | 80 + .../recommendation_subscription_status.py | 63 + .../v24/enums/types/recommendation_type.py | 287 + .../v24/enums/types/regulatory_fee_type.py | 79 + .../enums/types/reservation_request_type.py | 62 + .../enums/types/resource_change_operation.py | 61 + .../v24/enums/types/resource_limit_type.py | 632 ++ .../v24/enums/types/response_content_type.py | 56 + .../types/search_engine_results_page_type.py | 61 + .../enums/types/search_term_match_source.py | 74 + .../v24/enums/types/search_term_match_type.py | 74 + .../types/search_term_targeting_status.py | 65 + .../enums/types/seasonality_event_scope.py | 69 + .../enums/types/seasonality_event_status.py | 60 + .../enums/types/served_asset_field_type.py | 170 + .../v24/enums/types/shared_set_status.py | 56 + .../v24/enums/types/shared_set_type.py | 79 + ...roducts_to_campaign_recommendation_enum.py | 70 + .../types/simulation_modification_method.py | 70 + .../v24/enums/types/simulation_type.py | 77 + .../types/sk_ad_network_ad_event_type.py | 58 + .../types/sk_ad_network_attribution_credit.py | 63 + .../sk_ad_network_coarse_conversion_value.py | 67 + .../enums/types/sk_ad_network_source_type.py | 59 + .../enums/types/sk_ad_network_user_type.py | 59 + google/ads/googleads/v24/enums/types/slot.py | 69 + .../smart_campaign_not_eligible_reason.py | 70 + .../v24/enums/types/smart_campaign_status.py | 73 + .../v24/enums/types/spending_limit_type.py | 53 + .../v24/enums/types/summary_row_setting.py | 61 + .../types/system_managed_entity_source.py | 55 + .../target_cpa_opt_in_recommendation_goal.py | 69 + .../enums/types/target_frequency_time_unit.py | 61 + .../types/target_impression_share_location.py | 62 + .../v24/enums/types/targeting_dimension.py | 84 + ...rd_party_brand_lift_integration_partner.py | 65 + ..._party_brand_safety_integration_partner.py | 62 + .../third_party_reach_integration_partner.py | 80 + ...d_party_viewability_integration_partner.py | 59 + .../googleads/v24/enums/types/time_type.py | 56 + .../enums/types/tracking_code_page_format.py | 59 + .../v24/enums/types/tracking_code_type.py | 73 + .../v24/enums/types/unit_of_measure.py | 85 + .../v24/enums/types/user_identifier_source.py | 62 + .../types/user_interest_taxonomy_type.py | 67 + .../enums/types/user_list_access_status.py | 55 + .../enums/types/user_list_closing_reason.py | 56 + .../types/user_list_crm_data_source_type.py | 64 + .../types/user_list_customer_type_category.py | 102 + .../user_list_date_rule_item_operator.py | 61 + .../types/user_list_flexible_rule_operator.py | 55 + .../types/user_list_logical_rule_operator.py | 58 + .../types/user_list_membership_status.py | 61 + .../user_list_number_rule_item_operator.py | 68 + .../types/user_list_prepopulation_status.py | 58 + .../v24/enums/types/user_list_rule_type.py | 55 + .../v24/enums/types/user_list_size_range.py | 111 + .../user_list_string_rule_item_operator.py | 74 + .../v24/enums/types/user_list_type.py | 78 + .../v24/enums/types/value_rule_device_type.py | 61 + .../value_rule_geo_location_match_type.py | 60 + .../v24/enums/types/value_rule_operation.py | 61 + .../types/value_rule_set_attachment_type.py | 58 + .../enums/types/value_rule_set_dimension.py | 68 + .../types/vanity_pharma_display_url_mode.py | 58 + .../v24/enums/types/vanity_pharma_text.py | 106 + .../types/vertical_ads_item_vertical_type.py | 71 + .../types/video_ad_format_restriction.py | 56 + .../video_ad_sequence_interaction_type.py | 75 + .../video_ad_sequence_minimum_duration.py | 66 + .../enums/types/video_enhancement_source.py | 59 + .../v24/enums/types/video_thumbnail.py | 66 + .../enums/types/webpage_condition_operand.py | 72 + .../enums/types/webpage_condition_operator.py | 60 + .../v24/enums/types/youtube_video_privacy.py | 57 + .../v24/enums/types/youtube_video_property.py | 57 + .../enums/types/youtube_video_upload_state.py | 79 + google/ads/googleads/v24/errors/__init__.py | 529 ++ .../googleads/v24/errors/services/__init__.py | 15 + .../googleads/v24/errors/types/__init__.py | 714 +++ .../errors/types/access_invitation_error.py | 83 + .../types/account_budget_proposal_error.py | 156 + .../v24/errors/types/account_link_error.py | 56 + .../v24/errors/types/action_error.py | 56 + .../v24/errors/types/ad_customizer_error.py | 66 + .../googleads/v24/errors/types/ad_error.py | 612 ++ .../v24/errors/types/ad_group_ad_error.py | 96 + .../types/ad_group_bid_modifier_error.py | 61 + .../ad_group_criterion_customizer_error.py | 57 + .../errors/types/ad_group_criterion_error.py | 166 + .../errors/types/ad_group_customizer_error.py | 52 + .../v24/errors/types/ad_group_error.py | 147 + .../v24/errors/types/ad_group_feed_error.py | 76 + .../v24/errors/types/ad_parameter_error.py | 56 + .../v24/errors/types/ad_sharing_error.py | 60 + .../googleads/v24/errors/types/adx_error.py | 53 + .../googleads/v24/errors/types/asset_error.py | 212 + .../errors/types/asset_generation_error.py | 188 + .../errors/types/asset_group_asset_error.py | 68 + .../v24/errors/types/asset_group_error.py | 109 + .../asset_group_listing_group_filter_error.py | 148 + .../errors/types/asset_group_signal_error.py | 70 + .../v24/errors/types/asset_link_error.py | 166 + .../v24/errors/types/asset_set_asset_error.py | 70 + .../v24/errors/types/asset_set_error.py | 95 + .../v24/errors/types/asset_set_link_error.py | 72 + .../v24/errors/types/audience_error.py | 90 + .../errors/types/audience_insights_error.py | 56 + .../v24/errors/types/authentication_error.py | 138 + .../v24/errors/types/authorization_error.py | 119 + ...tomatically_created_asset_removal_error.py | 69 + .../v24/errors/types/batch_job_error.py | 123 + .../v24/errors/types/benchmarks_error.py | 59 + .../v24/errors/types/bidding_error.py | 152 + .../errors/types/bidding_strategy_error.py | 72 + .../v24/errors/types/billing_setup_error.py | 135 + .../types/brand_guidelines_migration_error.py | 76 + .../v24/errors/types/campaign_budget_error.py | 135 + .../types/campaign_conversion_goal_error.py | 60 + .../errors/types/campaign_criterion_error.py | 172 + .../errors/types/campaign_customizer_error.py | 52 + .../v24/errors/types/campaign_draft_error.py | 91 + .../v24/errors/types/campaign_error.py | 481 ++ .../errors/types/campaign_experiment_error.py | 94 + .../v24/errors/types/campaign_feed_error.py | 79 + .../types/campaign_goal_config_error.py | 75 + .../types/campaign_lifecycle_goal_error.py | 123 + .../errors/types/campaign_shared_set_error.py | 56 + .../v24/errors/types/change_event_error.py | 70 + .../v24/errors/types/change_status_error.py | 69 + .../v24/errors/types/click_view_error.py | 55 + .../v24/errors/types/collection_size_error.py | 58 + .../types/content_creator_insights_error.py | 57 + .../v24/errors/types/context_error.py | 57 + .../errors/types/conversion_action_error.py | 99 + .../conversion_adjustment_upload_error.py | 184 + .../types/conversion_custom_variable_error.py | 64 + .../conversion_goal_campaign_config_error.py | 79 + .../errors/types/conversion_upload_error.py | 295 + .../types/conversion_value_rule_error.py | 115 + .../types/conversion_value_rule_set_error.py | 128 + .../v24/errors/types/country_code_error.py | 52 + .../v24/errors/types/criterion_error.py | 707 +++ .../v24/errors/types/currency_code_error.py | 52 + .../v24/errors/types/currency_error.py | 52 + .../v24/errors/types/custom_audience_error.py | 81 + .../types/custom_conversion_goal_error.py | 76 + .../v24/errors/types/custom_interest_error.py | 75 + .../types/customer_client_link_error.py | 89 + .../errors/types/customer_customizer_error.py | 52 + .../v24/errors/types/customer_error.py | 68 + .../v24/errors/types/customer_feed_error.py | 74 + .../types/customer_lifecycle_goal_error.py | 91 + .../types/customer_manager_link_error.py | 88 + ...d_network_conversion_value_schema_error.py | 75 + .../types/customer_user_access_error.py | 73 + .../types/customizer_attribute_error.py | 56 + .../v24/errors/types/data_link_error.py | 74 + .../v24/errors/types/database_error.py | 62 + .../googleads/v24/errors/types/date_error.py | 93 + .../v24/errors/types/date_range_error.py | 66 + .../v24/errors/types/distinct_error.py | 55 + .../googleads/v24/errors/types/enum_error.py | 52 + .../ads/googleads/v24/errors/types/errors.py | 3014 ++++++++++ .../v24/errors/types/experiment_arm_error.py | 105 + .../v24/errors/types/experiment_error.py | 172 + .../errors/types/extension_feed_item_error.py | 223 + .../errors/types/extension_setting_error.py | 307 + .../types/feed_attribute_reference_error.py | 62 + .../googleads/v24/errors/types/feed_error.py | 135 + .../v24/errors/types/feed_item_error.py | 84 + .../v24/errors/types/feed_item_set_error.py | 81 + .../errors/types/feed_item_set_link_error.py | 60 + .../errors/types/feed_item_target_error.py | 82 + .../types/feed_item_validation_error.py | 420 ++ .../v24/errors/types/feed_mapping_error.py | 119 + .../googleads/v24/errors/types/field_error.py | 76 + .../v24/errors/types/field_mask_error.py | 67 + .../final_url_expansion_asset_view_error.py | 82 + .../v24/errors/types/function_error.py | 103 + .../errors/types/function_parsing_error.py | 86 + .../geo_target_constant_suggestion_error.py | 68 + .../googleads/v24/errors/types/goal_error.py | 66 + .../v24/errors/types/header_error.py | 56 + .../googleads/v24/errors/types/id_error.py | 52 + .../types/identity_verification_error.py | 62 + .../googleads/v24/errors/types/image_error.py | 174 + .../v24/errors/types/incentive_error.py | 62 + .../v24/errors/types/internal_error.py | 66 + .../v24/errors/types/invoice_error.py | 69 + .../types/keyword_plan_ad_group_error.py | 63 + .../keyword_plan_ad_group_keyword_error.py | 83 + .../types/keyword_plan_campaign_error.py | 79 + .../keyword_plan_campaign_keyword_error.py | 56 + .../v24/errors/types/keyword_plan_error.py | 101 + .../errors/types/keyword_plan_idea_error.py | 58 + .../googleads/v24/errors/types/label_error.py | 82 + .../v24/errors/types/language_code_error.py | 55 + .../v24/errors/types/list_operation_error.py | 56 + .../v24/errors/types/manager_link_error.py | 120 + .../v24/errors/types/media_bundle_error.py | 124 + .../v24/errors/types/media_file_error.py | 127 + .../v24/errors/types/media_upload_error.py | 176 + .../v24/errors/types/merchant_center_error.py | 60 + .../v24/errors/types/multiplier_error.py | 91 + .../v24/errors/types/mutate_error.py | 85 + .../types/new_resource_creation_error.py | 65 + .../v24/errors/types/not_allowlisted_error.py | 56 + .../v24/errors/types/not_empty_error.py | 52 + .../googleads/v24/errors/types/null_error.py | 53 + .../types/offline_user_data_job_error.py | 211 + .../types/operation_access_denied_error.py | 91 + .../v24/errors/types/operator_error.py | 52 + .../v24/errors/types/partial_failure_error.py | 57 + .../errors/types/payments_account_error.py | 56 + .../v24/errors/types/policy_finding_error.py | 57 + .../policy_validation_parameter_error.py | 67 + .../errors/types/policy_violation_error.py | 56 + .../v24/errors/types/product_link_error.py | 65 + .../types/product_link_invitation_error.py | 73 + .../googleads/v24/errors/types/query_error.py | 268 + .../googleads/v24/errors/types/quota_error.py | 81 + .../googleads/v24/errors/types/range_error.py | 55 + .../v24/errors/types/reach_plan_error.py | 63 + .../v24/errors/types/recommendation_error.py | 213 + .../recommendation_subscription_error.py | 52 + .../v24/errors/types/region_code_error.py | 52 + .../v24/errors/types/request_error.py | 153 + .../types/resource_access_denied_error.py | 55 + .../resource_count_limit_exceeded_error.py | 114 + .../errors/types/search_term_insight_error.py | 76 + .../v24/errors/types/setting_error.py | 111 + .../errors/types/shareable_preview_error.py | 60 + .../errors/types/shared_criterion_error.py | 56 + .../v24/errors/types/shared_set_error.py | 63 + .../errors/types/shopping_product_error.py | 61 + .../v24/errors/types/size_limit_error.py | 60 + .../v24/errors/types/smart_campaign_error.py | 74 + .../v24/errors/types/string_format_error.py | 57 + .../v24/errors/types/string_length_error.py | 59 + .../third_party_app_analytics_link_error.py | 68 + .../v24/errors/types/time_zone_error.py | 52 + .../v24/errors/types/url_field_error.py | 254 + .../v24/errors/types/user_data_error.py | 62 + .../types/user_list_customer_type_error.py | 87 + .../v24/errors/types/user_list_error.py | 213 + .../v24/errors/types/video_campaign_error.py | 54 + .../errors/types/video_reservation_error.py | 195 + .../types/youtube_video_registration_error.py | 63 + google/ads/googleads/v24/gapic_metadata.json | 3263 +++++++++++ google/ads/googleads/v24/gapic_version.py | 16 + google/ads/googleads/v24/py.typed | 2 + .../ads/googleads/v24/resources/__init__.py | 677 +++ .../v24/resources/services/__init__.py | 15 + .../googleads/v24/resources/types/__init__.py | 880 +++ .../types/accessible_bidding_strategy.py | 344 ++ .../v24/resources/types/account_budget.py | 465 ++ .../types/account_budget_proposal.py | 292 + .../v24/resources/types/account_link.py | 154 + .../ads/googleads/v24/resources/types/ad.py | 489 ++ .../googleads/v24/resources/types/ad_group.py | 739 +++ .../v24/resources/types/ad_group_ad.py | 260 + .../ad_group_ad_asset_combination_view.py | 82 + .../resources/types/ad_group_ad_asset_view.py | 193 + .../v24/resources/types/ad_group_ad_label.py | 69 + .../v24/resources/types/ad_group_asset.py | 135 + .../v24/resources/types/ad_group_asset_set.py | 76 + .../resources/types/ad_group_audience_view.py | 51 + .../resources/types/ad_group_bid_modifier.py | 184 + .../v24/resources/types/ad_group_criterion.py | 807 +++ .../types/ad_group_criterion_customizer.py | 94 + .../types/ad_group_criterion_label.py | 70 + .../types/ad_group_criterion_simulation.py | 149 + .../resources/types/ad_group_customizer.py | 86 + .../v24/resources/types/ad_group_label.py | 69 + .../resources/types/ad_group_simulation.py | 170 + .../v24/resources/types/ad_parameter.py | 103 + .../v24/resources/types/ad_schedule_view.py | 49 + .../v24/resources/types/age_range_view.py | 48 + .../ai_max_search_term_ad_combination_view.py | 92 + ...roid_privacy_shared_key_google_ad_group.py | 109 + ...roid_privacy_shared_key_google_campaign.py | 89 + ..._privacy_shared_key_google_network_type.py | 104 + .../types/app_top_combination_view.py | 78 + .../v24/resources/types/applied_incentive.py | 186 + .../googleads/v24/resources/types/asset.py | 570 ++ .../resources/types/asset_field_type_view.py | 62 + .../v24/resources/types/asset_group.py | 263 + .../v24/resources/types/asset_group_asset.py | 148 + .../types/asset_group_listing_group_filter.py | 504 ++ .../types/asset_group_product_group_view.py | 63 + .../v24/resources/types/asset_group_signal.py | 121 + .../types/asset_group_top_combination_view.py | 79 + .../v24/resources/types/asset_set.py | 282 + .../v24/resources/types/asset_set_asset.py | 75 + .../resources/types/asset_set_type_view.py | 65 + .../googleads/v24/resources/types/audience.py | 132 + .../v24/resources/types/batch_job.py | 192 + .../resources/types/bidding_data_exclusion.py | 156 + .../types/bidding_seasonality_adjustment.py | 165 + .../v24/resources/types/bidding_strategy.py | 260 + .../types/bidding_strategy_simulation.py | 130 + .../v24/resources/types/billing_setup.py | 224 + .../v24/resources/types/call_view.py | 115 + .../googleads/v24/resources/types/campaign.py | 2113 +++++++ .../types/campaign_aggregate_asset_view.py | 99 + .../v24/resources/types/campaign_asset.py | 143 + .../v24/resources/types/campaign_asset_set.py | 76 + .../resources/types/campaign_audience_view.py | 53 + .../resources/types/campaign_bid_modifier.py | 96 + .../v24/resources/types/campaign_budget.py | 295 + .../types/campaign_conversion_goal.py | 86 + .../v24/resources/types/campaign_criterion.py | 490 ++ .../resources/types/campaign_customizer.py | 86 + .../v24/resources/types/campaign_draft.py | 137 + .../resources/types/campaign_goal_config.py | 88 + .../v24/resources/types/campaign_group.py | 81 + .../v24/resources/types/campaign_label.py | 69 + .../types/campaign_lifecycle_goal.py | 100 + .../types/campaign_search_term_insight.py | 85 + .../types/campaign_search_term_view.py | 74 + .../resources/types/campaign_shared_set.py | 91 + .../resources/types/campaign_simulation.py | 177 + .../v24/resources/types/carrier_constant.py | 80 + .../resources/types/cart_data_sales_view.py | 56 + .../v24/resources/types/change_event.py | 315 + .../v24/resources/types/change_status.py | 223 + .../types/channel_aggregate_asset_view.py | 105 + .../v24/resources/types/click_view.py | 144 + .../v24/resources/types/combined_audience.py | 83 + .../resources/types/content_criterion_view.py | 48 + .../v24/resources/types/conversion_action.py | 456 ++ .../types/conversion_custom_variable.py | 104 + .../types/conversion_goal_campaign_config.py | 77 + .../resources/types/conversion_value_rule.py | 359 ++ .../types/conversion_value_rule_set.py | 137 + .../v24/resources/types/currency_constant.py | 91 + .../v24/resources/types/custom_audience.py | 182 + .../resources/types/custom_conversion_goal.py | 81 + .../v24/resources/types/custom_interest.py | 151 + .../googleads/v24/resources/types/customer.py | 648 +++ .../v24/resources/types/customer_asset.py | 128 + .../v24/resources/types/customer_asset_set.py | 76 + .../v24/resources/types/customer_client.py | 168 + .../resources/types/customer_client_link.py | 92 + .../types/customer_conversion_goal.py | 83 + .../resources/types/customer_customizer.py | 79 + .../v24/resources/types/customer_label.py | 78 + .../types/customer_lifecycle_goal.py | 67 + .../resources/types/customer_manager_link.py | 81 + .../types/customer_negative_criterion.py | 168 + .../types/customer_search_term_insight.py | 76 + ...r_sk_ad_network_conversion_value_schema.py | 374 ++ .../resources/types/customer_user_access.py | 100 + .../types/customer_user_access_invitation.py | 92 + .../resources/types/customizer_attribute.py | 92 + .../v24/resources/types/data_link.py | 135 + ...tail_content_suitability_placement_view.py | 88 + .../resources/types/detail_placement_view.py | 117 + .../resources/types/detailed_demographic.py | 92 + .../resources/types/display_keyword_view.py | 64 + .../v24/resources/types/distance_view.py | 79 + .../v24/resources/types/domain_category.py | 146 + .../dynamic_search_ads_search_term_view.py | 128 + .../types/expanded_landing_page_view.py | 63 + .../v24/resources/types/experiment.py | 190 + .../v24/resources/types/experiment_arm.py | 97 + .../types/final_url_expansion_asset_view.py | 122 + .../v24/resources/types/gender_view.py | 51 + .../resources/types/geo_target_constant.py | 123 + .../v24/resources/types/geographic_view.py | 78 + .../ads/googleads/v24/resources/types/goal.py | 101 + .../v24/resources/types/google_ads_field.py | 183 + ...roup_content_suitability_placement_view.py | 88 + .../resources/types/group_placement_view.py | 97 + .../v24/resources/types/hotel_group_view.py | 48 + .../resources/types/hotel_performance_view.py | 48 + .../resources/types/hotel_reconciliation.py | 154 + .../v24/resources/types/income_range_view.py | 48 + .../googleads/v24/resources/types/invoice.py | 929 +++ .../v24/resources/types/keyword_plan.py | 129 + .../resources/types/keyword_plan_ad_group.py | 96 + .../types/keyword_plan_ad_group_keyword.py | 116 + .../resources/types/keyword_plan_campaign.py | 150 + .../types/keyword_plan_campaign_keyword.py | 104 + .../resources/types/keyword_theme_constant.py | 85 + .../v24/resources/types/keyword_view.py | 48 + .../googleads/v24/resources/types/label.py | 90 + .../v24/resources/types/landing_page_view.py | 62 + .../v24/resources/types/language_constant.py | 90 + .../types/lead_form_submission_data.py | 169 + .../v24/resources/types/life_event.py | 91 + .../types/local_services_employee.py | 308 + .../resources/types/local_services_lead.py | 252 + .../types/local_services_lead_conversation.py | 175 + .../local_services_verification_artifact.py | 476 ++ .../resources/types/location_interest_view.py | 49 + .../v24/resources/types/location_view.py | 51 + .../resources/types/managed_placement_view.py | 48 + .../types/matched_location_interest_view.py | 53 + .../v24/resources/types/media_file.py | 307 + .../types/mobile_app_category_constant.py | 70 + .../resources/types/mobile_device_constant.py | 101 + ...ffline_conversion_upload_client_summary.py | 383 ++ ...ersion_upload_conversion_action_summary.py | 154 + .../resources/types/offline_user_data_job.py | 170 + .../operating_system_version_constant.py | 106 + .../types/paid_organic_search_term_view.py | 62 + .../resources/types/parental_status_view.py | 48 + .../v24/resources/types/payments_account.py | 116 + .../v24/resources/types/per_store_view.py | 111 + .../types/performance_max_placement_view.py | 102 + .../types/product_category_constant.py | 130 + .../v24/resources/types/product_group_view.py | 48 + .../v24/resources/types/product_link.py | 253 + .../types/product_link_invitation.py | 218 + .../resources/types/qualifying_question.py | 67 + .../v24/resources/types/recommendation.py | 2101 +++++++ .../types/recommendation_subscription.py | 103 + .../v24/resources/types/remarketing_action.py | 86 + .../v24/resources/types/search_term_view.py | 86 + .../v24/resources/types/shared_criterion.py | 198 + .../v24/resources/types/shared_set.py | 134 + .../types/shopping_performance_view.py | 67 + .../v24/resources/types/shopping_product.py | 533 ++ .../types/smart_campaign_search_term_view.py | 62 + .../resources/types/smart_campaign_setting.py | 180 + .../types/targeting_expansion_view.py | 49 + .../types/third_party_app_analytics_link.py | 66 + .../v24/resources/types/topic_constant.py | 85 + .../v24/resources/types/topic_view.py | 48 + .../types/travel_activity_group_view.py | 49 + .../types/travel_activity_performance_view.py | 49 + .../v24/resources/types/user_interest.py | 115 + .../v24/resources/types/user_list.py | 357 ++ .../types/user_list_customer_type.py | 69 + .../v24/resources/types/user_location_view.py | 76 + .../googleads/v24/resources/types/video.py | 94 + .../v24/resources/types/video_enhancement.py | 81 + .../v24/resources/types/webpage_view.py | 48 + .../resources/types/youtube_video_upload.py | 118 + google/ads/googleads/v24/services/__init__.py | 1486 +++++ .../v24/services/services/__init__.py | 15 + .../__init__.py | 22 + .../async_client.py | 458 ++ .../account_budget_proposal_service/client.py | 965 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 177 + .../transports/grpc.py | 404 ++ .../transports/grpc_asyncio.py | 427 ++ .../services/account_link_service/__init__.py | 22 + .../account_link_service/async_client.py | 532 ++ .../services/account_link_service/client.py | 987 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../account_link_service/transports/base.py | 190 + .../account_link_service/transports/grpc.py | 428 ++ .../transports/grpc_asyncio.py | 454 ++ .../ad_group_ad_label_service/__init__.py | 22 + .../ad_group_ad_label_service/async_client.py | 436 ++ .../ad_group_ad_label_service/client.py | 949 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../transports/base.py | 173 + .../transports/grpc.py | 390 ++ .../transports/grpc_asyncio.py | 411 ++ .../services/ad_group_ad_service/__init__.py | 22 + .../ad_group_ad_service/async_client.py | 554 ++ .../services/ad_group_ad_service/client.py | 1093 ++++ .../ad_group_ad_service/transports/README.rst | 9 + .../transports/__init__.py | 34 + .../ad_group_ad_service/transports/base.py | 188 + .../ad_group_ad_service/transports/grpc.py | 443 ++ .../transports/grpc_asyncio.py | 469 ++ .../ad_group_asset_service/__init__.py | 22 + .../ad_group_asset_service/async_client.py | 431 ++ .../services/ad_group_asset_service/client.py | 936 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../ad_group_asset_service/transports/base.py | 173 + .../ad_group_asset_service/transports/grpc.py | 390 ++ .../transports/grpc_asyncio.py | 411 ++ .../ad_group_asset_set_service/__init__.py | 22 + .../async_client.py | 435 ++ .../ad_group_asset_set_service/client.py | 945 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../transports/base.py | 175 + .../transports/grpc.py | 384 ++ .../transports/grpc_asyncio.py | 407 ++ .../ad_group_bid_modifier_service/__init__.py | 22 + .../async_client.py | 451 ++ .../ad_group_bid_modifier_service/client.py | 949 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 177 + .../transports/grpc.py | 399 ++ .../transports/grpc_asyncio.py | 422 ++ .../__init__.py | 22 + .../async_client.py | 455 ++ .../client.py | 972 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 179 + .../transports/grpc.py | 394 ++ .../transports/grpc_asyncio.py | 417 ++ .../__init__.py | 22 + .../async_client.py | 449 ++ .../client.py | 969 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 177 + .../transports/grpc.py | 394 ++ .../transports/grpc_asyncio.py | 417 ++ .../ad_group_criterion_service/__init__.py | 22 + .../async_client.py | 469 ++ .../ad_group_criterion_service/client.py | 1018 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 173 + .../transports/grpc.py | 400 ++ .../transports/grpc_asyncio.py | 423 ++ .../ad_group_customizer_service/__init__.py | 22 + .../async_client.py | 442 ++ .../ad_group_customizer_service/client.py | 952 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 384 ++ .../transports/grpc_asyncio.py | 407 ++ .../ad_group_label_service/__init__.py | 22 + .../ad_group_label_service/async_client.py | 430 ++ .../services/ad_group_label_service/client.py | 933 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../ad_group_label_service/transports/base.py | 173 + .../ad_group_label_service/transports/grpc.py | 390 ++ .../transports/grpc_asyncio.py | 411 ++ .../services/ad_group_service/__init__.py | 22 + .../services/ad_group_service/async_client.py | 427 ++ .../services/ad_group_service/client.py | 933 +++ .../ad_group_service/transports/README.rst | 9 + .../ad_group_service/transports/__init__.py | 34 + .../ad_group_service/transports/base.py | 173 + .../ad_group_service/transports/grpc.py | 397 ++ .../transports/grpc_asyncio.py | 418 ++ .../services/ad_parameter_service/__init__.py | 22 + .../ad_parameter_service/async_client.py | 428 ++ .../services/ad_parameter_service/client.py | 914 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../ad_parameter_service/transports/base.py | 173 + .../ad_parameter_service/transports/grpc.py | 390 ++ .../transports/grpc_asyncio.py | 411 ++ .../services/services/ad_service/__init__.py | 22 + .../services/ad_service/async_client.py | 412 ++ .../services/services/ad_service/client.py | 880 +++ .../services/ad_service/transports/README.rst | 9 + .../ad_service/transports/__init__.py | 32 + .../services/ad_service/transports/base.py | 173 + .../services/ad_service/transports/grpc.py | 397 ++ .../ad_service/transports/grpc_asyncio.py | 420 ++ .../asset_generation_service/__init__.py | 22 + .../asset_generation_service/async_client.py | 466 ++ .../asset_generation_service/client.py | 947 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../transports/base.py | 190 + .../transports/grpc.py | 422 ++ .../transports/grpc_asyncio.py | 450 ++ .../asset_group_asset_service/__init__.py | 22 + .../asset_group_asset_service/async_client.py | 435 ++ .../asset_group_asset_service/client.py | 944 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../transports/base.py | 173 + .../transports/grpc.py | 384 ++ .../transports/grpc_asyncio.py | 407 ++ .../__init__.py | 22 + .../async_client.py | 458 ++ .../client.py | 973 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 38 + .../transports/base.py | 179 + .../transports/grpc.py | 394 ++ .../transports/grpc_asyncio.py | 417 ++ .../services/asset_group_service/__init__.py | 22 + .../asset_group_service/async_client.py | 420 ++ .../services/asset_group_service/client.py | 902 +++ .../asset_group_service/transports/README.rst | 9 + .../transports/__init__.py | 34 + .../asset_group_service/transports/base.py | 173 + .../asset_group_service/transports/grpc.py | 384 ++ .../transports/grpc_asyncio.py | 405 ++ .../asset_group_signal_service/__init__.py | 22 + .../async_client.py | 435 ++ .../asset_group_signal_service/client.py | 929 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 384 ++ .../transports/grpc_asyncio.py | 407 ++ .../services/asset_service/__init__.py | 22 + .../services/asset_service/async_client.py | 421 ++ .../services/services/asset_service/client.py | 904 +++ .../asset_service/transports/README.rst | 9 + .../asset_service/transports/__init__.py | 34 + .../services/asset_service/transports/base.py | 173 + .../services/asset_service/transports/grpc.py | 395 ++ .../asset_service/transports/grpc_asyncio.py | 417 ++ .../asset_set_asset_service/__init__.py | 22 + .../asset_set_asset_service/async_client.py | 427 ++ .../asset_set_asset_service/client.py | 936 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../transports/base.py | 173 + .../transports/grpc.py | 384 ++ .../transports/grpc_asyncio.py | 405 ++ .../services/asset_set_service/__init__.py | 22 + .../asset_set_service/async_client.py | 412 ++ .../services/asset_set_service/client.py | 880 +++ .../asset_set_service/transports/README.rst | 9 + .../asset_set_service/transports/__init__.py | 34 + .../asset_set_service/transports/base.py | 173 + .../asset_set_service/transports/grpc.py | 382 ++ .../transports/grpc_asyncio.py | 403 ++ .../audience_insights_service/__init__.py | 22 + .../audience_insights_service/async_client.py | 1247 ++++ .../audience_insights_service/client.py | 1706 ++++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 308 + .../transports/grpc.py | 660 +++ .../transports/grpc_asyncio.py | 730 +++ .../services/audience_service/__init__.py | 22 + .../services/audience_service/async_client.py | 427 ++ .../services/audience_service/client.py | 939 +++ .../audience_service/transports/README.rst | 9 + .../audience_service/transports/__init__.py | 34 + .../audience_service/transports/base.py | 173 + .../audience_service/transports/grpc.py | 383 ++ .../transports/grpc_asyncio.py | 404 ++ .../__init__.py | 22 + .../async_client.py | 453 ++ .../client.py | 924 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 40 + .../transports/base.py | 179 + .../transports/grpc.py | 398 ++ .../transports/grpc_asyncio.py | 421 ++ .../services/batch_job_service/__init__.py | 22 + .../batch_job_service/async_client.py | 1192 ++++ .../services/batch_job_service/client.py | 2785 +++++++++ .../services/batch_job_service/pagers.py | 199 + .../batch_job_service/transports/README.rst | 9 + .../batch_job_service/transports/__init__.py | 34 + .../batch_job_service/transports/base.py | 227 + .../batch_job_service/transports/grpc.py | 516 ++ .../transports/grpc_asyncio.py | 555 ++ .../services/benchmarks_service/__init__.py | 22 + .../benchmarks_service/async_client.py | 733 +++ .../services/benchmarks_service/client.py | 1182 ++++ .../benchmarks_service/transports/README.rst | 9 + .../benchmarks_service/transports/__init__.py | 34 + .../benchmarks_service/transports/base.py | 241 + .../benchmarks_service/transports/grpc.py | 534 ++ .../transports/grpc_asyncio.py | 575 ++ .../__init__.py | 22 + .../async_client.py | 439 ++ .../bidding_data_exclusion_service/client.py | 936 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 177 + .../transports/grpc.py | 388 ++ .../transports/grpc_asyncio.py | 411 ++ .../__init__.py | 22 + .../async_client.py | 451 ++ .../client.py | 948 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 38 + .../transports/base.py | 179 + .../transports/grpc.py | 394 ++ .../transports/grpc_asyncio.py | 417 ++ .../bidding_strategy_service/__init__.py | 22 + .../bidding_strategy_service/async_client.py | 438 ++ .../bidding_strategy_service/client.py | 914 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../transports/base.py | 173 + .../transports/grpc.py | 397 ++ .../transports/grpc_asyncio.py | 420 ++ .../billing_setup_service/__init__.py | 22 + .../billing_setup_service/async_client.py | 435 ++ .../services/billing_setup_service/client.py | 909 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../billing_setup_service/transports/base.py | 173 + .../billing_setup_service/transports/grpc.py | 399 ++ .../transports/grpc_asyncio.py | 420 ++ .../brand_suggestion_service/__init__.py | 22 + .../brand_suggestion_service/async_client.py | 411 ++ .../brand_suggestion_service/client.py | 861 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../transports/base.py | 173 + .../transports/grpc.py | 382 ++ .../transports/grpc_asyncio.py | 405 ++ .../campaign_asset_service/__init__.py | 22 + .../campaign_asset_service/async_client.py | 433 ++ .../services/campaign_asset_service/client.py | 944 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../campaign_asset_service/transports/base.py | 173 + .../campaign_asset_service/transports/grpc.py | 390 ++ .../transports/grpc_asyncio.py | 411 ++ .../campaign_asset_set_service/__init__.py | 22 + .../async_client.py | 437 ++ .../campaign_asset_set_service/client.py | 949 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 384 ++ .../transports/grpc_asyncio.py | 407 ++ .../campaign_bid_modifier_service/__init__.py | 22 + .../async_client.py | 451 ++ .../campaign_bid_modifier_service/client.py | 952 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 177 + .../transports/grpc.py | 398 ++ .../transports/grpc_asyncio.py | 421 ++ .../campaign_budget_service/__init__.py | 22 + .../campaign_budget_service/async_client.py | 430 ++ .../campaign_budget_service/client.py | 906 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../transports/base.py | 173 + .../transports/grpc.py | 393 ++ .../transports/grpc_asyncio.py | 414 ++ .../__init__.py | 22 + .../async_client.py | 442 ++ .../client.py | 943 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 177 + .../transports/grpc.py | 389 ++ .../transports/grpc_asyncio.py | 412 ++ .../campaign_criterion_service/__init__.py | 22 + .../async_client.py | 487 ++ .../campaign_criterion_service/client.py | 1063 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 398 ++ .../transports/grpc_asyncio.py | 421 ++ .../campaign_customizer_service/__init__.py | 22 + .../async_client.py | 445 ++ .../campaign_customizer_service/client.py | 957 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 386 ++ .../transports/grpc_asyncio.py | 409 ++ .../campaign_draft_service/__init__.py | 22 + .../campaign_draft_service/async_client.py | 681 +++ .../services/campaign_draft_service/client.py | 1171 ++++ .../services/campaign_draft_service/pagers.py | 213 + .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../campaign_draft_service/transports/base.py | 212 + .../campaign_draft_service/transports/grpc.py | 493 ++ .../transports/grpc_asyncio.py | 526 ++ .../campaign_goal_config_service/__init__.py | 22 + .../async_client.py | 446 ++ .../campaign_goal_config_service/client.py | 960 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 390 ++ .../transports/grpc_asyncio.py | 413 ++ .../campaign_group_service/__init__.py | 22 + .../campaign_group_service/async_client.py | 421 ++ .../services/campaign_group_service/client.py | 897 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../campaign_group_service/transports/base.py | 173 + .../campaign_group_service/transports/grpc.py | 384 ++ .../transports/grpc_asyncio.py | 405 ++ .../campaign_label_service/__init__.py | 22 + .../campaign_label_service/async_client.py | 433 ++ .../services/campaign_label_service/client.py | 942 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../campaign_label_service/transports/base.py | 173 + .../campaign_label_service/transports/grpc.py | 390 ++ .../transports/grpc_asyncio.py | 411 ++ .../__init__.py | 22 + .../async_client.py | 442 ++ .../campaign_lifecycle_goal_service/client.py | 931 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 179 + .../transports/grpc.py | 395 ++ .../transports/grpc_asyncio.py | 418 ++ .../services/campaign_service/__init__.py | 22 + .../services/campaign_service/async_client.py | 579 ++ .../services/campaign_service/client.py | 1148 ++++ .../campaign_service/transports/README.rst | 9 + .../campaign_service/transports/__init__.py | 34 + .../campaign_service/transports/base.py | 190 + .../campaign_service/transports/grpc.py | 437 ++ .../transports/grpc_asyncio.py | 463 ++ .../campaign_shared_set_service/__init__.py | 22 + .../async_client.py | 452 ++ .../campaign_shared_set_service/client.py | 962 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 394 ++ .../transports/grpc_asyncio.py | 417 ++ .../__init__.py | 22 + .../async_client.py | 477 ++ .../client.py | 937 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 196 + .../transports/grpc.py | 432 ++ .../transports/grpc_asyncio.py | 462 ++ .../conversion_action_service/__init__.py | 22 + .../conversion_action_service/async_client.py | 439 ++ .../conversion_action_service/client.py | 928 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 392 ++ .../transports/grpc_asyncio.py | 415 ++ .../__init__.py | 22 + .../async_client.py | 462 ++ .../client.py | 931 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 179 + .../transports/grpc.py | 397 ++ .../transports/grpc_asyncio.py | 420 ++ .../__init__.py | 22 + .../async_client.py | 450 ++ .../client.py | 944 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 179 + .../transports/grpc.py | 396 ++ .../transports/grpc_asyncio.py | 419 ++ .../__init__.py | 22 + .../async_client.py | 456 ++ .../client.py | 967 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 38 + .../transports/base.py | 179 + .../transports/grpc.py | 394 ++ .../transports/grpc_asyncio.py | 417 ++ .../conversion_upload_service/__init__.py | 22 + .../conversion_upload_service/async_client.py | 570 ++ .../conversion_upload_service/client.py | 1047 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 190 + .../transports/grpc.py | 424 ++ .../transports/grpc_asyncio.py | 452 ++ .../conversion_value_rule_service/__init__.py | 22 + .../async_client.py | 459 ++ .../conversion_value_rule_service/client.py | 992 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 177 + .../transports/grpc.py | 388 ++ .../transports/grpc_asyncio.py | 411 ++ .../__init__.py | 22 + .../async_client.py | 457 ++ .../client.py | 977 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 179 + .../transports/grpc.py | 391 ++ .../transports/grpc_asyncio.py | 414 ++ .../custom_audience_service/__init__.py | 22 + .../custom_audience_service/async_client.py | 428 ++ .../custom_audience_service/client.py | 904 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../transports/base.py | 173 + .../transports/grpc.py | 392 ++ .../transports/grpc_asyncio.py | 413 ++ .../__init__.py | 22 + .../async_client.py | 440 ++ .../custom_conversion_goal_service/client.py | 937 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 177 + .../transports/grpc.py | 388 ++ .../transports/grpc_asyncio.py | 411 ++ .../custom_interest_service/__init__.py | 22 + .../custom_interest_service/async_client.py | 427 ++ .../custom_interest_service/client.py | 903 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../transports/base.py | 173 + .../transports/grpc.py | 391 ++ .../transports/grpc_asyncio.py | 412 ++ .../customer_asset_service/__init__.py | 22 + .../customer_asset_service/async_client.py | 428 ++ .../services/customer_asset_service/client.py | 921 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../customer_asset_service/transports/base.py | 173 + .../customer_asset_service/transports/grpc.py | 389 ++ .../transports/grpc_asyncio.py | 410 ++ .../customer_asset_set_service/__init__.py | 22 + .../async_client.py | 437 ++ .../customer_asset_set_service/client.py | 944 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 384 ++ .../transports/grpc_asyncio.py | 407 ++ .../customer_client_link_service/__init__.py | 22 + .../async_client.py | 441 ++ .../customer_client_link_service/client.py | 924 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 393 ++ .../transports/grpc_asyncio.py | 416 ++ .../__init__.py | 22 + .../async_client.py | 436 ++ .../client.py | 921 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 177 + .../transports/grpc.py | 389 ++ .../transports/grpc_asyncio.py | 412 ++ .../customer_customizer_service/__init__.py | 22 + .../async_client.py | 441 ++ .../customer_customizer_service/client.py | 935 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 386 ++ .../transports/grpc_asyncio.py | 409 ++ .../customer_label_service/__init__.py | 22 + .../customer_label_service/async_client.py | 443 ++ .../services/customer_label_service/client.py | 945 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../customer_label_service/transports/base.py | 173 + .../customer_label_service/transports/grpc.py | 393 ++ .../transports/grpc_asyncio.py | 414 ++ .../__init__.py | 22 + .../async_client.py | 442 ++ .../customer_lifecycle_goal_service/client.py | 923 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 179 + .../transports/grpc.py | 395 ++ .../transports/grpc_asyncio.py | 418 ++ .../customer_manager_link_service/__init__.py | 22 + .../async_client.py | 576 ++ .../customer_manager_link_service/client.py | 1071 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 194 + .../transports/grpc.py | 432 ++ .../transports/grpc_asyncio.py | 460 ++ .../__init__.py | 22 + .../async_client.py | 448 ++ .../client.py | 945 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 179 + .../transports/grpc.py | 396 ++ .../transports/grpc_asyncio.py | 419 ++ .../services/customer_service/__init__.py | 22 + .../services/customer_service/async_client.py | 590 ++ .../services/customer_service/client.py | 1054 ++++ .../customer_service/transports/README.rst | 9 + .../customer_service/transports/__init__.py | 34 + .../customer_service/transports/base.py | 207 + .../customer_service/transports/grpc.py | 460 ++ .../transports/grpc_asyncio.py | 491 ++ .../__init__.py | 24 + .../async_client.py | 412 ++ .../client.py | 895 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 40 + .../transports/base.py | 179 + .../transports/grpc.py | 402 ++ .../transports/grpc_asyncio.py | 427 ++ .../__init__.py | 22 + .../async_client.py | 447 ++ .../client.py | 920 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 38 + .../transports/base.py | 179 + .../transports/grpc.py | 399 ++ .../transports/grpc_asyncio.py | 422 ++ .../customer_user_access_service/__init__.py | 22 + .../async_client.py | 437 ++ .../customer_user_access_service/client.py | 907 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 392 ++ .../transports/grpc_asyncio.py | 415 ++ .../customizer_attribute_service/__init__.py | 22 + .../async_client.py | 435 ++ .../customizer_attribute_service/client.py | 918 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 386 ++ .../transports/grpc_asyncio.py | 409 ++ .../services/data_link_service/__init__.py | 22 + .../data_link_service/async_client.py | 645 +++ .../services/data_link_service/client.py | 1097 ++++ .../data_link_service/transports/README.rst | 9 + .../data_link_service/transports/__init__.py | 34 + .../data_link_service/transports/base.py | 207 + .../data_link_service/transports/grpc.py | 461 ++ .../transports/grpc_asyncio.py | 492 ++ .../experiment_arm_service/__init__.py | 22 + .../experiment_arm_service/async_client.py | 433 ++ .../services/experiment_arm_service/client.py | 941 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../experiment_arm_service/transports/base.py | 173 + .../experiment_arm_service/transports/grpc.py | 389 ++ .../transports/grpc_asyncio.py | 410 ++ .../services/experiment_service/__init__.py | 22 + .../experiment_service/async_client.py | 977 ++++ .../services/experiment_service/client.py | 1466 +++++ .../services/experiment_service/pagers.py | 208 + .../experiment_service/transports/README.rst | 9 + .../experiment_service/transports/__init__.py | 34 + .../experiment_service/transports/base.py | 253 + .../experiment_service/transports/grpc.py | 601 ++ .../transports/grpc_asyncio.py | 654 +++ .../geo_target_constant_service/__init__.py | 22 + .../async_client.py | 388 ++ .../geo_target_constant_service/client.py | 852 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 389 ++ .../transports/grpc_asyncio.py | 414 ++ .../services/goal_service/__init__.py | 22 + .../services/goal_service/async_client.py | 404 ++ .../services/services/goal_service/client.py | 886 +++ .../goal_service/transports/README.rst | 9 + .../goal_service/transports/__init__.py | 34 + .../services/goal_service/transports/base.py | 173 + .../services/goal_service/transports/grpc.py | 385 ++ .../goal_service/transports/grpc_asyncio.py | 407 ++ .../google_ads_field_service/__init__.py | 22 + .../google_ads_field_service/async_client.py | 514 ++ .../google_ads_field_service/client.py | 974 ++++ .../google_ads_field_service/pagers.py | 209 + .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../transports/base.py | 191 + .../transports/grpc.py | 424 ++ .../transports/grpc_asyncio.py | 450 ++ .../services/google_ads_service/__init__.py | 22 + .../google_ads_service/async_client.py | 1747 ++++++ .../services/google_ads_service/client.py | 5080 +++++++++++++++++ .../services/google_ads_service/pagers.py | 199 + .../google_ads_service/transports/README.rst | 9 + .../google_ads_service/transports/__init__.py | 34 + .../google_ads_service/transports/base.py | 207 + .../google_ads_service/transports/grpc.py | 538 ++ .../transports/grpc_asyncio.py | 569 ++ .../identity_verification_service/__init__.py | 22 + .../async_client.py | 527 ++ .../identity_verification_service/client.py | 985 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 192 + .../transports/grpc.py | 428 ++ .../transports/grpc_asyncio.py | 456 ++ .../services/incentive_service/__init__.py | 22 + .../incentive_service/async_client.py | 457 ++ .../services/incentive_service/client.py | 895 +++ .../incentive_service/transports/README.rst | 9 + .../incentive_service/transports/__init__.py | 34 + .../incentive_service/transports/base.py | 190 + .../incentive_service/transports/grpc.py | 410 ++ .../transports/grpc_asyncio.py | 436 ++ .../services/invoice_service/__init__.py | 22 + .../services/invoice_service/async_client.py | 436 ++ .../services/invoice_service/client.py | 896 +++ .../invoice_service/transports/README.rst | 9 + .../invoice_service/transports/__init__.py | 34 + .../invoice_service/transports/base.py | 173 + .../invoice_service/transports/grpc.py | 388 ++ .../transports/grpc_asyncio.py | 409 ++ .../__init__.py | 22 + .../async_client.py | 459 ++ .../client.py | 958 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 179 + .../transports/grpc.py | 404 ++ .../transports/grpc_asyncio.py | 427 ++ .../keyword_plan_ad_group_service/__init__.py | 22 + .../async_client.py | 451 ++ .../keyword_plan_ad_group_service/client.py | 945 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 177 + .../transports/grpc.py | 396 ++ .../transports/grpc_asyncio.py | 419 ++ .../__init__.py | 22 + .../async_client.py | 461 ++ .../client.py | 958 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 179 + .../transports/grpc.py | 405 ++ .../transports/grpc_asyncio.py | 428 ++ .../keyword_plan_campaign_service/__init__.py | 22 + .../async_client.py | 463 ++ .../keyword_plan_campaign_service/client.py | 978 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 177 + .../transports/grpc.py | 396 ++ .../transports/grpc_asyncio.py | 419 ++ .../keyword_plan_idea_service/__init__.py | 22 + .../keyword_plan_idea_service/async_client.py | 701 +++ .../keyword_plan_idea_service/client.py | 1162 ++++ .../keyword_plan_idea_service/pagers.py | 212 + .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../transports/base.py | 228 + .../transports/grpc.py | 501 ++ .../transports/grpc_asyncio.py | 543 ++ .../services/keyword_plan_service/__init__.py | 22 + .../keyword_plan_service/async_client.py | 423 ++ .../services/keyword_plan_service/client.py | 889 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../keyword_plan_service/transports/base.py | 173 + .../keyword_plan_service/transports/grpc.py | 391 ++ .../transports/grpc_asyncio.py | 412 ++ .../__init__.py | 22 + .../async_client.py | 388 ++ .../keyword_theme_constant_service/client.py | 862 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 177 + .../transports/grpc.py | 392 ++ .../transports/grpc_asyncio.py | 415 ++ .../services/label_service/__init__.py | 22 + .../services/label_service/async_client.py | 411 ++ .../services/services/label_service/client.py | 880 +++ .../label_service/transports/README.rst | 9 + .../label_service/transports/__init__.py | 34 + .../services/label_service/transports/base.py | 173 + .../services/label_service/transports/grpc.py | 392 ++ .../label_service/transports/grpc_asyncio.py | 414 ++ .../local_services_lead_service/__init__.py | 22 + .../async_client.py | 496 ++ .../local_services_lead_service/client.py | 974 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 192 + .../transports/grpc.py | 417 ++ .../transports/grpc_asyncio.py | 445 ++ .../offline_user_data_job_service/__init__.py | 22 + .../async_client.py | 682 +++ .../offline_user_data_job_service/client.py | 1160 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 216 + .../transports/grpc.py | 490 ++ .../transports/grpc_asyncio.py | 527 ++ .../payments_account_service/__init__.py | 22 + .../payments_account_service/async_client.py | 423 ++ .../payments_account_service/client.py | 900 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../transports/base.py | 173 + .../transports/grpc.py | 391 ++ .../transports/grpc_asyncio.py | 414 ++ .../__init__.py | 22 + .../async_client.py | 677 +++ .../product_link_invitation_service/client.py | 1159 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 215 + .../transports/grpc.py | 450 ++ .../transports/grpc_asyncio.py | 487 ++ .../services/product_link_service/__init__.py | 22 + .../product_link_service/async_client.py | 534 ++ .../services/product_link_service/client.py | 1000 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../product_link_service/transports/base.py | 190 + .../product_link_service/transports/grpc.py | 425 ++ .../transports/grpc_asyncio.py | 451 ++ .../services/reach_plan_service/__init__.py | 22 + .../reach_plan_service/async_client.py | 850 +++ .../services/reach_plan_service/client.py | 1298 +++++ .../reach_plan_service/transports/README.rst | 9 + .../reach_plan_service/transports/__init__.py | 34 + .../reach_plan_service/transports/base.py | 258 + .../reach_plan_service/transports/grpc.py | 581 ++ .../transports/grpc_asyncio.py | 627 ++ .../recommendation_service/__init__.py | 22 + .../recommendation_service/async_client.py | 713 +++ .../services/recommendation_service/client.py | 1279 +++++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../recommendation_service/transports/base.py | 207 + .../recommendation_service/transports/grpc.py | 463 ++ .../transports/grpc_asyncio.py | 494 ++ .../__init__.py | 22 + .../async_client.py | 447 ++ .../client.py | 930 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 179 + .../transports/grpc.py | 400 ++ .../transports/grpc_asyncio.py | 423 ++ .../remarketing_action_service/__init__.py | 22 + .../async_client.py | 436 ++ .../remarketing_action_service/client.py | 914 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 389 ++ .../transports/grpc_asyncio.py | 412 ++ .../services/reservation_service/__init__.py | 22 + .../reservation_service/async_client.py | 489 ++ .../services/reservation_service/client.py | 924 +++ .../reservation_service/transports/README.rst | 9 + .../transports/__init__.py | 34 + .../reservation_service/transports/base.py | 190 + .../reservation_service/transports/grpc.py | 413 ++ .../transports/grpc_asyncio.py | 439 ++ .../shareable_preview_service/__init__.py | 22 + .../shareable_preview_service/async_client.py | 407 ++ .../shareable_preview_service/client.py | 861 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 175 + .../transports/grpc.py | 383 ++ .../transports/grpc_asyncio.py | 406 ++ .../shared_criterion_service/__init__.py | 22 + .../shared_criterion_service/async_client.py | 444 ++ .../shared_criterion_service/client.py | 950 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 34 + .../transports/base.py | 173 + .../transports/grpc.py | 394 ++ .../transports/grpc_asyncio.py | 417 ++ .../services/shared_set_service/__init__.py | 22 + .../shared_set_service/async_client.py | 423 ++ .../services/shared_set_service/client.py | 891 +++ .../shared_set_service/transports/README.rst | 9 + .../shared_set_service/transports/__init__.py | 34 + .../shared_set_service/transports/base.py | 173 + .../shared_set_service/transports/grpc.py | 395 ++ .../transports/grpc_asyncio.py | 416 ++ .../__init__.py | 22 + .../async_client.py | 538 ++ .../smart_campaign_setting_service/client.py | 1034 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 196 + .../transports/grpc.py | 418 ++ .../transports/grpc_asyncio.py | 448 ++ .../__init__.py | 22 + .../async_client.py | 632 ++ .../smart_campaign_suggest_service/client.py | 1118 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 217 + .../transports/grpc.py | 454 ++ .../transports/grpc_asyncio.py | 489 ++ .../__init__.py | 22 + .../async_client.py | 408 ++ .../client.py | 882 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 179 + .../transports/grpc.py | 399 ++ .../transports/grpc_asyncio.py | 422 ++ .../__init__.py | 22 + .../async_client.py | 426 ++ .../travel_asset_suggestion_service/client.py | 887 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 177 + .../transports/grpc.py | 390 ++ .../transports/grpc_asyncio.py | 411 ++ .../services/user_data_service/__init__.py | 22 + .../user_data_service/async_client.py | 386 ++ .../services/user_data_service/client.py | 827 +++ .../user_data_service/transports/README.rst | 9 + .../user_data_service/transports/__init__.py | 34 + .../user_data_service/transports/base.py | 173 + .../user_data_service/transports/grpc.py | 394 ++ .../transports/grpc_asyncio.py | 415 ++ .../__init__.py | 22 + .../async_client.py | 445 ++ .../user_list_customer_type_service/client.py | 944 +++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 177 + .../transports/grpc.py | 394 ++ .../transports/grpc_asyncio.py | 417 ++ .../services/user_list_service/__init__.py | 22 + .../user_list_service/async_client.py | 421 ++ .../services/user_list_service/client.py | 889 +++ .../user_list_service/transports/README.rst | 9 + .../user_list_service/transports/__init__.py | 34 + .../user_list_service/transports/base.py | 173 + .../user_list_service/transports/grpc.py | 391 ++ .../transports/grpc_asyncio.py | 412 ++ .../you_tube_video_upload_service/__init__.py | 22 + .../async_client.py | 624 ++ .../you_tube_video_upload_service/client.py | 1191 ++++ .../transports/README.rst | 9 + .../transports/__init__.py | 36 + .../transports/base.py | 213 + .../transports/grpc.py | 449 ++ .../transports/grpc_asyncio.py | 486 ++ .../transports/rest_resumable.py | 343 ++ .../transports/rest_resumable_base.py | 118 + .../transports/resumable_upload.py | 483 ++ .../resumable_upload_error_adapter.py | 119 + .../googleads/v24/services/types/__init__.py | 1486 +++++ .../types/account_budget_proposal_service.py | 155 + .../services/types/account_link_service.py | 208 + .../types/ad_group_ad_label_service.py | 161 + .../v24/services/types/ad_group_ad_service.py | 268 + .../services/types/ad_group_asset_service.py | 203 + .../types/ad_group_asset_set_service.py | 185 + .../types/ad_group_bid_modifier_service.py | 209 + .../ad_group_criterion_customizer_service.py | 192 + .../types/ad_group_criterion_label_service.py | 162 + .../types/ad_group_criterion_service.py | 225 + .../types/ad_group_customizer_service.py | 188 + .../services/types/ad_group_label_service.py | 157 + .../v24/services/types/ad_group_service.py | 200 + .../services/types/ad_parameter_service.py | 203 + .../v24/services/types/ad_service.py | 183 + .../types/asset_generation_service.py | 417 ++ .../types/asset_group_asset_service.py | 180 + ...sset_group_listing_group_filter_service.py | 198 + .../v24/services/types/asset_group_service.py | 166 + .../types/asset_group_signal_service.py | 203 + .../v24/services/types/asset_service.py | 195 + .../services/types/asset_set_asset_service.py | 181 + .../v24/services/types/asset_set_service.py | 199 + .../types/audience_insights_service.py | 1186 ++++ .../v24/services/types/audience_service.py | 188 + ...matically_created_asset_removal_service.py | 127 + .../v24/services/types/batch_job_service.py | 335 ++ .../v24/services/types/benchmarks_service.py | 770 +++ .../types/bidding_data_exclusion_service.py | 209 + .../bidding_seasonality_adjustment_service.py | 213 + .../types/bidding_strategy_service.py | 207 + .../services/types/billing_setup_service.py | 127 + .../types/brand_suggestion_service.py | 124 + .../services/types/campaign_asset_service.py | 203 + .../types/campaign_asset_set_service.py | 185 + .../types/campaign_bid_modifier_service.py | 209 + .../services/types/campaign_budget_service.py | 207 + .../types/campaign_conversion_goal_service.py | 131 + .../types/campaign_criterion_service.py | 209 + .../types/campaign_customizer_service.py | 188 + .../services/types/campaign_draft_service.py | 294 + .../types/campaign_goal_config_service.py | 174 + .../services/types/campaign_group_service.py | 203 + .../services/types/campaign_label_service.py | 159 + .../types/campaign_lifecycle_goal_service.py | 147 + .../v24/services/types/campaign_service.py | 362 ++ .../types/campaign_shared_set_service.py | 188 + .../types/content_creator_insights_service.py | 882 +++ .../types/conversion_action_service.py | 208 + .../conversion_adjustment_upload_service.py | 392 ++ .../conversion_custom_variable_service.py | 203 + ...conversion_goal_campaign_config_service.py | 164 + .../types/conversion_upload_service.py | 837 +++ .../types/conversion_value_rule_service.py | 210 + .../conversion_value_rule_set_service.py | 210 + .../services/types/custom_audience_service.py | 159 + .../types/custom_conversion_goal_service.py | 187 + .../services/types/custom_interest_service.py | 147 + .../services/types/customer_asset_service.py | 203 + .../types/customer_asset_set_service.py | 185 + .../types/customer_client_link_service.py | 143 + .../types/customer_conversion_goal_service.py | 131 + .../types/customer_customizer_service.py | 188 + .../services/types/customer_label_service.py | 164 + .../types/customer_lifecycle_goal_service.py | 145 + .../types/customer_manager_link_service.py | 199 + .../customer_negative_criterion_service.py | 191 + .../v24/services/types/customer_service.py | 251 + ...network_conversion_value_schema_service.py | 147 + ...customer_user_access_invitation_service.py | 132 + .../types/customer_user_access_service.py | 136 + .../types/customizer_attribute_service.py | 197 + .../v24/services/types/data_link_service.py | 167 + .../services/types/experiment_arm_service.py | 201 + .../v24/services/types/experiment_service.py | 406 ++ .../types/geo_target_constant_service.py | 207 + .../v24/services/types/goal_service.py | 161 + .../types/google_ads_field_service.py | 123 + .../v24/services/types/google_ads_service.py | 4209 ++++++++++++++ .../types/identity_verification_service.py | 200 + .../v24/services/types/incentive_service.py | 434 ++ .../v24/services/types/invoice_service.py | 104 + .../keyword_plan_ad_group_keyword_service.py | 191 + .../types/keyword_plan_ad_group_service.py | 184 + .../keyword_plan_campaign_keyword_service.py | 189 + .../types/keyword_plan_campaign_service.py | 182 + .../types/keyword_plan_idea_service.py | 1010 ++++ .../services/types/keyword_plan_service.py | 178 + .../types/keyword_theme_constant_service.py | 86 + .../v24/services/types/label_service.py | 200 + .../types/local_services_lead_service.py | 284 + .../types/offline_user_data_job_service.py | 254 + .../types/payments_account_service.py | 69 + .../types/product_link_invitation_service.py | 169 + .../services/types/product_link_service.py | 123 + .../v24/services/types/reach_plan_service.py | 1920 +++++++ .../services/types/recommendation_service.py | 1573 +++++ .../recommendation_subscription_service.py | 207 + .../types/remarketing_action_service.py | 169 + .../v24/services/types/reservation_service.py | 115 + .../types/shareable_preview_service.py | 78 + .../types/shared_criterion_service.py | 186 + .../v24/services/types/shared_set_service.py | 202 + .../types/smart_campaign_setting_service.py | 408 ++ .../types/smart_campaign_suggest_service.py | 429 ++ .../third_party_app_analytics_link_service.py | 55 + .../types/travel_asset_suggestion_service.py | 203 + .../v24/services/types/user_data_service.py | 148 + .../types/user_list_customer_type_service.py | 164 + .../v24/services/types/user_list_service.py | 177 + .../types/youtube_video_upload_service.py | 172 + pyproject.toml | 7 +- 1918 files changed, 443079 insertions(+), 922 deletions(-) create mode 100644 google/ads/googleads/v24/__init__.py create mode 100644 google/ads/googleads/v24/actions/__init__.py create mode 100644 google/ads/googleads/v24/actions/services/__init__.py create mode 100644 google/ads/googleads/v24/actions/types/__init__.py create mode 100644 google/ads/googleads/v24/actions/types/book_campaigns.py create mode 100644 google/ads/googleads/v24/actions/types/generate_shareable_previews.py create mode 100644 google/ads/googleads/v24/actions/types/quote_campaigns.py create mode 100644 google/ads/googleads/v24/common/__init__.py create mode 100644 google/ads/googleads/v24/common/services/__init__.py create mode 100644 google/ads/googleads/v24/common/types/__init__.py create mode 100644 google/ads/googleads/v24/common/types/ad_asset.py create mode 100644 google/ads/googleads/v24/common/types/ad_type_infos.py create mode 100644 google/ads/googleads/v24/common/types/additional_application_info.py create mode 100644 google/ads/googleads/v24/common/types/asset_policy.py create mode 100644 google/ads/googleads/v24/common/types/asset_set_types.py create mode 100644 google/ads/googleads/v24/common/types/asset_types.py create mode 100644 google/ads/googleads/v24/common/types/asset_usage.py create mode 100644 google/ads/googleads/v24/common/types/audience_insights_attribute.py create mode 100644 google/ads/googleads/v24/common/types/audiences.py create mode 100644 google/ads/googleads/v24/common/types/bidding.py create mode 100644 google/ads/googleads/v24/common/types/campaign_goal_settings.py create mode 100644 google/ads/googleads/v24/common/types/campaign_reservation_quote.py create mode 100644 google/ads/googleads/v24/common/types/click_location.py create mode 100644 google/ads/googleads/v24/common/types/consent.py create mode 100644 google/ads/googleads/v24/common/types/criteria.py create mode 100644 google/ads/googleads/v24/common/types/criterion_category_availability.py create mode 100644 google/ads/googleads/v24/common/types/custom_parameter.py create mode 100644 google/ads/googleads/v24/common/types/customizer_value.py create mode 100644 google/ads/googleads/v24/common/types/dates.py create mode 100644 google/ads/googleads/v24/common/types/extensions.py create mode 100644 google/ads/googleads/v24/common/types/feed_common.py create mode 100644 google/ads/googleads/v24/common/types/final_app_url.py create mode 100644 google/ads/googleads/v24/common/types/frequency_cap.py create mode 100644 google/ads/googleads/v24/common/types/goal_common.py create mode 100644 google/ads/googleads/v24/common/types/goal_setting.py create mode 100644 google/ads/googleads/v24/common/types/keyword_plan_common.py create mode 100644 google/ads/googleads/v24/common/types/lifecycle_goals.py create mode 100644 google/ads/googleads/v24/common/types/local_services.py create mode 100644 google/ads/googleads/v24/common/types/metric_goal.py create mode 100644 google/ads/googleads/v24/common/types/metrics.py create mode 100644 google/ads/googleads/v24/common/types/offline_user_data.py create mode 100644 google/ads/googleads/v24/common/types/policy.py create mode 100644 google/ads/googleads/v24/common/types/policy_summary.py create mode 100644 google/ads/googleads/v24/common/types/real_time_bidding_setting.py create mode 100644 google/ads/googleads/v24/common/types/segments.py create mode 100644 google/ads/googleads/v24/common/types/simulation.py create mode 100644 google/ads/googleads/v24/common/types/tag_snippet.py create mode 100644 google/ads/googleads/v24/common/types/targeting_setting.py create mode 100644 google/ads/googleads/v24/common/types/text_label.py create mode 100644 google/ads/googleads/v24/common/types/third_party_integration_partners.py create mode 100644 google/ads/googleads/v24/common/types/url_collection.py create mode 100644 google/ads/googleads/v24/common/types/user_lists.py create mode 100644 google/ads/googleads/v24/common/types/value.py create mode 100644 google/ads/googleads/v24/enums/__init__.py create mode 100644 google/ads/googleads/v24/enums/services/__init__.py create mode 100644 google/ads/googleads/v24/enums/types/__init__.py create mode 100644 google/ads/googleads/v24/enums/types/access_invitation_status.py create mode 100644 google/ads/googleads/v24/enums/types/access_reason.py create mode 100644 google/ads/googleads/v24/enums/types/access_role.py create mode 100644 google/ads/googleads/v24/enums/types/account_budget_proposal_status.py create mode 100644 google/ads/googleads/v24/enums/types/account_budget_proposal_type.py create mode 100644 google/ads/googleads/v24/enums/types/account_budget_status.py create mode 100644 google/ads/googleads/v24/enums/types/account_link_status.py create mode 100644 google/ads/googleads/v24/enums/types/ad_destination_type.py create mode 100644 google/ads/googleads/v24/enums/types/ad_format_type.py create mode 100644 google/ads/googleads/v24/enums/types/ad_group_ad_primary_status.py create mode 100644 google/ads/googleads/v24/enums/types/ad_group_ad_primary_status_reason.py create mode 100644 google/ads/googleads/v24/enums/types/ad_group_ad_rotation_mode.py create mode 100644 google/ads/googleads/v24/enums/types/ad_group_ad_status.py create mode 100644 google/ads/googleads/v24/enums/types/ad_group_criterion_approval_status.py create mode 100644 google/ads/googleads/v24/enums/types/ad_group_criterion_primary_status.py create mode 100644 google/ads/googleads/v24/enums/types/ad_group_criterion_primary_status_reason.py create mode 100644 google/ads/googleads/v24/enums/types/ad_group_criterion_status.py create mode 100644 google/ads/googleads/v24/enums/types/ad_group_primary_status.py create mode 100644 google/ads/googleads/v24/enums/types/ad_group_primary_status_reason.py create mode 100644 google/ads/googleads/v24/enums/types/ad_group_status.py create mode 100644 google/ads/googleads/v24/enums/types/ad_group_type.py create mode 100644 google/ads/googleads/v24/enums/types/ad_network_type.py create mode 100644 google/ads/googleads/v24/enums/types/ad_serving_optimization_status.py create mode 100644 google/ads/googleads/v24/enums/types/ad_strength.py create mode 100644 google/ads/googleads/v24/enums/types/ad_strength_action_item_type.py create mode 100644 google/ads/googleads/v24/enums/types/ad_sub_network_type.py create mode 100644 google/ads/googleads/v24/enums/types/ad_type.py create mode 100644 google/ads/googleads/v24/enums/types/advertising_channel_sub_type.py create mode 100644 google/ads/googleads/v24/enums/types/advertising_channel_type.py create mode 100644 google/ads/googleads/v24/enums/types/age_range_type.py create mode 100644 google/ads/googleads/v24/enums/types/android_privacy_interaction_type.py create mode 100644 google/ads/googleads/v24/enums/types/android_privacy_network_type.py create mode 100644 google/ads/googleads/v24/enums/types/app_bidding_goal.py create mode 100644 google/ads/googleads/v24/enums/types/app_campaign_app_store.py create mode 100644 google/ads/googleads/v24/enums/types/app_campaign_bidding_strategy_goal_type.py create mode 100644 google/ads/googleads/v24/enums/types/app_payment_model_type.py create mode 100644 google/ads/googleads/v24/enums/types/app_url_operating_system_type.py create mode 100644 google/ads/googleads/v24/enums/types/application_instance.py create mode 100644 google/ads/googleads/v24/enums/types/asset_automation_status.py create mode 100644 google/ads/googleads/v24/enums/types/asset_automation_type.py create mode 100644 google/ads/googleads/v24/enums/types/asset_coverage_video_aspect_ratio_requirement.py create mode 100644 google/ads/googleads/v24/enums/types/asset_field_type.py create mode 100644 google/ads/googleads/v24/enums/types/asset_group_primary_status.py create mode 100644 google/ads/googleads/v24/enums/types/asset_group_primary_status_reason.py create mode 100644 google/ads/googleads/v24/enums/types/asset_group_signal_approval_status.py create mode 100644 google/ads/googleads/v24/enums/types/asset_group_status.py create mode 100644 google/ads/googleads/v24/enums/types/asset_link_primary_status.py create mode 100644 google/ads/googleads/v24/enums/types/asset_link_primary_status_reason.py create mode 100644 google/ads/googleads/v24/enums/types/asset_link_status.py create mode 100644 google/ads/googleads/v24/enums/types/asset_offline_evaluation_error_reasons.py create mode 100644 google/ads/googleads/v24/enums/types/asset_orientation.py create mode 100644 google/ads/googleads/v24/enums/types/asset_performance_label.py create mode 100644 google/ads/googleads/v24/enums/types/asset_set_asset_status.py create mode 100644 google/ads/googleads/v24/enums/types/asset_set_link_status.py create mode 100644 google/ads/googleads/v24/enums/types/asset_set_status.py create mode 100644 google/ads/googleads/v24/enums/types/asset_set_type.py create mode 100644 google/ads/googleads/v24/enums/types/asset_source.py create mode 100644 google/ads/googleads/v24/enums/types/asset_type.py create mode 100644 google/ads/googleads/v24/enums/types/async_action_status.py create mode 100644 google/ads/googleads/v24/enums/types/attribution_model.py create mode 100644 google/ads/googleads/v24/enums/types/audience_insights_dimension.py create mode 100644 google/ads/googleads/v24/enums/types/audience_insights_marketing_objective.py create mode 100644 google/ads/googleads/v24/enums/types/audience_scope.py create mode 100644 google/ads/googleads/v24/enums/types/audience_status.py create mode 100644 google/ads/googleads/v24/enums/types/batch_job_status.py create mode 100644 google/ads/googleads/v24/enums/types/benchmarks_marketing_objective.py create mode 100644 google/ads/googleads/v24/enums/types/benchmarks_source_type.py create mode 100644 google/ads/googleads/v24/enums/types/benchmarks_time_granularity.py create mode 100644 google/ads/googleads/v24/enums/types/bid_modifier_source.py create mode 100644 google/ads/googleads/v24/enums/types/bidding_source.py create mode 100644 google/ads/googleads/v24/enums/types/bidding_strategy_status.py create mode 100644 google/ads/googleads/v24/enums/types/bidding_strategy_system_status.py create mode 100644 google/ads/googleads/v24/enums/types/bidding_strategy_type.py create mode 100644 google/ads/googleads/v24/enums/types/billing_setup_status.py create mode 100644 google/ads/googleads/v24/enums/types/booking_status.py create mode 100644 google/ads/googleads/v24/enums/types/brand_request_rejection_reason.py create mode 100644 google/ads/googleads/v24/enums/types/brand_safety_suitability.py create mode 100644 google/ads/googleads/v24/enums/types/brand_state.py create mode 100644 google/ads/googleads/v24/enums/types/budget_campaign_association_status.py create mode 100644 google/ads/googleads/v24/enums/types/budget_delivery_method.py create mode 100644 google/ads/googleads/v24/enums/types/budget_period.py create mode 100644 google/ads/googleads/v24/enums/types/budget_status.py create mode 100644 google/ads/googleads/v24/enums/types/budget_type.py create mode 100644 google/ads/googleads/v24/enums/types/business_message_call_to_action_type.py create mode 100644 google/ads/googleads/v24/enums/types/business_message_provider.py create mode 100644 google/ads/googleads/v24/enums/types/call_conversion_reporting_state.py create mode 100644 google/ads/googleads/v24/enums/types/call_to_action_type.py create mode 100644 google/ads/googleads/v24/enums/types/call_tracking_display_location.py create mode 100644 google/ads/googleads/v24/enums/types/call_type.py create mode 100644 google/ads/googleads/v24/enums/types/campaign_criterion_status.py create mode 100644 google/ads/googleads/v24/enums/types/campaign_draft_status.py create mode 100644 google/ads/googleads/v24/enums/types/campaign_experiment_type.py create mode 100644 google/ads/googleads/v24/enums/types/campaign_group_status.py create mode 100644 google/ads/googleads/v24/enums/types/campaign_keyword_match_type.py create mode 100644 google/ads/googleads/v24/enums/types/campaign_primary_status.py create mode 100644 google/ads/googleads/v24/enums/types/campaign_primary_status_reason.py create mode 100644 google/ads/googleads/v24/enums/types/campaign_serving_status.py create mode 100644 google/ads/googleads/v24/enums/types/campaign_shared_set_status.py create mode 100644 google/ads/googleads/v24/enums/types/campaign_status.py create mode 100644 google/ads/googleads/v24/enums/types/chain_relationship_type.py create mode 100644 google/ads/googleads/v24/enums/types/change_client_type.py create mode 100644 google/ads/googleads/v24/enums/types/change_event_resource_type.py create mode 100644 google/ads/googleads/v24/enums/types/change_status_operation.py create mode 100644 google/ads/googleads/v24/enums/types/change_status_resource_type.py create mode 100644 google/ads/googleads/v24/enums/types/click_type.py create mode 100644 google/ads/googleads/v24/enums/types/combined_audience_status.py create mode 100644 google/ads/googleads/v24/enums/types/consent_status.py create mode 100644 google/ads/googleads/v24/enums/types/content_label_type.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_action_category.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_action_counting_type.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_action_status.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_action_type.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_adjustment_type.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_attribution_event_type.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_custom_variable_status.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_customer_type.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_environment_enum.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_lag_bucket.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_or_adjustment_lag_bucket.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_origin.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_tracking_status_enum.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_value_rule_primary_dimension.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_value_rule_set_status.py create mode 100644 google/ads/googleads/v24/enums/types/conversion_value_rule_status.py create mode 100644 google/ads/googleads/v24/enums/types/converting_user_prior_engagement_type_and_ltv_bucket.py create mode 100644 google/ads/googleads/v24/enums/types/criterion_category_channel_availability_mode.py create mode 100644 google/ads/googleads/v24/enums/types/criterion_category_locale_availability_mode.py create mode 100644 google/ads/googleads/v24/enums/types/criterion_system_serving_status.py create mode 100644 google/ads/googleads/v24/enums/types/criterion_type.py create mode 100644 google/ads/googleads/v24/enums/types/custom_audience_member_type.py create mode 100644 google/ads/googleads/v24/enums/types/custom_audience_status.py create mode 100644 google/ads/googleads/v24/enums/types/custom_audience_type.py create mode 100644 google/ads/googleads/v24/enums/types/custom_conversion_goal_status.py create mode 100644 google/ads/googleads/v24/enums/types/custom_interest_member_type.py create mode 100644 google/ads/googleads/v24/enums/types/custom_interest_status.py create mode 100644 google/ads/googleads/v24/enums/types/custom_interest_type.py create mode 100644 google/ads/googleads/v24/enums/types/customer_acquisition_optimization_mode.py create mode 100644 google/ads/googleads/v24/enums/types/customer_lifecycle_optimization_mode.py create mode 100644 google/ads/googleads/v24/enums/types/customer_match_upload_key_type.py create mode 100644 google/ads/googleads/v24/enums/types/customer_pay_per_conversion_eligibility_failure_reason.py create mode 100644 google/ads/googleads/v24/enums/types/customer_status.py create mode 100644 google/ads/googleads/v24/enums/types/customizer_attribute_status.py create mode 100644 google/ads/googleads/v24/enums/types/customizer_attribute_type.py create mode 100644 google/ads/googleads/v24/enums/types/customizer_value_status.py create mode 100644 google/ads/googleads/v24/enums/types/data_driven_model_status.py create mode 100644 google/ads/googleads/v24/enums/types/data_link_status.py create mode 100644 google/ads/googleads/v24/enums/types/data_link_type.py create mode 100644 google/ads/googleads/v24/enums/types/day_of_week.py create mode 100644 google/ads/googleads/v24/enums/types/demand_gen_channel_config.py create mode 100644 google/ads/googleads/v24/enums/types/demand_gen_channel_strategy.py create mode 100644 google/ads/googleads/v24/enums/types/device.py create mode 100644 google/ads/googleads/v24/enums/types/display_ad_format_setting.py create mode 100644 google/ads/googleads/v24/enums/types/display_upload_product_type.py create mode 100644 google/ads/googleads/v24/enums/types/distance_bucket.py create mode 100644 google/ads/googleads/v24/enums/types/eu_political_advertising_status.py create mode 100644 google/ads/googleads/v24/enums/types/experiment_metric.py create mode 100644 google/ads/googleads/v24/enums/types/experiment_metric_direction.py create mode 100644 google/ads/googleads/v24/enums/types/experiment_status.py create mode 100644 google/ads/googleads/v24/enums/types/experiment_type.py create mode 100644 google/ads/googleads/v24/enums/types/external_conversion_source.py create mode 100644 google/ads/googleads/v24/enums/types/fixed_cpm_goal.py create mode 100644 google/ads/googleads/v24/enums/types/fixed_cpm_target_frequency_time_unit.py create mode 100644 google/ads/googleads/v24/enums/types/frequency_cap_event_type.py create mode 100644 google/ads/googleads/v24/enums/types/frequency_cap_level.py create mode 100644 google/ads/googleads/v24/enums/types/frequency_cap_time_unit.py create mode 100644 google/ads/googleads/v24/enums/types/gender_type.py create mode 100644 google/ads/googleads/v24/enums/types/geo_target_constant_status.py create mode 100644 google/ads/googleads/v24/enums/types/geo_targeting_type.py create mode 100644 google/ads/googleads/v24/enums/types/goal_config_level.py create mode 100644 google/ads/googleads/v24/enums/types/goal_optimization_eligibility.py create mode 100644 google/ads/googleads/v24/enums/types/goal_type.py create mode 100644 google/ads/googleads/v24/enums/types/google_ads_field_category.py create mode 100644 google/ads/googleads/v24/enums/types/google_ads_field_data_type.py create mode 100644 google/ads/googleads/v24/enums/types/google_voice_call_status.py create mode 100644 google/ads/googleads/v24/enums/types/hotel_asset_suggestion_status.py create mode 100644 google/ads/googleads/v24/enums/types/hotel_date_selection_type.py create mode 100644 google/ads/googleads/v24/enums/types/hotel_price_bucket.py create mode 100644 google/ads/googleads/v24/enums/types/hotel_rate_type.py create mode 100644 google/ads/googleads/v24/enums/types/hotel_reconciliation_status.py create mode 100644 google/ads/googleads/v24/enums/types/identity_verification_program.py create mode 100644 google/ads/googleads/v24/enums/types/identity_verification_program_status.py create mode 100644 google/ads/googleads/v24/enums/types/incentive_state.py create mode 100644 google/ads/googleads/v24/enums/types/income_range_type.py create mode 100644 google/ads/googleads/v24/enums/types/insights_knowledge_graph_entity_capabilities.py create mode 100644 google/ads/googleads/v24/enums/types/insights_trend.py create mode 100644 google/ads/googleads/v24/enums/types/interaction_event_type.py create mode 100644 google/ads/googleads/v24/enums/types/interaction_type.py create mode 100644 google/ads/googleads/v24/enums/types/invoice_type.py create mode 100644 google/ads/googleads/v24/enums/types/keyword_match_type.py create mode 100644 google/ads/googleads/v24/enums/types/keyword_plan_aggregate_metric_type.py create mode 100644 google/ads/googleads/v24/enums/types/keyword_plan_competition_level.py create mode 100644 google/ads/googleads/v24/enums/types/keyword_plan_concept_group_type.py create mode 100644 google/ads/googleads/v24/enums/types/keyword_plan_forecast_interval.py create mode 100644 google/ads/googleads/v24/enums/types/keyword_plan_keyword_annotation.py create mode 100644 google/ads/googleads/v24/enums/types/keyword_plan_network.py create mode 100644 google/ads/googleads/v24/enums/types/label_status.py create mode 100644 google/ads/googleads/v24/enums/types/landing_page_source.py create mode 100644 google/ads/googleads/v24/enums/types/lead_form_call_to_action_type.py create mode 100644 google/ads/googleads/v24/enums/types/lead_form_desired_intent.py create mode 100644 google/ads/googleads/v24/enums/types/lead_form_field_user_input_type.py create mode 100644 google/ads/googleads/v24/enums/types/lead_form_post_submit_call_to_action_type.py create mode 100644 google/ads/googleads/v24/enums/types/legacy_app_install_ad_app_store.py create mode 100644 google/ads/googleads/v24/enums/types/linked_account_type.py create mode 100644 google/ads/googleads/v24/enums/types/linked_product_type.py create mode 100644 google/ads/googleads/v24/enums/types/listing_group_filter_custom_attribute_index.py create mode 100644 google/ads/googleads/v24/enums/types/listing_group_filter_listing_source.py create mode 100644 google/ads/googleads/v24/enums/types/listing_group_filter_product_category_level.py create mode 100644 google/ads/googleads/v24/enums/types/listing_group_filter_product_channel.py create mode 100644 google/ads/googleads/v24/enums/types/listing_group_filter_product_condition.py create mode 100644 google/ads/googleads/v24/enums/types/listing_group_filter_product_type_level.py create mode 100644 google/ads/googleads/v24/enums/types/listing_group_filter_type_enum.py create mode 100644 google/ads/googleads/v24/enums/types/listing_group_type.py create mode 100644 google/ads/googleads/v24/enums/types/listing_type.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_business_registration_check_rejection_reason.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_business_registration_type.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_conversation_type.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_employee_status.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_employee_type.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_insurance_rejection_reason.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_lead_credit_issuance_decision.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_lead_credit_state.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_lead_status.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_lead_survey_answer.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_lead_survey_dissatisfied_reason.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_lead_survey_satisfied_reason.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_lead_type.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_license_rejection_reason.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_participant_type.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_verification_artifact_status.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_verification_artifact_type.py create mode 100644 google/ads/googleads/v24/enums/types/local_services_verification_status.py create mode 100644 google/ads/googleads/v24/enums/types/location_group_radius_units.py create mode 100644 google/ads/googleads/v24/enums/types/location_ownership_type.py create mode 100644 google/ads/googleads/v24/enums/types/location_source_type.py create mode 100644 google/ads/googleads/v24/enums/types/location_string_filter_type.py create mode 100644 google/ads/googleads/v24/enums/types/lookalike_expansion_level.py create mode 100644 google/ads/googleads/v24/enums/types/manager_link_status.py create mode 100644 google/ads/googleads/v24/enums/types/match_type.py create mode 100644 google/ads/googleads/v24/enums/types/media_type.py create mode 100644 google/ads/googleads/v24/enums/types/messaging_restriction_type.py create mode 100644 google/ads/googleads/v24/enums/types/mime_type.py create mode 100644 google/ads/googleads/v24/enums/types/minute_of_hour.py create mode 100644 google/ads/googleads/v24/enums/types/mobile_app_vendor.py create mode 100644 google/ads/googleads/v24/enums/types/mobile_device_type.py create mode 100644 google/ads/googleads/v24/enums/types/month_of_year.py create mode 100644 google/ads/googleads/v24/enums/types/negative_geo_target_type.py create mode 100644 google/ads/googleads/v24/enums/types/non_skippable_max_duration.py create mode 100644 google/ads/googleads/v24/enums/types/non_skippable_min_duration.py create mode 100644 google/ads/googleads/v24/enums/types/offline_conversion_diagnostic_status_enum.py create mode 100644 google/ads/googleads/v24/enums/types/offline_event_upload_client_enum.py create mode 100644 google/ads/googleads/v24/enums/types/offline_user_data_job_failure_reason.py create mode 100644 google/ads/googleads/v24/enums/types/offline_user_data_job_match_rate_range.py create mode 100644 google/ads/googleads/v24/enums/types/offline_user_data_job_status.py create mode 100644 google/ads/googleads/v24/enums/types/offline_user_data_job_type.py create mode 100644 google/ads/googleads/v24/enums/types/operating_system_version_operator_type.py create mode 100644 google/ads/googleads/v24/enums/types/optimization_goal_type.py create mode 100644 google/ads/googleads/v24/enums/types/parental_status_type.py create mode 100644 google/ads/googleads/v24/enums/types/partnership_opportunity.py create mode 100644 google/ads/googleads/v24/enums/types/payment_mode.py create mode 100644 google/ads/googleads/v24/enums/types/performance_max_upgrade_status.py create mode 100644 google/ads/googleads/v24/enums/types/placement_type.py create mode 100644 google/ads/googleads/v24/enums/types/policy_approval_status.py create mode 100644 google/ads/googleads/v24/enums/types/policy_review_status.py create mode 100644 google/ads/googleads/v24/enums/types/policy_topic_entry_type.py create mode 100644 google/ads/googleads/v24/enums/types/policy_topic_evidence_destination_mismatch_url_type.py create mode 100644 google/ads/googleads/v24/enums/types/policy_topic_evidence_destination_not_working_device.py create mode 100644 google/ads/googleads/v24/enums/types/policy_topic_evidence_destination_not_working_dns_error_type.py create mode 100644 google/ads/googleads/v24/enums/types/positive_geo_target_type.py create mode 100644 google/ads/googleads/v24/enums/types/preview_type.py create mode 100644 google/ads/googleads/v24/enums/types/price_extension_price_qualifier.py create mode 100644 google/ads/googleads/v24/enums/types/price_extension_price_unit.py create mode 100644 google/ads/googleads/v24/enums/types/price_extension_type.py create mode 100644 google/ads/googleads/v24/enums/types/product_availability.py create mode 100644 google/ads/googleads/v24/enums/types/product_category_level.py create mode 100644 google/ads/googleads/v24/enums/types/product_category_state.py create mode 100644 google/ads/googleads/v24/enums/types/product_channel.py create mode 100644 google/ads/googleads/v24/enums/types/product_channel_exclusivity.py create mode 100644 google/ads/googleads/v24/enums/types/product_condition.py create mode 100644 google/ads/googleads/v24/enums/types/product_custom_attribute_index.py create mode 100644 google/ads/googleads/v24/enums/types/product_issue_severity.py create mode 100644 google/ads/googleads/v24/enums/types/product_link_invitation_status.py create mode 100644 google/ads/googleads/v24/enums/types/product_status.py create mode 100644 google/ads/googleads/v24/enums/types/product_type_level.py create mode 100644 google/ads/googleads/v24/enums/types/promotion_barcode_type.py create mode 100644 google/ads/googleads/v24/enums/types/promotion_extension_discount_modifier.py create mode 100644 google/ads/googleads/v24/enums/types/promotion_extension_occasion.py create mode 100644 google/ads/googleads/v24/enums/types/proximity_radius_units.py create mode 100644 google/ads/googleads/v24/enums/types/quality_score_bucket.py create mode 100644 google/ads/googleads/v24/enums/types/reach_plan_age_range.py create mode 100644 google/ads/googleads/v24/enums/types/reach_plan_buying_method.py create mode 100644 google/ads/googleads/v24/enums/types/reach_plan_conversion_rate_model.py create mode 100644 google/ads/googleads/v24/enums/types/reach_plan_cost_model.py create mode 100644 google/ads/googleads/v24/enums/types/reach_plan_marketing_objective.py create mode 100644 google/ads/googleads/v24/enums/types/reach_plan_network.py create mode 100644 google/ads/googleads/v24/enums/types/reach_plan_plannable_user_list_status.py create mode 100644 google/ads/googleads/v24/enums/types/reach_plan_surface.py create mode 100644 google/ads/googleads/v24/enums/types/recommendation_subscription_status.py create mode 100644 google/ads/googleads/v24/enums/types/recommendation_type.py create mode 100644 google/ads/googleads/v24/enums/types/regulatory_fee_type.py create mode 100644 google/ads/googleads/v24/enums/types/reservation_request_type.py create mode 100644 google/ads/googleads/v24/enums/types/resource_change_operation.py create mode 100644 google/ads/googleads/v24/enums/types/resource_limit_type.py create mode 100644 google/ads/googleads/v24/enums/types/response_content_type.py create mode 100644 google/ads/googleads/v24/enums/types/search_engine_results_page_type.py create mode 100644 google/ads/googleads/v24/enums/types/search_term_match_source.py create mode 100644 google/ads/googleads/v24/enums/types/search_term_match_type.py create mode 100644 google/ads/googleads/v24/enums/types/search_term_targeting_status.py create mode 100644 google/ads/googleads/v24/enums/types/seasonality_event_scope.py create mode 100644 google/ads/googleads/v24/enums/types/seasonality_event_status.py create mode 100644 google/ads/googleads/v24/enums/types/served_asset_field_type.py create mode 100644 google/ads/googleads/v24/enums/types/shared_set_status.py create mode 100644 google/ads/googleads/v24/enums/types/shared_set_type.py create mode 100644 google/ads/googleads/v24/enums/types/shopping_add_products_to_campaign_recommendation_enum.py create mode 100644 google/ads/googleads/v24/enums/types/simulation_modification_method.py create mode 100644 google/ads/googleads/v24/enums/types/simulation_type.py create mode 100644 google/ads/googleads/v24/enums/types/sk_ad_network_ad_event_type.py create mode 100644 google/ads/googleads/v24/enums/types/sk_ad_network_attribution_credit.py create mode 100644 google/ads/googleads/v24/enums/types/sk_ad_network_coarse_conversion_value.py create mode 100644 google/ads/googleads/v24/enums/types/sk_ad_network_source_type.py create mode 100644 google/ads/googleads/v24/enums/types/sk_ad_network_user_type.py create mode 100644 google/ads/googleads/v24/enums/types/slot.py create mode 100644 google/ads/googleads/v24/enums/types/smart_campaign_not_eligible_reason.py create mode 100644 google/ads/googleads/v24/enums/types/smart_campaign_status.py create mode 100644 google/ads/googleads/v24/enums/types/spending_limit_type.py create mode 100644 google/ads/googleads/v24/enums/types/summary_row_setting.py create mode 100644 google/ads/googleads/v24/enums/types/system_managed_entity_source.py create mode 100644 google/ads/googleads/v24/enums/types/target_cpa_opt_in_recommendation_goal.py create mode 100644 google/ads/googleads/v24/enums/types/target_frequency_time_unit.py create mode 100644 google/ads/googleads/v24/enums/types/target_impression_share_location.py create mode 100644 google/ads/googleads/v24/enums/types/targeting_dimension.py create mode 100644 google/ads/googleads/v24/enums/types/third_party_brand_lift_integration_partner.py create mode 100644 google/ads/googleads/v24/enums/types/third_party_brand_safety_integration_partner.py create mode 100644 google/ads/googleads/v24/enums/types/third_party_reach_integration_partner.py create mode 100644 google/ads/googleads/v24/enums/types/third_party_viewability_integration_partner.py create mode 100644 google/ads/googleads/v24/enums/types/time_type.py create mode 100644 google/ads/googleads/v24/enums/types/tracking_code_page_format.py create mode 100644 google/ads/googleads/v24/enums/types/tracking_code_type.py create mode 100644 google/ads/googleads/v24/enums/types/unit_of_measure.py create mode 100644 google/ads/googleads/v24/enums/types/user_identifier_source.py create mode 100644 google/ads/googleads/v24/enums/types/user_interest_taxonomy_type.py create mode 100644 google/ads/googleads/v24/enums/types/user_list_access_status.py create mode 100644 google/ads/googleads/v24/enums/types/user_list_closing_reason.py create mode 100644 google/ads/googleads/v24/enums/types/user_list_crm_data_source_type.py create mode 100644 google/ads/googleads/v24/enums/types/user_list_customer_type_category.py create mode 100644 google/ads/googleads/v24/enums/types/user_list_date_rule_item_operator.py create mode 100644 google/ads/googleads/v24/enums/types/user_list_flexible_rule_operator.py create mode 100644 google/ads/googleads/v24/enums/types/user_list_logical_rule_operator.py create mode 100644 google/ads/googleads/v24/enums/types/user_list_membership_status.py create mode 100644 google/ads/googleads/v24/enums/types/user_list_number_rule_item_operator.py create mode 100644 google/ads/googleads/v24/enums/types/user_list_prepopulation_status.py create mode 100644 google/ads/googleads/v24/enums/types/user_list_rule_type.py create mode 100644 google/ads/googleads/v24/enums/types/user_list_size_range.py create mode 100644 google/ads/googleads/v24/enums/types/user_list_string_rule_item_operator.py create mode 100644 google/ads/googleads/v24/enums/types/user_list_type.py create mode 100644 google/ads/googleads/v24/enums/types/value_rule_device_type.py create mode 100644 google/ads/googleads/v24/enums/types/value_rule_geo_location_match_type.py create mode 100644 google/ads/googleads/v24/enums/types/value_rule_operation.py create mode 100644 google/ads/googleads/v24/enums/types/value_rule_set_attachment_type.py create mode 100644 google/ads/googleads/v24/enums/types/value_rule_set_dimension.py create mode 100644 google/ads/googleads/v24/enums/types/vanity_pharma_display_url_mode.py create mode 100644 google/ads/googleads/v24/enums/types/vanity_pharma_text.py create mode 100644 google/ads/googleads/v24/enums/types/vertical_ads_item_vertical_type.py create mode 100644 google/ads/googleads/v24/enums/types/video_ad_format_restriction.py create mode 100644 google/ads/googleads/v24/enums/types/video_ad_sequence_interaction_type.py create mode 100644 google/ads/googleads/v24/enums/types/video_ad_sequence_minimum_duration.py create mode 100644 google/ads/googleads/v24/enums/types/video_enhancement_source.py create mode 100644 google/ads/googleads/v24/enums/types/video_thumbnail.py create mode 100644 google/ads/googleads/v24/enums/types/webpage_condition_operand.py create mode 100644 google/ads/googleads/v24/enums/types/webpage_condition_operator.py create mode 100644 google/ads/googleads/v24/enums/types/youtube_video_privacy.py create mode 100644 google/ads/googleads/v24/enums/types/youtube_video_property.py create mode 100644 google/ads/googleads/v24/enums/types/youtube_video_upload_state.py create mode 100644 google/ads/googleads/v24/errors/__init__.py create mode 100644 google/ads/googleads/v24/errors/services/__init__.py create mode 100644 google/ads/googleads/v24/errors/types/__init__.py create mode 100644 google/ads/googleads/v24/errors/types/access_invitation_error.py create mode 100644 google/ads/googleads/v24/errors/types/account_budget_proposal_error.py create mode 100644 google/ads/googleads/v24/errors/types/account_link_error.py create mode 100644 google/ads/googleads/v24/errors/types/action_error.py create mode 100644 google/ads/googleads/v24/errors/types/ad_customizer_error.py create mode 100644 google/ads/googleads/v24/errors/types/ad_error.py create mode 100644 google/ads/googleads/v24/errors/types/ad_group_ad_error.py create mode 100644 google/ads/googleads/v24/errors/types/ad_group_bid_modifier_error.py create mode 100644 google/ads/googleads/v24/errors/types/ad_group_criterion_customizer_error.py create mode 100644 google/ads/googleads/v24/errors/types/ad_group_criterion_error.py create mode 100644 google/ads/googleads/v24/errors/types/ad_group_customizer_error.py create mode 100644 google/ads/googleads/v24/errors/types/ad_group_error.py create mode 100644 google/ads/googleads/v24/errors/types/ad_group_feed_error.py create mode 100644 google/ads/googleads/v24/errors/types/ad_parameter_error.py create mode 100644 google/ads/googleads/v24/errors/types/ad_sharing_error.py create mode 100644 google/ads/googleads/v24/errors/types/adx_error.py create mode 100644 google/ads/googleads/v24/errors/types/asset_error.py create mode 100644 google/ads/googleads/v24/errors/types/asset_generation_error.py create mode 100644 google/ads/googleads/v24/errors/types/asset_group_asset_error.py create mode 100644 google/ads/googleads/v24/errors/types/asset_group_error.py create mode 100644 google/ads/googleads/v24/errors/types/asset_group_listing_group_filter_error.py create mode 100644 google/ads/googleads/v24/errors/types/asset_group_signal_error.py create mode 100644 google/ads/googleads/v24/errors/types/asset_link_error.py create mode 100644 google/ads/googleads/v24/errors/types/asset_set_asset_error.py create mode 100644 google/ads/googleads/v24/errors/types/asset_set_error.py create mode 100644 google/ads/googleads/v24/errors/types/asset_set_link_error.py create mode 100644 google/ads/googleads/v24/errors/types/audience_error.py create mode 100644 google/ads/googleads/v24/errors/types/audience_insights_error.py create mode 100644 google/ads/googleads/v24/errors/types/authentication_error.py create mode 100644 google/ads/googleads/v24/errors/types/authorization_error.py create mode 100644 google/ads/googleads/v24/errors/types/automatically_created_asset_removal_error.py create mode 100644 google/ads/googleads/v24/errors/types/batch_job_error.py create mode 100644 google/ads/googleads/v24/errors/types/benchmarks_error.py create mode 100644 google/ads/googleads/v24/errors/types/bidding_error.py create mode 100644 google/ads/googleads/v24/errors/types/bidding_strategy_error.py create mode 100644 google/ads/googleads/v24/errors/types/billing_setup_error.py create mode 100644 google/ads/googleads/v24/errors/types/brand_guidelines_migration_error.py create mode 100644 google/ads/googleads/v24/errors/types/campaign_budget_error.py create mode 100644 google/ads/googleads/v24/errors/types/campaign_conversion_goal_error.py create mode 100644 google/ads/googleads/v24/errors/types/campaign_criterion_error.py create mode 100644 google/ads/googleads/v24/errors/types/campaign_customizer_error.py create mode 100644 google/ads/googleads/v24/errors/types/campaign_draft_error.py create mode 100644 google/ads/googleads/v24/errors/types/campaign_error.py create mode 100644 google/ads/googleads/v24/errors/types/campaign_experiment_error.py create mode 100644 google/ads/googleads/v24/errors/types/campaign_feed_error.py create mode 100644 google/ads/googleads/v24/errors/types/campaign_goal_config_error.py create mode 100644 google/ads/googleads/v24/errors/types/campaign_lifecycle_goal_error.py create mode 100644 google/ads/googleads/v24/errors/types/campaign_shared_set_error.py create mode 100644 google/ads/googleads/v24/errors/types/change_event_error.py create mode 100644 google/ads/googleads/v24/errors/types/change_status_error.py create mode 100644 google/ads/googleads/v24/errors/types/click_view_error.py create mode 100644 google/ads/googleads/v24/errors/types/collection_size_error.py create mode 100644 google/ads/googleads/v24/errors/types/content_creator_insights_error.py create mode 100644 google/ads/googleads/v24/errors/types/context_error.py create mode 100644 google/ads/googleads/v24/errors/types/conversion_action_error.py create mode 100644 google/ads/googleads/v24/errors/types/conversion_adjustment_upload_error.py create mode 100644 google/ads/googleads/v24/errors/types/conversion_custom_variable_error.py create mode 100644 google/ads/googleads/v24/errors/types/conversion_goal_campaign_config_error.py create mode 100644 google/ads/googleads/v24/errors/types/conversion_upload_error.py create mode 100644 google/ads/googleads/v24/errors/types/conversion_value_rule_error.py create mode 100644 google/ads/googleads/v24/errors/types/conversion_value_rule_set_error.py create mode 100644 google/ads/googleads/v24/errors/types/country_code_error.py create mode 100644 google/ads/googleads/v24/errors/types/criterion_error.py create mode 100644 google/ads/googleads/v24/errors/types/currency_code_error.py create mode 100644 google/ads/googleads/v24/errors/types/currency_error.py create mode 100644 google/ads/googleads/v24/errors/types/custom_audience_error.py create mode 100644 google/ads/googleads/v24/errors/types/custom_conversion_goal_error.py create mode 100644 google/ads/googleads/v24/errors/types/custom_interest_error.py create mode 100644 google/ads/googleads/v24/errors/types/customer_client_link_error.py create mode 100644 google/ads/googleads/v24/errors/types/customer_customizer_error.py create mode 100644 google/ads/googleads/v24/errors/types/customer_error.py create mode 100644 google/ads/googleads/v24/errors/types/customer_feed_error.py create mode 100644 google/ads/googleads/v24/errors/types/customer_lifecycle_goal_error.py create mode 100644 google/ads/googleads/v24/errors/types/customer_manager_link_error.py create mode 100644 google/ads/googleads/v24/errors/types/customer_sk_ad_network_conversion_value_schema_error.py create mode 100644 google/ads/googleads/v24/errors/types/customer_user_access_error.py create mode 100644 google/ads/googleads/v24/errors/types/customizer_attribute_error.py create mode 100644 google/ads/googleads/v24/errors/types/data_link_error.py create mode 100644 google/ads/googleads/v24/errors/types/database_error.py create mode 100644 google/ads/googleads/v24/errors/types/date_error.py create mode 100644 google/ads/googleads/v24/errors/types/date_range_error.py create mode 100644 google/ads/googleads/v24/errors/types/distinct_error.py create mode 100644 google/ads/googleads/v24/errors/types/enum_error.py create mode 100644 google/ads/googleads/v24/errors/types/errors.py create mode 100644 google/ads/googleads/v24/errors/types/experiment_arm_error.py create mode 100644 google/ads/googleads/v24/errors/types/experiment_error.py create mode 100644 google/ads/googleads/v24/errors/types/extension_feed_item_error.py create mode 100644 google/ads/googleads/v24/errors/types/extension_setting_error.py create mode 100644 google/ads/googleads/v24/errors/types/feed_attribute_reference_error.py create mode 100644 google/ads/googleads/v24/errors/types/feed_error.py create mode 100644 google/ads/googleads/v24/errors/types/feed_item_error.py create mode 100644 google/ads/googleads/v24/errors/types/feed_item_set_error.py create mode 100644 google/ads/googleads/v24/errors/types/feed_item_set_link_error.py create mode 100644 google/ads/googleads/v24/errors/types/feed_item_target_error.py create mode 100644 google/ads/googleads/v24/errors/types/feed_item_validation_error.py create mode 100644 google/ads/googleads/v24/errors/types/feed_mapping_error.py create mode 100644 google/ads/googleads/v24/errors/types/field_error.py create mode 100644 google/ads/googleads/v24/errors/types/field_mask_error.py create mode 100644 google/ads/googleads/v24/errors/types/final_url_expansion_asset_view_error.py create mode 100644 google/ads/googleads/v24/errors/types/function_error.py create mode 100644 google/ads/googleads/v24/errors/types/function_parsing_error.py create mode 100644 google/ads/googleads/v24/errors/types/geo_target_constant_suggestion_error.py create mode 100644 google/ads/googleads/v24/errors/types/goal_error.py create mode 100644 google/ads/googleads/v24/errors/types/header_error.py create mode 100644 google/ads/googleads/v24/errors/types/id_error.py create mode 100644 google/ads/googleads/v24/errors/types/identity_verification_error.py create mode 100644 google/ads/googleads/v24/errors/types/image_error.py create mode 100644 google/ads/googleads/v24/errors/types/incentive_error.py create mode 100644 google/ads/googleads/v24/errors/types/internal_error.py create mode 100644 google/ads/googleads/v24/errors/types/invoice_error.py create mode 100644 google/ads/googleads/v24/errors/types/keyword_plan_ad_group_error.py create mode 100644 google/ads/googleads/v24/errors/types/keyword_plan_ad_group_keyword_error.py create mode 100644 google/ads/googleads/v24/errors/types/keyword_plan_campaign_error.py create mode 100644 google/ads/googleads/v24/errors/types/keyword_plan_campaign_keyword_error.py create mode 100644 google/ads/googleads/v24/errors/types/keyword_plan_error.py create mode 100644 google/ads/googleads/v24/errors/types/keyword_plan_idea_error.py create mode 100644 google/ads/googleads/v24/errors/types/label_error.py create mode 100644 google/ads/googleads/v24/errors/types/language_code_error.py create mode 100644 google/ads/googleads/v24/errors/types/list_operation_error.py create mode 100644 google/ads/googleads/v24/errors/types/manager_link_error.py create mode 100644 google/ads/googleads/v24/errors/types/media_bundle_error.py create mode 100644 google/ads/googleads/v24/errors/types/media_file_error.py create mode 100644 google/ads/googleads/v24/errors/types/media_upload_error.py create mode 100644 google/ads/googleads/v24/errors/types/merchant_center_error.py create mode 100644 google/ads/googleads/v24/errors/types/multiplier_error.py create mode 100644 google/ads/googleads/v24/errors/types/mutate_error.py create mode 100644 google/ads/googleads/v24/errors/types/new_resource_creation_error.py create mode 100644 google/ads/googleads/v24/errors/types/not_allowlisted_error.py create mode 100644 google/ads/googleads/v24/errors/types/not_empty_error.py create mode 100644 google/ads/googleads/v24/errors/types/null_error.py create mode 100644 google/ads/googleads/v24/errors/types/offline_user_data_job_error.py create mode 100644 google/ads/googleads/v24/errors/types/operation_access_denied_error.py create mode 100644 google/ads/googleads/v24/errors/types/operator_error.py create mode 100644 google/ads/googleads/v24/errors/types/partial_failure_error.py create mode 100644 google/ads/googleads/v24/errors/types/payments_account_error.py create mode 100644 google/ads/googleads/v24/errors/types/policy_finding_error.py create mode 100644 google/ads/googleads/v24/errors/types/policy_validation_parameter_error.py create mode 100644 google/ads/googleads/v24/errors/types/policy_violation_error.py create mode 100644 google/ads/googleads/v24/errors/types/product_link_error.py create mode 100644 google/ads/googleads/v24/errors/types/product_link_invitation_error.py create mode 100644 google/ads/googleads/v24/errors/types/query_error.py create mode 100644 google/ads/googleads/v24/errors/types/quota_error.py create mode 100644 google/ads/googleads/v24/errors/types/range_error.py create mode 100644 google/ads/googleads/v24/errors/types/reach_plan_error.py create mode 100644 google/ads/googleads/v24/errors/types/recommendation_error.py create mode 100644 google/ads/googleads/v24/errors/types/recommendation_subscription_error.py create mode 100644 google/ads/googleads/v24/errors/types/region_code_error.py create mode 100644 google/ads/googleads/v24/errors/types/request_error.py create mode 100644 google/ads/googleads/v24/errors/types/resource_access_denied_error.py create mode 100644 google/ads/googleads/v24/errors/types/resource_count_limit_exceeded_error.py create mode 100644 google/ads/googleads/v24/errors/types/search_term_insight_error.py create mode 100644 google/ads/googleads/v24/errors/types/setting_error.py create mode 100644 google/ads/googleads/v24/errors/types/shareable_preview_error.py create mode 100644 google/ads/googleads/v24/errors/types/shared_criterion_error.py create mode 100644 google/ads/googleads/v24/errors/types/shared_set_error.py create mode 100644 google/ads/googleads/v24/errors/types/shopping_product_error.py create mode 100644 google/ads/googleads/v24/errors/types/size_limit_error.py create mode 100644 google/ads/googleads/v24/errors/types/smart_campaign_error.py create mode 100644 google/ads/googleads/v24/errors/types/string_format_error.py create mode 100644 google/ads/googleads/v24/errors/types/string_length_error.py create mode 100644 google/ads/googleads/v24/errors/types/third_party_app_analytics_link_error.py create mode 100644 google/ads/googleads/v24/errors/types/time_zone_error.py create mode 100644 google/ads/googleads/v24/errors/types/url_field_error.py create mode 100644 google/ads/googleads/v24/errors/types/user_data_error.py create mode 100644 google/ads/googleads/v24/errors/types/user_list_customer_type_error.py create mode 100644 google/ads/googleads/v24/errors/types/user_list_error.py create mode 100644 google/ads/googleads/v24/errors/types/video_campaign_error.py create mode 100644 google/ads/googleads/v24/errors/types/video_reservation_error.py create mode 100644 google/ads/googleads/v24/errors/types/youtube_video_registration_error.py create mode 100644 google/ads/googleads/v24/gapic_metadata.json create mode 100644 google/ads/googleads/v24/gapic_version.py create mode 100644 google/ads/googleads/v24/py.typed create mode 100644 google/ads/googleads/v24/resources/__init__.py create mode 100644 google/ads/googleads/v24/resources/services/__init__.py create mode 100644 google/ads/googleads/v24/resources/types/__init__.py create mode 100644 google/ads/googleads/v24/resources/types/accessible_bidding_strategy.py create mode 100644 google/ads/googleads/v24/resources/types/account_budget.py create mode 100644 google/ads/googleads/v24/resources/types/account_budget_proposal.py create mode 100644 google/ads/googleads/v24/resources/types/account_link.py create mode 100644 google/ads/googleads/v24/resources/types/ad.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_ad.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_ad_asset_combination_view.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_ad_asset_view.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_ad_label.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_asset.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_asset_set.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_audience_view.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_bid_modifier.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_criterion.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_criterion_customizer.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_criterion_label.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_criterion_simulation.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_customizer.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_label.py create mode 100644 google/ads/googleads/v24/resources/types/ad_group_simulation.py create mode 100644 google/ads/googleads/v24/resources/types/ad_parameter.py create mode 100644 google/ads/googleads/v24/resources/types/ad_schedule_view.py create mode 100644 google/ads/googleads/v24/resources/types/age_range_view.py create mode 100644 google/ads/googleads/v24/resources/types/ai_max_search_term_ad_combination_view.py create mode 100644 google/ads/googleads/v24/resources/types/android_privacy_shared_key_google_ad_group.py create mode 100644 google/ads/googleads/v24/resources/types/android_privacy_shared_key_google_campaign.py create mode 100644 google/ads/googleads/v24/resources/types/android_privacy_shared_key_google_network_type.py create mode 100644 google/ads/googleads/v24/resources/types/app_top_combination_view.py create mode 100644 google/ads/googleads/v24/resources/types/applied_incentive.py create mode 100644 google/ads/googleads/v24/resources/types/asset.py create mode 100644 google/ads/googleads/v24/resources/types/asset_field_type_view.py create mode 100644 google/ads/googleads/v24/resources/types/asset_group.py create mode 100644 google/ads/googleads/v24/resources/types/asset_group_asset.py create mode 100644 google/ads/googleads/v24/resources/types/asset_group_listing_group_filter.py create mode 100644 google/ads/googleads/v24/resources/types/asset_group_product_group_view.py create mode 100644 google/ads/googleads/v24/resources/types/asset_group_signal.py create mode 100644 google/ads/googleads/v24/resources/types/asset_group_top_combination_view.py create mode 100644 google/ads/googleads/v24/resources/types/asset_set.py create mode 100644 google/ads/googleads/v24/resources/types/asset_set_asset.py create mode 100644 google/ads/googleads/v24/resources/types/asset_set_type_view.py create mode 100644 google/ads/googleads/v24/resources/types/audience.py create mode 100644 google/ads/googleads/v24/resources/types/batch_job.py create mode 100644 google/ads/googleads/v24/resources/types/bidding_data_exclusion.py create mode 100644 google/ads/googleads/v24/resources/types/bidding_seasonality_adjustment.py create mode 100644 google/ads/googleads/v24/resources/types/bidding_strategy.py create mode 100644 google/ads/googleads/v24/resources/types/bidding_strategy_simulation.py create mode 100644 google/ads/googleads/v24/resources/types/billing_setup.py create mode 100644 google/ads/googleads/v24/resources/types/call_view.py create mode 100644 google/ads/googleads/v24/resources/types/campaign.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_aggregate_asset_view.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_asset.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_asset_set.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_audience_view.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_bid_modifier.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_budget.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_conversion_goal.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_criterion.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_customizer.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_draft.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_goal_config.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_group.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_label.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_lifecycle_goal.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_search_term_insight.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_search_term_view.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_shared_set.py create mode 100644 google/ads/googleads/v24/resources/types/campaign_simulation.py create mode 100644 google/ads/googleads/v24/resources/types/carrier_constant.py create mode 100644 google/ads/googleads/v24/resources/types/cart_data_sales_view.py create mode 100644 google/ads/googleads/v24/resources/types/change_event.py create mode 100644 google/ads/googleads/v24/resources/types/change_status.py create mode 100644 google/ads/googleads/v24/resources/types/channel_aggregate_asset_view.py create mode 100644 google/ads/googleads/v24/resources/types/click_view.py create mode 100644 google/ads/googleads/v24/resources/types/combined_audience.py create mode 100644 google/ads/googleads/v24/resources/types/content_criterion_view.py create mode 100644 google/ads/googleads/v24/resources/types/conversion_action.py create mode 100644 google/ads/googleads/v24/resources/types/conversion_custom_variable.py create mode 100644 google/ads/googleads/v24/resources/types/conversion_goal_campaign_config.py create mode 100644 google/ads/googleads/v24/resources/types/conversion_value_rule.py create mode 100644 google/ads/googleads/v24/resources/types/conversion_value_rule_set.py create mode 100644 google/ads/googleads/v24/resources/types/currency_constant.py create mode 100644 google/ads/googleads/v24/resources/types/custom_audience.py create mode 100644 google/ads/googleads/v24/resources/types/custom_conversion_goal.py create mode 100644 google/ads/googleads/v24/resources/types/custom_interest.py create mode 100644 google/ads/googleads/v24/resources/types/customer.py create mode 100644 google/ads/googleads/v24/resources/types/customer_asset.py create mode 100644 google/ads/googleads/v24/resources/types/customer_asset_set.py create mode 100644 google/ads/googleads/v24/resources/types/customer_client.py create mode 100644 google/ads/googleads/v24/resources/types/customer_client_link.py create mode 100644 google/ads/googleads/v24/resources/types/customer_conversion_goal.py create mode 100644 google/ads/googleads/v24/resources/types/customer_customizer.py create mode 100644 google/ads/googleads/v24/resources/types/customer_label.py create mode 100644 google/ads/googleads/v24/resources/types/customer_lifecycle_goal.py create mode 100644 google/ads/googleads/v24/resources/types/customer_manager_link.py create mode 100644 google/ads/googleads/v24/resources/types/customer_negative_criterion.py create mode 100644 google/ads/googleads/v24/resources/types/customer_search_term_insight.py create mode 100644 google/ads/googleads/v24/resources/types/customer_sk_ad_network_conversion_value_schema.py create mode 100644 google/ads/googleads/v24/resources/types/customer_user_access.py create mode 100644 google/ads/googleads/v24/resources/types/customer_user_access_invitation.py create mode 100644 google/ads/googleads/v24/resources/types/customizer_attribute.py create mode 100644 google/ads/googleads/v24/resources/types/data_link.py create mode 100644 google/ads/googleads/v24/resources/types/detail_content_suitability_placement_view.py create mode 100644 google/ads/googleads/v24/resources/types/detail_placement_view.py create mode 100644 google/ads/googleads/v24/resources/types/detailed_demographic.py create mode 100644 google/ads/googleads/v24/resources/types/display_keyword_view.py create mode 100644 google/ads/googleads/v24/resources/types/distance_view.py create mode 100644 google/ads/googleads/v24/resources/types/domain_category.py create mode 100644 google/ads/googleads/v24/resources/types/dynamic_search_ads_search_term_view.py create mode 100644 google/ads/googleads/v24/resources/types/expanded_landing_page_view.py create mode 100644 google/ads/googleads/v24/resources/types/experiment.py create mode 100644 google/ads/googleads/v24/resources/types/experiment_arm.py create mode 100644 google/ads/googleads/v24/resources/types/final_url_expansion_asset_view.py create mode 100644 google/ads/googleads/v24/resources/types/gender_view.py create mode 100644 google/ads/googleads/v24/resources/types/geo_target_constant.py create mode 100644 google/ads/googleads/v24/resources/types/geographic_view.py create mode 100644 google/ads/googleads/v24/resources/types/goal.py create mode 100644 google/ads/googleads/v24/resources/types/google_ads_field.py create mode 100644 google/ads/googleads/v24/resources/types/group_content_suitability_placement_view.py create mode 100644 google/ads/googleads/v24/resources/types/group_placement_view.py create mode 100644 google/ads/googleads/v24/resources/types/hotel_group_view.py create mode 100644 google/ads/googleads/v24/resources/types/hotel_performance_view.py create mode 100644 google/ads/googleads/v24/resources/types/hotel_reconciliation.py create mode 100644 google/ads/googleads/v24/resources/types/income_range_view.py create mode 100644 google/ads/googleads/v24/resources/types/invoice.py create mode 100644 google/ads/googleads/v24/resources/types/keyword_plan.py create mode 100644 google/ads/googleads/v24/resources/types/keyword_plan_ad_group.py create mode 100644 google/ads/googleads/v24/resources/types/keyword_plan_ad_group_keyword.py create mode 100644 google/ads/googleads/v24/resources/types/keyword_plan_campaign.py create mode 100644 google/ads/googleads/v24/resources/types/keyword_plan_campaign_keyword.py create mode 100644 google/ads/googleads/v24/resources/types/keyword_theme_constant.py create mode 100644 google/ads/googleads/v24/resources/types/keyword_view.py create mode 100644 google/ads/googleads/v24/resources/types/label.py create mode 100644 google/ads/googleads/v24/resources/types/landing_page_view.py create mode 100644 google/ads/googleads/v24/resources/types/language_constant.py create mode 100644 google/ads/googleads/v24/resources/types/lead_form_submission_data.py create mode 100644 google/ads/googleads/v24/resources/types/life_event.py create mode 100644 google/ads/googleads/v24/resources/types/local_services_employee.py create mode 100644 google/ads/googleads/v24/resources/types/local_services_lead.py create mode 100644 google/ads/googleads/v24/resources/types/local_services_lead_conversation.py create mode 100644 google/ads/googleads/v24/resources/types/local_services_verification_artifact.py create mode 100644 google/ads/googleads/v24/resources/types/location_interest_view.py create mode 100644 google/ads/googleads/v24/resources/types/location_view.py create mode 100644 google/ads/googleads/v24/resources/types/managed_placement_view.py create mode 100644 google/ads/googleads/v24/resources/types/matched_location_interest_view.py create mode 100644 google/ads/googleads/v24/resources/types/media_file.py create mode 100644 google/ads/googleads/v24/resources/types/mobile_app_category_constant.py create mode 100644 google/ads/googleads/v24/resources/types/mobile_device_constant.py create mode 100644 google/ads/googleads/v24/resources/types/offline_conversion_upload_client_summary.py create mode 100644 google/ads/googleads/v24/resources/types/offline_conversion_upload_conversion_action_summary.py create mode 100644 google/ads/googleads/v24/resources/types/offline_user_data_job.py create mode 100644 google/ads/googleads/v24/resources/types/operating_system_version_constant.py create mode 100644 google/ads/googleads/v24/resources/types/paid_organic_search_term_view.py create mode 100644 google/ads/googleads/v24/resources/types/parental_status_view.py create mode 100644 google/ads/googleads/v24/resources/types/payments_account.py create mode 100644 google/ads/googleads/v24/resources/types/per_store_view.py create mode 100644 google/ads/googleads/v24/resources/types/performance_max_placement_view.py create mode 100644 google/ads/googleads/v24/resources/types/product_category_constant.py create mode 100644 google/ads/googleads/v24/resources/types/product_group_view.py create mode 100644 google/ads/googleads/v24/resources/types/product_link.py create mode 100644 google/ads/googleads/v24/resources/types/product_link_invitation.py create mode 100644 google/ads/googleads/v24/resources/types/qualifying_question.py create mode 100644 google/ads/googleads/v24/resources/types/recommendation.py create mode 100644 google/ads/googleads/v24/resources/types/recommendation_subscription.py create mode 100644 google/ads/googleads/v24/resources/types/remarketing_action.py create mode 100644 google/ads/googleads/v24/resources/types/search_term_view.py create mode 100644 google/ads/googleads/v24/resources/types/shared_criterion.py create mode 100644 google/ads/googleads/v24/resources/types/shared_set.py create mode 100644 google/ads/googleads/v24/resources/types/shopping_performance_view.py create mode 100644 google/ads/googleads/v24/resources/types/shopping_product.py create mode 100644 google/ads/googleads/v24/resources/types/smart_campaign_search_term_view.py create mode 100644 google/ads/googleads/v24/resources/types/smart_campaign_setting.py create mode 100644 google/ads/googleads/v24/resources/types/targeting_expansion_view.py create mode 100644 google/ads/googleads/v24/resources/types/third_party_app_analytics_link.py create mode 100644 google/ads/googleads/v24/resources/types/topic_constant.py create mode 100644 google/ads/googleads/v24/resources/types/topic_view.py create mode 100644 google/ads/googleads/v24/resources/types/travel_activity_group_view.py create mode 100644 google/ads/googleads/v24/resources/types/travel_activity_performance_view.py create mode 100644 google/ads/googleads/v24/resources/types/user_interest.py create mode 100644 google/ads/googleads/v24/resources/types/user_list.py create mode 100644 google/ads/googleads/v24/resources/types/user_list_customer_type.py create mode 100644 google/ads/googleads/v24/resources/types/user_location_view.py create mode 100644 google/ads/googleads/v24/resources/types/video.py create mode 100644 google/ads/googleads/v24/resources/types/video_enhancement.py create mode 100644 google/ads/googleads/v24/resources/types/webpage_view.py create mode 100644 google/ads/googleads/v24/resources/types/youtube_video_upload.py create mode 100644 google/ads/googleads/v24/services/__init__.py create mode 100644 google/ads/googleads/v24/services/services/__init__.py create mode 100644 google/ads/googleads/v24/services/services/account_budget_proposal_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/account_budget_proposal_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/account_budget_proposal_service/client.py create mode 100644 google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/account_link_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/account_link_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/account_link_service/client.py create mode 100644 google/ads/googleads/v24/services/services/account_link_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/account_link_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/account_link_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/account_link_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/account_link_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_label_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_label_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_label_service/client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_service/client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_ad_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_service/client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_set_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_set_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_set_service/client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_label_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_label_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_label_service/client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_service/client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_customizer_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_customizer_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_customizer_service/client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_label_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_label_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_label_service/client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_label_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/ad_group_label_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_label_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_label_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_label_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_service/client.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/ad_group_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/ad_group_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/ad_parameter_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_parameter_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/ad_parameter_service/client.py create mode 100644 google/ads/googleads/v24/services/services/ad_parameter_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/ad_parameter_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_parameter_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/ad_parameter_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/ad_parameter_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/ad_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/ad_service/client.py create mode 100644 google/ads/googleads/v24/services/services/ad_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/ad_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/ad_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/ad_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/ad_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/asset_generation_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_generation_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/asset_generation_service/client.py create mode 100644 google/ads/googleads/v24/services/services/asset_generation_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/asset_generation_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_generation_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/asset_generation_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/asset_generation_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_asset_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_asset_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_asset_service/client.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_asset_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/asset_group_asset_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_asset_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_asset_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_asset_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/client.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_service/client.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/asset_group_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_signal_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_signal_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_signal_service/client.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_signal_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/asset_group_signal_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_signal_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_signal_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/asset_group_signal_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/asset_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/asset_service/client.py create mode 100644 google/ads/googleads/v24/services/services/asset_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/asset_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/asset_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/asset_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/asset_set_asset_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_set_asset_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/asset_set_asset_service/client.py create mode 100644 google/ads/googleads/v24/services/services/asset_set_asset_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/asset_set_asset_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_set_asset_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/asset_set_asset_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/asset_set_asset_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/asset_set_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_set_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/asset_set_service/client.py create mode 100644 google/ads/googleads/v24/services/services/asset_set_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/asset_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/asset_set_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/asset_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/asset_set_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/audience_insights_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/audience_insights_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/audience_insights_service/client.py create mode 100644 google/ads/googleads/v24/services/services/audience_insights_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/audience_insights_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/audience_insights_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/audience_insights_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/audience_insights_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/audience_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/audience_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/audience_service/client.py create mode 100644 google/ads/googleads/v24/services/services/audience_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/audience_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/audience_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/audience_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/audience_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/client.py create mode 100644 google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/batch_job_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/batch_job_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/batch_job_service/client.py create mode 100644 google/ads/googleads/v24/services/services/batch_job_service/pagers.py create mode 100644 google/ads/googleads/v24/services/services/batch_job_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/batch_job_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/batch_job_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/batch_job_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/batch_job_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/benchmarks_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/benchmarks_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/benchmarks_service/client.py create mode 100644 google/ads/googleads/v24/services/services/benchmarks_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/benchmarks_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/benchmarks_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/benchmarks_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/benchmarks_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/bidding_data_exclusion_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/bidding_data_exclusion_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/bidding_data_exclusion_service/client.py create mode 100644 google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/client.py create mode 100644 google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/bidding_strategy_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/bidding_strategy_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/bidding_strategy_service/client.py create mode 100644 google/ads/googleads/v24/services/services/bidding_strategy_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/bidding_strategy_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/bidding_strategy_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/bidding_strategy_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/bidding_strategy_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/billing_setup_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/billing_setup_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/billing_setup_service/client.py create mode 100644 google/ads/googleads/v24/services/services/billing_setup_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/billing_setup_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/billing_setup_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/billing_setup_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/billing_setup_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/brand_suggestion_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/brand_suggestion_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/brand_suggestion_service/client.py create mode 100644 google/ads/googleads/v24/services/services/brand_suggestion_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/brand_suggestion_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/brand_suggestion_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/brand_suggestion_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/brand_suggestion_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_service/client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_set_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_set_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_set_service/client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/campaign_bid_modifier_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_bid_modifier_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_bid_modifier_service/client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/campaign_budget_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_budget_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_budget_service/client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_budget_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/campaign_budget_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_budget_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/campaign_budget_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/campaign_budget_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/campaign_conversion_goal_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_conversion_goal_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_conversion_goal_service/client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/campaign_criterion_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_criterion_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_criterion_service/client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_criterion_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/campaign_criterion_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_criterion_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/campaign_criterion_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/campaign_criterion_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/campaign_customizer_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_customizer_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_customizer_service/client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_customizer_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/campaign_customizer_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_customizer_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/campaign_customizer_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/campaign_customizer_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/campaign_draft_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_draft_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_draft_service/client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_draft_service/pagers.py create mode 100644 google/ads/googleads/v24/services/services/campaign_draft_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/campaign_draft_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_draft_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/campaign_draft_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/campaign_draft_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/campaign_goal_config_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_goal_config_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_goal_config_service/client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/campaign_group_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_group_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_group_service/client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_group_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/campaign_group_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_group_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/campaign_group_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/campaign_group_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/campaign_label_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_label_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_label_service/client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_label_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/campaign_label_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_label_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/campaign_label_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/campaign_label_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/campaign_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_service/client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/campaign_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/campaign_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/campaign_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/campaign_shared_set_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_shared_set_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_shared_set_service/client.py create mode 100644 google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/content_creator_insights_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/content_creator_insights_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/content_creator_insights_service/client.py create mode 100644 google/ads/googleads/v24/services/services/content_creator_insights_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/content_creator_insights_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/content_creator_insights_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/content_creator_insights_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/content_creator_insights_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/conversion_action_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/conversion_action_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/conversion_action_service/client.py create mode 100644 google/ads/googleads/v24/services/services/conversion_action_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/conversion_action_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/conversion_action_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/conversion_action_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/conversion_action_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/client.py create mode 100644 google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/conversion_custom_variable_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/conversion_custom_variable_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/conversion_custom_variable_service/client.py create mode 100644 google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/client.py create mode 100644 google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/conversion_upload_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/conversion_upload_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/conversion_upload_service/client.py create mode 100644 google/ads/googleads/v24/services/services/conversion_upload_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/conversion_upload_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/conversion_upload_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/conversion_upload_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/conversion_upload_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_service/client.py create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_set_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_set_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_set_service/client.py create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/custom_audience_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/custom_audience_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/custom_audience_service/client.py create mode 100644 google/ads/googleads/v24/services/services/custom_audience_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/custom_audience_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/custom_audience_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/custom_audience_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/custom_audience_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/custom_conversion_goal_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/custom_conversion_goal_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/custom_conversion_goal_service/client.py create mode 100644 google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/custom_interest_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/custom_interest_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/custom_interest_service/client.py create mode 100644 google/ads/googleads/v24/services/services/custom_interest_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/custom_interest_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/custom_interest_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/custom_interest_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/custom_interest_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/customer_asset_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_asset_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/customer_asset_service/client.py create mode 100644 google/ads/googleads/v24/services/services/customer_asset_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/customer_asset_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_asset_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/customer_asset_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/customer_asset_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/customer_asset_set_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_asset_set_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/customer_asset_set_service/client.py create mode 100644 google/ads/googleads/v24/services/services/customer_asset_set_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/customer_asset_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_asset_set_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/customer_asset_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/customer_asset_set_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/customer_client_link_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_client_link_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/customer_client_link_service/client.py create mode 100644 google/ads/googleads/v24/services/services/customer_client_link_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/customer_client_link_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_client_link_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/customer_client_link_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/customer_client_link_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/customer_conversion_goal_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_conversion_goal_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/customer_conversion_goal_service/client.py create mode 100644 google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/customer_customizer_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_customizer_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/customer_customizer_service/client.py create mode 100644 google/ads/googleads/v24/services/services/customer_customizer_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/customer_customizer_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_customizer_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/customer_customizer_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/customer_customizer_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/customer_label_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_label_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/customer_label_service/client.py create mode 100644 google/ads/googleads/v24/services/services/customer_label_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/customer_label_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_label_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/customer_label_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/customer_label_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/client.py create mode 100644 google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/customer_manager_link_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_manager_link_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/customer_manager_link_service/client.py create mode 100644 google/ads/googleads/v24/services/services/customer_manager_link_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/customer_manager_link_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_manager_link_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/customer_manager_link_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/customer_manager_link_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/customer_negative_criterion_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_negative_criterion_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/customer_negative_criterion_service/client.py create mode 100644 google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/customer_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/customer_service/client.py create mode 100644 google/ads/googleads/v24/services/services/customer_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/customer_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/customer_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/customer_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/client.py create mode 100644 google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_invitation_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_invitation_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_invitation_service/client.py create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_service/client.py create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/customer_user_access_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/customizer_attribute_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customizer_attribute_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/customizer_attribute_service/client.py create mode 100644 google/ads/googleads/v24/services/services/customizer_attribute_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/customizer_attribute_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/customizer_attribute_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/customizer_attribute_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/customizer_attribute_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/data_link_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/data_link_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/data_link_service/client.py create mode 100644 google/ads/googleads/v24/services/services/data_link_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/data_link_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/data_link_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/data_link_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/data_link_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/experiment_arm_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/experiment_arm_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/experiment_arm_service/client.py create mode 100644 google/ads/googleads/v24/services/services/experiment_arm_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/experiment_arm_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/experiment_arm_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/experiment_arm_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/experiment_arm_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/experiment_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/experiment_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/experiment_service/client.py create mode 100644 google/ads/googleads/v24/services/services/experiment_service/pagers.py create mode 100644 google/ads/googleads/v24/services/services/experiment_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/experiment_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/experiment_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/experiment_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/experiment_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/geo_target_constant_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/geo_target_constant_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/geo_target_constant_service/client.py create mode 100644 google/ads/googleads/v24/services/services/geo_target_constant_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/geo_target_constant_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/geo_target_constant_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/geo_target_constant_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/geo_target_constant_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/goal_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/goal_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/goal_service/client.py create mode 100644 google/ads/googleads/v24/services/services/goal_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/goal_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/goal_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/goal_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/goal_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_field_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_field_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_field_service/client.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_field_service/pagers.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_field_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/google_ads_field_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_field_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_field_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_field_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_service/client.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_service/pagers.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/google_ads_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/google_ads_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/identity_verification_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/identity_verification_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/identity_verification_service/client.py create mode 100644 google/ads/googleads/v24/services/services/identity_verification_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/identity_verification_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/identity_verification_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/identity_verification_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/identity_verification_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/incentive_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/incentive_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/incentive_service/client.py create mode 100644 google/ads/googleads/v24/services/services/incentive_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/incentive_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/incentive_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/incentive_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/incentive_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/invoice_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/invoice_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/invoice_service/client.py create mode 100644 google/ads/googleads/v24/services/services/invoice_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/invoice_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/invoice_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/invoice_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/invoice_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/client.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/client.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/client.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_service/client.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_idea_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_idea_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_idea_service/client.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_idea_service/pagers.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_service/client.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/keyword_plan_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/keyword_theme_constant_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/keyword_theme_constant_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/keyword_theme_constant_service/client.py create mode 100644 google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/label_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/label_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/label_service/client.py create mode 100644 google/ads/googleads/v24/services/services/label_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/label_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/label_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/label_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/label_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/local_services_lead_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/local_services_lead_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/local_services_lead_service/client.py create mode 100644 google/ads/googleads/v24/services/services/local_services_lead_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/local_services_lead_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/local_services_lead_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/local_services_lead_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/local_services_lead_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/offline_user_data_job_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/offline_user_data_job_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/offline_user_data_job_service/client.py create mode 100644 google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/payments_account_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/payments_account_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/payments_account_service/client.py create mode 100644 google/ads/googleads/v24/services/services/payments_account_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/payments_account_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/payments_account_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/payments_account_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/payments_account_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/product_link_invitation_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/product_link_invitation_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/product_link_invitation_service/client.py create mode 100644 google/ads/googleads/v24/services/services/product_link_invitation_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/product_link_invitation_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/product_link_invitation_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/product_link_invitation_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/product_link_invitation_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/product_link_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/product_link_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/product_link_service/client.py create mode 100644 google/ads/googleads/v24/services/services/product_link_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/product_link_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/product_link_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/product_link_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/product_link_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/reach_plan_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/reach_plan_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/reach_plan_service/client.py create mode 100644 google/ads/googleads/v24/services/services/reach_plan_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/reach_plan_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/reach_plan_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/reach_plan_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/reach_plan_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/recommendation_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/recommendation_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/recommendation_service/client.py create mode 100644 google/ads/googleads/v24/services/services/recommendation_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/recommendation_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/recommendation_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/recommendation_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/recommendation_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/recommendation_subscription_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/recommendation_subscription_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/recommendation_subscription_service/client.py create mode 100644 google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/remarketing_action_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/remarketing_action_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/remarketing_action_service/client.py create mode 100644 google/ads/googleads/v24/services/services/remarketing_action_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/remarketing_action_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/remarketing_action_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/remarketing_action_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/remarketing_action_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/reservation_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/reservation_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/reservation_service/client.py create mode 100644 google/ads/googleads/v24/services/services/reservation_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/reservation_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/reservation_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/reservation_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/reservation_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/shareable_preview_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/shareable_preview_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/shareable_preview_service/client.py create mode 100644 google/ads/googleads/v24/services/services/shareable_preview_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/shareable_preview_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/shareable_preview_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/shareable_preview_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/shareable_preview_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/shared_criterion_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/shared_criterion_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/shared_criterion_service/client.py create mode 100644 google/ads/googleads/v24/services/services/shared_criterion_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/shared_criterion_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/shared_criterion_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/shared_criterion_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/shared_criterion_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/shared_set_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/shared_set_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/shared_set_service/client.py create mode 100644 google/ads/googleads/v24/services/services/shared_set_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/shared_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/shared_set_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/shared_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/shared_set_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_setting_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_setting_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_setting_service/client.py create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_suggest_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_suggest_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_suggest_service/client.py create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/client.py create mode 100644 google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/travel_asset_suggestion_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/travel_asset_suggestion_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/travel_asset_suggestion_service/client.py create mode 100644 google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/user_data_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/user_data_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/user_data_service/client.py create mode 100644 google/ads/googleads/v24/services/services/user_data_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/user_data_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/user_data_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/user_data_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/user_data_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/user_list_customer_type_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/user_list_customer_type_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/user_list_customer_type_service/client.py create mode 100644 google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/user_list_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/user_list_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/user_list_service/client.py create mode 100644 google/ads/googleads/v24/services/services/user_list_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/user_list_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/user_list_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/user_list_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/user_list_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/you_tube_video_upload_service/__init__.py create mode 100644 google/ads/googleads/v24/services/services/you_tube_video_upload_service/async_client.py create mode 100644 google/ads/googleads/v24/services/services/you_tube_video_upload_service/client.py create mode 100644 google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/README.rst create mode 100644 google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/__init__.py create mode 100644 google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/base.py create mode 100644 google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/grpc.py create mode 100644 google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/grpc_asyncio.py create mode 100644 google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/rest_resumable.py create mode 100644 google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/rest_resumable_base.py create mode 100644 google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/resumable_upload.py create mode 100644 google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/resumable_upload_error_adapter.py create mode 100644 google/ads/googleads/v24/services/types/__init__.py create mode 100644 google/ads/googleads/v24/services/types/account_budget_proposal_service.py create mode 100644 google/ads/googleads/v24/services/types/account_link_service.py create mode 100644 google/ads/googleads/v24/services/types/ad_group_ad_label_service.py create mode 100644 google/ads/googleads/v24/services/types/ad_group_ad_service.py create mode 100644 google/ads/googleads/v24/services/types/ad_group_asset_service.py create mode 100644 google/ads/googleads/v24/services/types/ad_group_asset_set_service.py create mode 100644 google/ads/googleads/v24/services/types/ad_group_bid_modifier_service.py create mode 100644 google/ads/googleads/v24/services/types/ad_group_criterion_customizer_service.py create mode 100644 google/ads/googleads/v24/services/types/ad_group_criterion_label_service.py create mode 100644 google/ads/googleads/v24/services/types/ad_group_criterion_service.py create mode 100644 google/ads/googleads/v24/services/types/ad_group_customizer_service.py create mode 100644 google/ads/googleads/v24/services/types/ad_group_label_service.py create mode 100644 google/ads/googleads/v24/services/types/ad_group_service.py create mode 100644 google/ads/googleads/v24/services/types/ad_parameter_service.py create mode 100644 google/ads/googleads/v24/services/types/ad_service.py create mode 100644 google/ads/googleads/v24/services/types/asset_generation_service.py create mode 100644 google/ads/googleads/v24/services/types/asset_group_asset_service.py create mode 100644 google/ads/googleads/v24/services/types/asset_group_listing_group_filter_service.py create mode 100644 google/ads/googleads/v24/services/types/asset_group_service.py create mode 100644 google/ads/googleads/v24/services/types/asset_group_signal_service.py create mode 100644 google/ads/googleads/v24/services/types/asset_service.py create mode 100644 google/ads/googleads/v24/services/types/asset_set_asset_service.py create mode 100644 google/ads/googleads/v24/services/types/asset_set_service.py create mode 100644 google/ads/googleads/v24/services/types/audience_insights_service.py create mode 100644 google/ads/googleads/v24/services/types/audience_service.py create mode 100644 google/ads/googleads/v24/services/types/automatically_created_asset_removal_service.py create mode 100644 google/ads/googleads/v24/services/types/batch_job_service.py create mode 100644 google/ads/googleads/v24/services/types/benchmarks_service.py create mode 100644 google/ads/googleads/v24/services/types/bidding_data_exclusion_service.py create mode 100644 google/ads/googleads/v24/services/types/bidding_seasonality_adjustment_service.py create mode 100644 google/ads/googleads/v24/services/types/bidding_strategy_service.py create mode 100644 google/ads/googleads/v24/services/types/billing_setup_service.py create mode 100644 google/ads/googleads/v24/services/types/brand_suggestion_service.py create mode 100644 google/ads/googleads/v24/services/types/campaign_asset_service.py create mode 100644 google/ads/googleads/v24/services/types/campaign_asset_set_service.py create mode 100644 google/ads/googleads/v24/services/types/campaign_bid_modifier_service.py create mode 100644 google/ads/googleads/v24/services/types/campaign_budget_service.py create mode 100644 google/ads/googleads/v24/services/types/campaign_conversion_goal_service.py create mode 100644 google/ads/googleads/v24/services/types/campaign_criterion_service.py create mode 100644 google/ads/googleads/v24/services/types/campaign_customizer_service.py create mode 100644 google/ads/googleads/v24/services/types/campaign_draft_service.py create mode 100644 google/ads/googleads/v24/services/types/campaign_goal_config_service.py create mode 100644 google/ads/googleads/v24/services/types/campaign_group_service.py create mode 100644 google/ads/googleads/v24/services/types/campaign_label_service.py create mode 100644 google/ads/googleads/v24/services/types/campaign_lifecycle_goal_service.py create mode 100644 google/ads/googleads/v24/services/types/campaign_service.py create mode 100644 google/ads/googleads/v24/services/types/campaign_shared_set_service.py create mode 100644 google/ads/googleads/v24/services/types/content_creator_insights_service.py create mode 100644 google/ads/googleads/v24/services/types/conversion_action_service.py create mode 100644 google/ads/googleads/v24/services/types/conversion_adjustment_upload_service.py create mode 100644 google/ads/googleads/v24/services/types/conversion_custom_variable_service.py create mode 100644 google/ads/googleads/v24/services/types/conversion_goal_campaign_config_service.py create mode 100644 google/ads/googleads/v24/services/types/conversion_upload_service.py create mode 100644 google/ads/googleads/v24/services/types/conversion_value_rule_service.py create mode 100644 google/ads/googleads/v24/services/types/conversion_value_rule_set_service.py create mode 100644 google/ads/googleads/v24/services/types/custom_audience_service.py create mode 100644 google/ads/googleads/v24/services/types/custom_conversion_goal_service.py create mode 100644 google/ads/googleads/v24/services/types/custom_interest_service.py create mode 100644 google/ads/googleads/v24/services/types/customer_asset_service.py create mode 100644 google/ads/googleads/v24/services/types/customer_asset_set_service.py create mode 100644 google/ads/googleads/v24/services/types/customer_client_link_service.py create mode 100644 google/ads/googleads/v24/services/types/customer_conversion_goal_service.py create mode 100644 google/ads/googleads/v24/services/types/customer_customizer_service.py create mode 100644 google/ads/googleads/v24/services/types/customer_label_service.py create mode 100644 google/ads/googleads/v24/services/types/customer_lifecycle_goal_service.py create mode 100644 google/ads/googleads/v24/services/types/customer_manager_link_service.py create mode 100644 google/ads/googleads/v24/services/types/customer_negative_criterion_service.py create mode 100644 google/ads/googleads/v24/services/types/customer_service.py create mode 100644 google/ads/googleads/v24/services/types/customer_sk_ad_network_conversion_value_schema_service.py create mode 100644 google/ads/googleads/v24/services/types/customer_user_access_invitation_service.py create mode 100644 google/ads/googleads/v24/services/types/customer_user_access_service.py create mode 100644 google/ads/googleads/v24/services/types/customizer_attribute_service.py create mode 100644 google/ads/googleads/v24/services/types/data_link_service.py create mode 100644 google/ads/googleads/v24/services/types/experiment_arm_service.py create mode 100644 google/ads/googleads/v24/services/types/experiment_service.py create mode 100644 google/ads/googleads/v24/services/types/geo_target_constant_service.py create mode 100644 google/ads/googleads/v24/services/types/goal_service.py create mode 100644 google/ads/googleads/v24/services/types/google_ads_field_service.py create mode 100644 google/ads/googleads/v24/services/types/google_ads_service.py create mode 100644 google/ads/googleads/v24/services/types/identity_verification_service.py create mode 100644 google/ads/googleads/v24/services/types/incentive_service.py create mode 100644 google/ads/googleads/v24/services/types/invoice_service.py create mode 100644 google/ads/googleads/v24/services/types/keyword_plan_ad_group_keyword_service.py create mode 100644 google/ads/googleads/v24/services/types/keyword_plan_ad_group_service.py create mode 100644 google/ads/googleads/v24/services/types/keyword_plan_campaign_keyword_service.py create mode 100644 google/ads/googleads/v24/services/types/keyword_plan_campaign_service.py create mode 100644 google/ads/googleads/v24/services/types/keyword_plan_idea_service.py create mode 100644 google/ads/googleads/v24/services/types/keyword_plan_service.py create mode 100644 google/ads/googleads/v24/services/types/keyword_theme_constant_service.py create mode 100644 google/ads/googleads/v24/services/types/label_service.py create mode 100644 google/ads/googleads/v24/services/types/local_services_lead_service.py create mode 100644 google/ads/googleads/v24/services/types/offline_user_data_job_service.py create mode 100644 google/ads/googleads/v24/services/types/payments_account_service.py create mode 100644 google/ads/googleads/v24/services/types/product_link_invitation_service.py create mode 100644 google/ads/googleads/v24/services/types/product_link_service.py create mode 100644 google/ads/googleads/v24/services/types/reach_plan_service.py create mode 100644 google/ads/googleads/v24/services/types/recommendation_service.py create mode 100644 google/ads/googleads/v24/services/types/recommendation_subscription_service.py create mode 100644 google/ads/googleads/v24/services/types/remarketing_action_service.py create mode 100644 google/ads/googleads/v24/services/types/reservation_service.py create mode 100644 google/ads/googleads/v24/services/types/shareable_preview_service.py create mode 100644 google/ads/googleads/v24/services/types/shared_criterion_service.py create mode 100644 google/ads/googleads/v24/services/types/shared_set_service.py create mode 100644 google/ads/googleads/v24/services/types/smart_campaign_setting_service.py create mode 100644 google/ads/googleads/v24/services/types/smart_campaign_suggest_service.py create mode 100644 google/ads/googleads/v24/services/types/third_party_app_analytics_link_service.py create mode 100644 google/ads/googleads/v24/services/types/travel_asset_suggestion_service.py create mode 100644 google/ads/googleads/v24/services/types/user_data_service.py create mode 100644 google/ads/googleads/v24/services/types/user_list_customer_type_service.py create mode 100644 google/ads/googleads/v24/services/types/user_list_service.py create mode 100644 google/ads/googleads/v24/services/types/youtube_video_upload_service.py diff --git a/ChangeLog b/ChangeLog index 8f2edcc41..97ef96e86 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +* 30.1.0 +- Google Ads API v24 release. +- Update examples to use Google Ads API v24. +- Fix apply_incentive example to make country code required. (#1070) +- Fix 'UnaryUnaryCall' object has no attribute 'exception' error in async requests (#1061) +- Update Generate Forecast Metrics example for v24 + * 30.0.0 - Google Ads API v23_2 release. - Fix config module so that login_customer_id=None doesn't raise an error. diff --git a/examples/account_management/create_customer.py b/examples/account_management/create_customer.py index e0eeb166f..cfe48811c 100755 --- a/examples/account_management/create_customer.py +++ b/examples/account_management/create_customer.py @@ -20,18 +20,17 @@ account. """ - import argparse import sys from datetime import datetime from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.customer import Customer -from google.ads.googleads.v23.services.services.customer_service.client import ( +from google.ads.googleads.v24.resources.types.customer import Customer +from google.ads.googleads.v24.services.services.customer_service.client import ( CustomerServiceClient, ) -from google.ads.googleads.v23.services.types.customer_service import ( +from google.ads.googleads.v24.services.types.customer_service import ( CreateCustomerClientResponse, ) @@ -91,7 +90,7 @@ def main(client: GoogleAdsClient, manager_customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main(googleads_client, args.manager_customer_id) diff --git a/examples/account_management/get_account_hierarchy.py b/examples/account_management/get_account_hierarchy.py index 4c051b68c..ef81d3c60 100755 --- a/examples/account_management/get_account_hierarchy.py +++ b/examples/account_management/get_account_hierarchy.py @@ -28,16 +28,16 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.google_ads_service.client import ( +from google.ads.googleads.v24.services.services.google_ads_service.client import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.services.customer_service.client import ( +from google.ads.googleads.v24.services.services.customer_service.client import ( CustomerServiceClient, ) -from google.ads.googleads.v23.resources.types.customer_client import ( +from google.ads.googleads.v24.resources.types.customer_client import ( CustomerClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( SearchPagedResponse, GoogleAdsRow, ) @@ -238,7 +238,7 @@ def print_account_hierarchy( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main(googleads_client, args.login_customer_id) except GoogleAdsException as ex: diff --git a/examples/account_management/get_change_details.py b/examples/account_management/get_change_details.py index 01c01e527..7ec79ff73 100755 --- a/examples/account_management/get_change_details.py +++ b/examples/account_management/get_change_details.py @@ -28,15 +28,15 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException from google.ads.googleads.util import get_nested_attr -from google.ads.googleads.v23.services.services.google_ads_service.client import ( +from google.ads.googleads.v24.services.services.google_ads_service.client import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( SearchGoogleAdsRequest, SearchPagedResponse, GoogleAdsRow, ) -from google.ads.googleads.v23.resources.types.change_event import ChangeEvent +from google.ads.googleads.v24.resources.types.change_event import ChangeEvent # [START get_change_details] @@ -218,7 +218,7 @@ def main(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main(googleads_client, args.customer_id) except GoogleAdsException as ex: diff --git a/examples/account_management/get_change_summary.py b/examples/account_management/get_change_summary.py index 69ee96ed4..44d549c60 100755 --- a/examples/account_management/get_change_summary.py +++ b/examples/account_management/get_change_summary.py @@ -16,21 +16,20 @@ """This example gets a list of which resources have been changed in an account.""" - import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.google_ads_service.client import ( +from google.ads.googleads.v24.services.services.google_ads_service.client import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( SearchGoogleAdsRequest, SearchPagedResponse, GoogleAdsRow, ) -from google.ads.googleads.v23.resources.types.change_status import ChangeStatus +from google.ads.googleads.v24.resources.types.change_status import ChangeStatus # [START get_change_summary] @@ -110,7 +109,7 @@ def main(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main(googleads_client, args.customer_id) diff --git a/examples/account_management/invite_user_with_access_role.py b/examples/account_management/invite_user_with_access_role.py index 89d2407a7..f649a40d8 100755 --- a/examples/account_management/invite_user_with_access_role.py +++ b/examples/account_management/invite_user_with_access_role.py @@ -17,24 +17,23 @@ The invitation is to manage a customer account with a desired access role. """ - import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.customer_user_access_invitation_service.client import ( +from google.ads.googleads.v24.services.services.customer_user_access_invitation_service.client import ( CustomerUserAccessInvitationServiceClient, ) -from google.ads.googleads.v23.services.types.customer_user_access_invitation_service import ( +from google.ads.googleads.v24.services.types.customer_user_access_invitation_service import ( CustomerUserAccessInvitationOperation, MutateCustomerUserAccessInvitationResponse, ) -from google.ads.googleads.v23.resources.types.customer_user_access_invitation import ( +from google.ads.googleads.v24.resources.types.customer_user_access_invitation import ( CustomerUserAccessInvitation, ) -# AccessRoleEnum is part of google.ads.googleads.v23.enums.types.access_role +# AccessRoleEnum is part of google.ads.googleads.v24.enums.types.access_role # but it's accessed via client.enums.AccessRoleEnum, so direct import for type hint might not be strictly needed for the parameter. # The field invitation.access_role expects an int (the enum value). @@ -115,7 +114,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main( diff --git a/examples/account_management/link_manager_to_client.py b/examples/account_management/link_manager_to_client.py index 25ec4e92b..5db5bbbf8 100755 --- a/examples/account_management/link_manager_to_client.py +++ b/examples/account_management/link_manager_to_client.py @@ -22,31 +22,31 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.customer_client_link_service.client import ( +from google.ads.googleads.v24.services.services.customer_client_link_service.client import ( CustomerClientLinkServiceClient, ) -from google.ads.googleads.v23.services.types.customer_client_link_service import ( +from google.ads.googleads.v24.services.types.customer_client_link_service import ( CustomerClientLinkOperation, MutateCustomerClientLinkResponse, ) -from google.ads.googleads.v23.resources.types.customer_client_link import ( +from google.ads.googleads.v24.resources.types.customer_client_link import ( CustomerClientLink, ) -from google.ads.googleads.v23.services.services.google_ads_service.client import ( +from google.ads.googleads.v24.services.services.google_ads_service.client import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( SearchPagedResponse, GoogleAdsRow, ) -from google.ads.googleads.v23.services.services.customer_manager_link_service.client import ( +from google.ads.googleads.v24.services.services.customer_manager_link_service.client import ( CustomerManagerLinkServiceClient, ) -from google.ads.googleads.v23.services.types.customer_manager_link_service import ( +from google.ads.googleads.v24.services.types.customer_manager_link_service import ( CustomerManagerLinkOperation, MutateCustomerManagerLinkResponse, ) -from google.ads.googleads.v23.resources.types.customer_manager_link import ( +from google.ads.googleads.v24.resources.types.customer_manager_link import ( CustomerManagerLink, ) @@ -179,7 +179,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main(googleads_client, args.customer_id, args.manager_customer_id) except GoogleAdsException as ex: diff --git a/examples/account_management/list_accessible_customers.py b/examples/account_management/list_accessible_customers.py index 5f0c5f4eb..2d156ff2c 100755 --- a/examples/account_management/list_accessible_customers.py +++ b/examples/account_management/list_accessible_customers.py @@ -20,16 +20,15 @@ documentation: https://developers.google.com/google-ads/api/docs/concepts/call-structure#cid """ - import sys from typing import List from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.customer_service.client import ( +from google.ads.googleads.v24.services.services.customer_service.client import ( CustomerServiceClient, ) -from google.ads.googleads.v23.services.types.customer_service import ( +from google.ads.googleads.v24.services.types.customer_service import ( ListAccessibleCustomersResponse, ) @@ -55,7 +54,7 @@ def main(client: GoogleAdsClient) -> None: if __name__ == "__main__": # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main(googleads_client) diff --git a/examples/account_management/update_user_access.py b/examples/account_management/update_user_access.py index af0396e84..9b20cb81a 100755 --- a/examples/account_management/update_user_access.py +++ b/examples/account_management/update_user_access.py @@ -26,20 +26,20 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.google_ads_service.client import ( +from google.ads.googleads.v24.services.services.google_ads_service.client import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( SearchGoogleAdsRequest, SearchPagedResponse, ) -from google.ads.googleads.v23.resources.types.customer_user_access import ( +from google.ads.googleads.v24.resources.types.customer_user_access import ( CustomerUserAccess, ) -from google.ads.googleads.v23.services.services.customer_user_access_service.client import ( +from google.ads.googleads.v24.services.services.customer_user_access_service.client import ( CustomerUserAccessServiceClient, ) -from google.ads.googleads.v23.services.types.customer_user_access_service import ( +from google.ads.googleads.v24.services.types.customer_user_access_service import ( CustomerUserAccessOperation, MutateCustomerUserAccessResponse, ) @@ -219,7 +219,7 @@ def modify_user_access( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main( googleads_client, diff --git a/examples/account_management/verify_advertiser_identity.py b/examples/account_management/verify_advertiser_identity.py index ce459889c..fb0995160 100755 --- a/examples/account_management/verify_advertiser_identity.py +++ b/examples/account_management/verify_advertiser_identity.py @@ -17,20 +17,19 @@ If required and not already started, it also starts the verification process. """ - import argparse import sys from typing import Optional from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.enums.types.identity_verification_program_status import ( +from google.ads.googleads.v24.enums.types.identity_verification_program_status import ( IdentityVerificationProgramStatusEnum, ) -from google.ads.googleads.v23.services.services.identity_verification_service.client import ( +from google.ads.googleads.v24.services.services.identity_verification_service.client import ( IdentityVerificationServiceClient, ) -from google.ads.googleads.v23.services.types.identity_verification_service import ( +from google.ads.googleads.v24.services.types.identity_verification_service import ( GetIdentityVerificationResponse, IdentityVerification, IdentityVerificationProgress, @@ -183,7 +182,7 @@ def start_identity_verification( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main(googleads_client, args.customer_id) diff --git a/examples/advanced_operations/add_ad_customizer.py b/examples/advanced_operations/add_ad_customizer.py index 8b3f33c17..0b072ba7a 100755 --- a/examples/advanced_operations/add_ad_customizer.py +++ b/examples/advanced_operations/add_ad_customizer.py @@ -18,32 +18,31 @@ customizer attributes to populate dynamic data. """ - import argparse import sys from uuid import uuid4 from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types import AdTextAsset -from google.ads.googleads.v23.resources.types import ( +from google.ads.googleads.v24.common.types import AdTextAsset +from google.ads.googleads.v24.resources.types import ( AdGroupAd, AdGroupCustomizer, CustomizerAttribute, ) -from google.ads.googleads.v23.services.services.ad_group_ad_service import ( +from google.ads.googleads.v24.services.services.ad_group_ad_service import ( AdGroupAdServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_customizer_service import ( +from google.ads.googleads.v24.services.services.ad_group_customizer_service import ( AdGroupCustomizerServiceClient, ) -from google.ads.googleads.v23.services.services.customizer_attribute_service import ( +from google.ads.googleads.v24.services.services.customizer_attribute_service import ( CustomizerAttributeServiceClient, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types import ( +from google.ads.googleads.v24.services.types import ( AdGroupAdOperation, AdGroupCustomizerOperation, CustomizerAttributeOperation, @@ -342,7 +341,7 @@ def create_ad_with_customizations( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/advanced_operations/add_ad_group_bid_modifier.py b/examples/advanced_operations/add_ad_group_bid_modifier.py index 37fee7768..9623bada9 100755 --- a/examples/advanced_operations/add_ad_group_bid_modifier.py +++ b/examples/advanced_operations/add_ad_group_bid_modifier.py @@ -17,23 +17,22 @@ To get ad group bid modifiers, run get_ad_group_bid_modifiers.py """ - import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.enums.types.device import DeviceEnum -from google.ads.googleads.v23.resources.types.ad_group_bid_modifier import ( +from google.ads.googleads.v24.enums.types.device import DeviceEnum +from google.ads.googleads.v24.resources.types.ad_group_bid_modifier import ( AdGroupBidModifier, ) -from google.ads.googleads.v23.services.services.ad_group_bid_modifier_service import ( +from google.ads.googleads.v24.services.services.ad_group_bid_modifier_service import ( AdGroupBidModifierServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_bid_modifier_service import ( +from google.ads.googleads.v24.services.types.ad_group_bid_modifier_service import ( AdGroupBidModifierOperation, MutateAdGroupBidModifiersResponse, ) @@ -120,7 +119,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/advanced_operations/add_app_campaign.py b/examples/advanced_operations/add_app_campaign.py index 197f040bc..5e3c00f00 100755 --- a/examples/advanced_operations/add_app_campaign.py +++ b/examples/advanced_operations/add_app_campaign.py @@ -21,7 +21,6 @@ To upload image assets for this campaign, run misc/upload_image_asset.py. """ - import argparse from datetime import datetime, timedelta import sys @@ -30,36 +29,36 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types import AdTextAsset -from google.ads.googleads.v23.resources.types import ( +from google.ads.googleads.v24.common.types import AdTextAsset +from google.ads.googleads.v24.resources.types import ( AdGroup, AdGroupAd, Campaign, CampaignBudget, CampaignCriterion, ) -from google.ads.googleads.v23.services.services.ad_group_ad_service import ( +from google.ads.googleads.v24.services.services.ad_group_ad_service import ( AdGroupAdServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_budget_service import ( +from google.ads.googleads.v24.services.services.campaign_budget_service import ( CampaignBudgetServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_criterion_service import ( +from google.ads.googleads.v24.services.services.campaign_criterion_service import ( CampaignCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.services.geo_target_constant_service import ( +from google.ads.googleads.v24.services.services.geo_target_constant_service import ( GeoTargetConstantServiceClient, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types import * +from google.ads.googleads.v24.services.types import * def main(client: GoogleAdsClient, customer_id: str) -> None: @@ -184,8 +183,12 @@ def create_campaign( ) # Optional fields - campaign.start_date_time = (datetime.now() + timedelta(1)).strftime("%Y%m%d 00:00:00") - campaign.end_date_time = (datetime.now() + timedelta(365)).strftime("%Y%m%d 23:59:59") + campaign.start_date_time = (datetime.now() + timedelta(1)).strftime( + "%Y%m%d 00:00:00" + ) + campaign.end_date_time = (datetime.now() + timedelta(365)).strftime( + "%Y%m%d 23:59:59" + ) # Optional: If you select the # OPTIMIZE_IN_APP_CONVERSIONS_TARGET_INSTALL_COST goal type, then also # specify your in-app conversion types so the Google Ads API can focus @@ -392,7 +395,7 @@ def create_ad_text_asset(client: GoogleAdsClient, text: str) -> AdTextAsset: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/advanced_operations/add_bidding_data_exclusion.py b/examples/advanced_operations/add_bidding_data_exclusion.py index e65e2ae53..7acd66210 100755 --- a/examples/advanced_operations/add_bidding_data_exclusion.py +++ b/examples/advanced_operations/add_bidding_data_exclusion.py @@ -21,20 +21,19 @@ https://developers.google.com/google-ads/api/docs/campaigns/bidding/data-exclusions """ - import argparse import sys from uuid import uuid4 from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.bidding_data_exclusion import ( +from google.ads.googleads.v24.resources.types.bidding_data_exclusion import ( BiddingDataExclusion, ) -from google.ads.googleads.v23.services.services.bidding_data_exclusion_service import ( +from google.ads.googleads.v24.services.services.bidding_data_exclusion_service import ( BiddingDataExclusionServiceClient, ) -from google.ads.googleads.v23.services.types.bidding_data_exclusion_service import ( +from google.ads.googleads.v24.services.types.bidding_data_exclusion_service import ( BiddingDataExclusionOperation, MutateBiddingDataExclusionsResponse, ) @@ -131,7 +130,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/advanced_operations/add_bidding_seasonality_adjustment.py b/examples/advanced_operations/add_bidding_seasonality_adjustment.py index 56656dc52..15f82fadb 100755 --- a/examples/advanced_operations/add_bidding_seasonality_adjustment.py +++ b/examples/advanced_operations/add_bidding_seasonality_adjustment.py @@ -21,20 +21,19 @@ https://developers.google.com/google-ads/api/docs/campaigns/bidding/seasonality-adjustments """ - import argparse import sys from uuid import uuid4 from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.bidding_seasonality_adjustment import ( +from google.ads.googleads.v24.resources.types.bidding_seasonality_adjustment import ( BiddingSeasonalityAdjustment, ) -from google.ads.googleads.v23.services.services.bidding_seasonality_adjustment_service import ( +from google.ads.googleads.v24.services.services.bidding_seasonality_adjustment_service import ( BiddingSeasonalityAdjustmentServiceClient, ) -from google.ads.googleads.v23.services.types.bidding_seasonality_adjustment_service import ( +from google.ads.googleads.v24.services.types.bidding_seasonality_adjustment_service import ( BiddingSeasonalityAdjustmentOperation, MutateBiddingSeasonalityAdjustmentsResponse, ) @@ -150,7 +149,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/advanced_operations/add_demand_gen_campaign.py b/examples/advanced_operations/add_demand_gen_campaign.py index 3ef6b955e..3ea5e9049 100644 --- a/examples/advanced_operations/add_demand_gen_campaign.py +++ b/examples/advanced_operations/add_demand_gen_campaign.py @@ -25,13 +25,13 @@ from examples.utils.example_helpers import get_image_bytes_from_url from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types import ( +from google.ads.googleads.v24.common.types import ( AdImageAsset, AdTextAsset, AdVideoAsset, DemandGenVideoResponsiveAdInfo, ) -from google.ads.googleads.v23.resources.types import ( +from google.ads.googleads.v24.resources.types import ( Ad, AdGroup, AdGroupAd, @@ -39,10 +39,10 @@ Campaign, CampaignBudget, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types import ( +from google.ads.googleads.v24.services.types import ( AdGroupAdOperation, AdGroupOperation, AssetOperation, @@ -430,7 +430,7 @@ def create_video_asset_operation( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/advanced_operations/add_display_upload_ad.py b/examples/advanced_operations/add_display_upload_ad.py index 5802561e4..2c1f0ded6 100644 --- a/examples/advanced_operations/add_display_upload_ad.py +++ b/examples/advanced_operations/add_display_upload_ad.py @@ -17,7 +17,6 @@ To get ad groups, run get_ad_groups.py. """ - import argparse import sys @@ -25,25 +24,24 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.ad import Ad -from google.ads.googleads.v23.resources.types.ad_group_ad import AdGroupAd -from google.ads.googleads.v23.resources.types.asset import Asset -from google.ads.googleads.v23.services.services.ad_group_ad_service import ( +from google.ads.googleads.v24.resources.types.ad import Ad +from google.ads.googleads.v24.resources.types.ad_group_ad import AdGroupAd +from google.ads.googleads.v24.resources.types.asset import Asset +from google.ads.googleads.v24.services.services.ad_group_ad_service import ( AdGroupAdServiceClient, ) -from google.ads.googleads.v23.services.services.asset_service import ( +from google.ads.googleads.v24.services.services.asset_service import ( AssetServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_ad_service import ( +from google.ads.googleads.v24.services.types.ad_group_ad_service import ( AdGroupAdOperation, MutateAdGroupAdsResponse, ) -from google.ads.googleads.v23.services.types.asset_service import ( +from google.ads.googleads.v24.services.types.asset_service import ( AssetOperation, MutateAssetsResponse, ) - BUNDLE_URL: str = "https://gaagl.page.link/ib87" @@ -197,7 +195,7 @@ def create_display_upload_ad_group_ad( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/advanced_operations/add_dynamic_page_feed_asset.py b/examples/advanced_operations/add_dynamic_page_feed_asset.py index 185e93f98..53ed8798f 100755 --- a/examples/advanced_operations/add_dynamic_page_feed_asset.py +++ b/examples/advanced_operations/add_dynamic_page_feed_asset.py @@ -21,61 +21,60 @@ from examples.utils.example_helpers import get_printable_datetime from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.asset_types import PageFeedAsset -from google.ads.googleads.v23.common.types.criteria import WebpageConditionInfo -from google.ads.googleads.v23.resources.types.ad_group_criterion import ( +from google.ads.googleads.v24.common.types.asset_types import PageFeedAsset +from google.ads.googleads.v24.common.types.criteria import WebpageConditionInfo +from google.ads.googleads.v24.resources.types.ad_group_criterion import ( AdGroupCriterion, ) -from google.ads.googleads.v23.resources.types.asset import Asset -from google.ads.googleads.v23.resources.types.asset_set import AssetSet -from google.ads.googleads.v23.resources.types.asset_set_asset import ( +from google.ads.googleads.v24.resources.types.asset import Asset +from google.ads.googleads.v24.resources.types.asset_set import AssetSet +from google.ads.googleads.v24.resources.types.asset_set_asset import ( AssetSetAsset, ) -from google.ads.googleads.v23.resources.types.campaign_asset_set import ( +from google.ads.googleads.v24.resources.types.campaign_asset_set import ( CampaignAssetSet, ) -from google.ads.googleads.v23.services.services.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.asset_service import ( +from google.ads.googleads.v24.services.services.asset_service import ( AssetServiceClient, ) -from google.ads.googleads.v23.services.services.asset_set_asset_service import ( +from google.ads.googleads.v24.services.services.asset_set_asset_service import ( AssetSetAssetServiceClient, ) -from google.ads.googleads.v23.services.services.asset_set_service import ( +from google.ads.googleads.v24.services.services.asset_set_service import ( AssetSetServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_asset_set_service import ( +from google.ads.googleads.v24.services.services.campaign_asset_set_service import ( CampaignAssetSetServiceClient, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation, MutateAdGroupCriteriaResponse, ) -from google.ads.googleads.v23.services.types.asset_service import ( +from google.ads.googleads.v24.services.types.asset_service import ( AssetOperation, MutateAssetResult, MutateAssetsResponse, ) -from google.ads.googleads.v23.services.types.asset_set_asset_service import ( +from google.ads.googleads.v24.services.types.asset_set_asset_service import ( AssetSetAssetOperation, MutateAssetSetAssetResult, MutateAssetSetAssetsResponse, ) -from google.ads.googleads.v23.services.types.asset_set_service import ( +from google.ads.googleads.v24.services.types.asset_set_service import ( AssetSetOperation, MutateAssetSetsResponse, ) -from google.ads.googleads.v23.services.types.campaign_asset_set_service import ( +from google.ads.googleads.v24.services.types.campaign_asset_set_service import ( CampaignAssetSetOperation, MutateCampaignAssetSetsResponse, ) - # The label for the DSA page URLs. DSA_PAGE_URL_LABEL = "discounts" @@ -387,7 +386,7 @@ def add_dsa_target( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/advanced_operations/add_dynamic_search_ads.py b/examples/advanced_operations/add_dynamic_search_ads.py index c1e744fd6..9a4879b80 100755 --- a/examples/advanced_operations/add_dynamic_search_ads.py +++ b/examples/advanced_operations/add_dynamic_search_ads.py @@ -17,7 +17,6 @@ It also creates a webpage targeting criteria for the DSA. """ - import argparse from datetime import datetime, timedelta import sys @@ -25,48 +24,48 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.criteria import WebpageConditionInfo -from google.ads.googleads.v23.resources.types.ad_group import AdGroup -from google.ads.googleads.v23.resources.types.ad_group_ad import AdGroupAd -from google.ads.googleads.v23.resources.types.ad_group_criterion import ( +from google.ads.googleads.v24.common.types.criteria import WebpageConditionInfo +from google.ads.googleads.v24.resources.types.ad_group import AdGroup +from google.ads.googleads.v24.resources.types.ad_group_ad import AdGroupAd +from google.ads.googleads.v24.resources.types.ad_group_criterion import ( AdGroupCriterion, ) -from google.ads.googleads.v23.resources.types.campaign import Campaign -from google.ads.googleads.v23.resources.types.campaign_budget import ( +from google.ads.googleads.v24.resources.types.campaign import Campaign +from google.ads.googleads.v24.resources.types.campaign_budget import ( CampaignBudget, ) -from google.ads.googleads.v23.services.services.ad_group_ad_service import ( +from google.ads.googleads.v24.services.services.ad_group_ad_service import ( AdGroupAdServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_budget_service import ( +from google.ads.googleads.v24.services.services.campaign_budget_service import ( CampaignBudgetServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_ad_service import ( +from google.ads.googleads.v24.services.types.ad_group_ad_service import ( AdGroupAdOperation, MutateAdGroupAdsResponse, ) -from google.ads.googleads.v23.services.types.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation, MutateAdGroupCriteriaResponse, ) -from google.ads.googleads.v23.services.types.ad_group_service import ( +from google.ads.googleads.v24.services.types.ad_group_service import ( AdGroupOperation, MutateAdGroupsResponse, ) -from google.ads.googleads.v23.services.types.campaign_budget_service import ( +from google.ads.googleads.v24.services.types.campaign_budget_service import ( CampaignBudgetOperation, MutateCampaignBudgetsResponse, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, MutateCampaignsResponse, ) @@ -174,7 +173,9 @@ def create_campaign( campaign.start_date_time = (datetime.now() + timedelta(days=1)).strftime( "%Y%m%d 00:00:00" ) - campaign.end_date_time = (datetime.now() + timedelta(days=30)).strftime("%Y%m%d 23:59:59") + campaign.end_date_time = (datetime.now() + timedelta(days=30)).strftime( + "%Y%m%d 23:59:59" + ) # Retrieve the campaign service. campaign_service: CampaignServiceClient = client.get_service( @@ -364,7 +365,7 @@ def add_webpage_criterion( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/advanced_operations/add_performance_max_campaign.py b/examples/advanced_operations/add_performance_max_campaign.py index 3165643d0..3b8dd5fd7 100644 --- a/examples/advanced_operations/add_performance_max_campaign.py +++ b/examples/advanced_operations/add_performance_max_campaign.py @@ -37,46 +37,46 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException from google.ads.googleads.util import convert_snake_case_to_upper_case -from google.ads.googleads.v23.enums.types.asset_field_type import ( +from google.ads.googleads.v24.enums.types.asset_field_type import ( AssetFieldTypeEnum, ) -from google.ads.googleads.v23.resources.types.asset import Asset -from google.ads.googleads.v23.resources.types.asset_group import AssetGroup -from google.ads.googleads.v23.resources.types.asset_group_asset import ( +from google.ads.googleads.v24.resources.types.asset import Asset +from google.ads.googleads.v24.resources.types.asset_group import AssetGroup +from google.ads.googleads.v24.resources.types.asset_group_asset import ( AssetGroupAsset, ) -from google.ads.googleads.v23.resources.types.asset_group_signal import ( +from google.ads.googleads.v24.resources.types.asset_group_signal import ( AssetGroupSignal, ) -from google.ads.googleads.v23.resources.types.campaign import Campaign -from google.ads.googleads.v23.resources.types.campaign_asset import ( +from google.ads.googleads.v24.resources.types.campaign import Campaign +from google.ads.googleads.v24.resources.types.campaign_asset import ( CampaignAsset, ) -from google.ads.googleads.v23.resources.types.campaign_budget import ( +from google.ads.googleads.v24.resources.types.campaign_budget import ( CampaignBudget, ) -from google.ads.googleads.v23.resources.types.campaign_criterion import ( +from google.ads.googleads.v24.resources.types.campaign_criterion import ( CampaignCriterion, ) -from google.ads.googleads.v23.services.services.asset_group_service import ( +from google.ads.googleads.v24.services.services.asset_group_service import ( AssetGroupServiceClient, ) -from google.ads.googleads.v23.services.services.asset_service import ( +from google.ads.googleads.v24.services.services.asset_service import ( AssetServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.services.geo_target_constant_service import ( +from google.ads.googleads.v24.services.services.geo_target_constant_service import ( GeoTargetConstantServiceClient, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.campaign_budget_service import ( +from google.ads.googleads.v24.services.types.campaign_budget_service import ( CampaignBudgetOperation, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( MutateGoogleAdsResponse, MutateOperation, MutateOperationResponse, @@ -990,7 +990,7 @@ def create_asset_group_signal_operations( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/advanced_operations/add_responsive_search_ad_full.py b/examples/advanced_operations/add_responsive_search_ad_full.py index da29511fc..b670a49ab 100644 --- a/examples/advanced_operations/add_responsive_search_ad_full.py +++ b/examples/advanced_operations/add_responsive_search_ad_full.py @@ -29,88 +29,88 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.ad_asset import AdTextAsset -from google.ads.googleads.v23.enums.types.served_asset_field_type import ( +from google.ads.googleads.v24.common.types.ad_asset import AdTextAsset +from google.ads.googleads.v24.enums.types.served_asset_field_type import ( ServedAssetFieldTypeEnum, ) -from google.ads.googleads.v23.resources.types.ad_group import AdGroup -from google.ads.googleads.v23.resources.types.ad_group_ad import AdGroupAd -from google.ads.googleads.v23.resources.types.ad_group_criterion import ( +from google.ads.googleads.v24.resources.types.ad_group import AdGroup +from google.ads.googleads.v24.resources.types.ad_group_ad import AdGroupAd +from google.ads.googleads.v24.resources.types.ad_group_criterion import ( AdGroupCriterion, ) -from google.ads.googleads.v23.resources.types.campaign import Campaign -from google.ads.googleads.v23.resources.types.campaign_budget import ( +from google.ads.googleads.v24.resources.types.campaign import Campaign +from google.ads.googleads.v24.resources.types.campaign_budget import ( CampaignBudget, ) -from google.ads.googleads.v23.resources.types.campaign_criterion import ( +from google.ads.googleads.v24.resources.types.campaign_criterion import ( CampaignCriterion, ) -from google.ads.googleads.v23.resources.types.customer_customizer import ( +from google.ads.googleads.v24.resources.types.customer_customizer import ( CustomerCustomizer, ) -from google.ads.googleads.v23.resources.types.customizer_attribute import ( +from google.ads.googleads.v24.resources.types.customizer_attribute import ( CustomizerAttribute, ) -from google.ads.googleads.v23.services.services.ad_group_ad_service import ( +from google.ads.googleads.v24.services.services.ad_group_ad_service import ( AdGroupAdServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_budget_service import ( +from google.ads.googleads.v24.services.services.campaign_budget_service import ( CampaignBudgetServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_criterion_service import ( +from google.ads.googleads.v24.services.services.campaign_criterion_service import ( CampaignCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.services.customer_customizer_service import ( +from google.ads.googleads.v24.services.services.customer_customizer_service import ( CustomerCustomizerServiceClient, ) -from google.ads.googleads.v23.services.services.customizer_attribute_service import ( +from google.ads.googleads.v24.services.services.customizer_attribute_service import ( CustomizerAttributeServiceClient, ) -from google.ads.googleads.v23.services.services.geo_target_constant_service import ( +from google.ads.googleads.v24.services.services.geo_target_constant_service import ( GeoTargetConstantServiceClient, ) -from google.ads.googleads.v23.services.types.geo_target_constant_service import ( +from google.ads.googleads.v24.services.types.geo_target_constant_service import ( SuggestGeoTargetConstantsRequest, SuggestGeoTargetConstantsResponse, ) -from google.ads.googleads.v23.services.types.ad_group_ad_service import ( +from google.ads.googleads.v24.services.types.ad_group_ad_service import ( AdGroupAdOperation, MutateAdGroupAdsResponse, ) -from google.ads.googleads.v23.services.types.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation, MutateAdGroupCriteriaResponse, ) -from google.ads.googleads.v23.services.types.ad_group_service import ( +from google.ads.googleads.v24.services.types.ad_group_service import ( AdGroupOperation, MutateAdGroupsResponse, ) -from google.ads.googleads.v23.services.types.campaign_budget_service import ( +from google.ads.googleads.v24.services.types.campaign_budget_service import ( CampaignBudgetOperation, MutateCampaignBudgetsResponse, ) -from google.ads.googleads.v23.services.types.campaign_criterion_service import ( +from google.ads.googleads.v24.services.types.campaign_criterion_service import ( CampaignCriterionOperation, MutateCampaignCriteriaResponse, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, MutateCampaignsResponse, ) -from google.ads.googleads.v23.services.types.customer_customizer_service import ( +from google.ads.googleads.v24.services.types.customer_customizer_service import ( CustomerCustomizerOperation, MutateCustomerCustomizersResponse, ) -from google.ads.googleads.v23.services.types.customizer_attribute_service import ( +from google.ads.googleads.v24.services.types.customizer_attribute_service import ( CustomizerAttributeOperation, MutateCustomizerAttributesResponse, ) @@ -748,7 +748,7 @@ def add_geo_targeting( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/advanced_operations/add_smart_campaign.py b/examples/advanced_operations/add_smart_campaign.py index 221298abc..605238b2d 100755 --- a/examples/advanced_operations/add_smart_campaign.py +++ b/examples/advanced_operations/add_smart_campaign.py @@ -25,70 +25,70 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.ad_asset import AdTextAsset -from google.ads.googleads.v23.common.types.ad_type_infos import ( +from google.ads.googleads.v24.common.types.ad_asset import AdTextAsset +from google.ads.googleads.v24.common.types.ad_type_infos import ( SmartCampaignAdInfo, ) -from google.ads.googleads.v23.common.types.criteria import ( +from google.ads.googleads.v24.common.types.criteria import ( AdScheduleInfo, KeywordThemeInfo, LocationInfo, ) -from google.ads.googleads.v23.resources.types.ad_group import AdGroup -from google.ads.googleads.v23.resources.types.ad_group_ad import AdGroupAd -from google.ads.googleads.v23.resources.types.campaign import Campaign -from google.ads.googleads.v23.resources.types.campaign_budget import ( +from google.ads.googleads.v24.resources.types.ad_group import AdGroup +from google.ads.googleads.v24.resources.types.ad_group_ad import AdGroupAd +from google.ads.googleads.v24.resources.types.campaign import Campaign +from google.ads.googleads.v24.resources.types.campaign_budget import ( CampaignBudget, ) -from google.ads.googleads.v23.resources.types.campaign_criterion import ( +from google.ads.googleads.v24.resources.types.campaign_criterion import ( CampaignCriterion, ) -from google.ads.googleads.v23.resources.types.keyword_theme_constant import ( +from google.ads.googleads.v24.resources.types.keyword_theme_constant import ( KeywordThemeConstant, ) -from google.ads.googleads.v23.resources.types.smart_campaign_setting import ( +from google.ads.googleads.v24.resources.types.smart_campaign_setting import ( SmartCampaignSetting, ) -from google.ads.googleads.v23.services.types.ad_group_ad_service import ( +from google.ads.googleads.v24.services.types.ad_group_ad_service import ( AdGroupAdOperation, ) -from google.ads.googleads.v23.services.types.ad_group_service import ( +from google.ads.googleads.v24.services.types.ad_group_service import ( AdGroupOperation, ) -from google.ads.googleads.v23.services.types.campaign_budget_service import ( +from google.ads.googleads.v24.services.types.campaign_budget_service import ( CampaignBudgetOperation, ) -from google.ads.googleads.v23.services.types.campaign_criterion_service import ( +from google.ads.googleads.v24.services.types.campaign_criterion_service import ( CampaignCriterionOperation, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.enums.types.minute_of_hour import ( +from google.ads.googleads.v24.enums.types.minute_of_hour import ( MinuteOfHourEnum, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( MutateGoogleAdsResponse, MutateOperation, MutateOperationResponse, ) -from google.ads.googleads.v23.services.services.keyword_theme_constant_service import ( +from google.ads.googleads.v24.services.services.keyword_theme_constant_service import ( KeywordThemeConstantServiceClient, ) -from google.ads.googleads.v23.services.types.keyword_theme_constant_service import ( +from google.ads.googleads.v24.services.types.keyword_theme_constant_service import ( SuggestKeywordThemeConstantsRequest, SuggestKeywordThemeConstantsResponse, ) -from google.ads.googleads.v23.services.services.smart_campaign_suggest_service import ( +from google.ads.googleads.v24.services.services.smart_campaign_suggest_service import ( SmartCampaignSuggestServiceClient, ) -from google.ads.googleads.v23.services.types.smart_campaign_suggest_service import ( +from google.ads.googleads.v24.services.types.smart_campaign_suggest_service import ( SmartCampaignSuggestionInfo, SuggestKeywordThemesResponse, SuggestKeywordThemesRequest, @@ -97,7 +97,7 @@ SuggestSmartCampaignBudgetOptionsResponse, SuggestSmartCampaignBudgetOptionsRequest, ) -from google.ads.googleads.v23.services.types.smart_campaign_setting_service import ( +from google.ads.googleads.v24.services.types.smart_campaign_setting_service import ( SmartCampaignSettingOperation, ) from google.api_core import protobuf_helpers @@ -1064,7 +1064,7 @@ def print_response_details(response: MutateGoogleAdsResponse) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/advanced_operations/create_and_attach_shared_keyword_set.py b/examples/advanced_operations/create_and_attach_shared_keyword_set.py index 18341d038..4306c345e 100755 --- a/examples/advanced_operations/create_and_attach_shared_keyword_set.py +++ b/examples/advanced_operations/create_and_attach_shared_keyword_set.py @@ -17,7 +17,6 @@ Note that the keywords will be attached to the specified campaign. """ - import argparse import sys from typing import List @@ -25,36 +24,36 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.errors.types.errors import GoogleAdsError -from google.ads.googleads.v23.resources.types.campaign_shared_set import ( +from google.ads.googleads.v24.errors.types.errors import GoogleAdsError +from google.ads.googleads.v24.resources.types.campaign_shared_set import ( CampaignSharedSet, ) -from google.ads.googleads.v23.resources.types.shared_criterion import ( +from google.ads.googleads.v24.resources.types.shared_criterion import ( SharedCriterion, ) -from google.ads.googleads.v23.resources.types.shared_set import SharedSet -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.resources.types.shared_set import SharedSet +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_shared_set_service import ( +from google.ads.googleads.v24.services.services.campaign_shared_set_service import ( CampaignSharedSetServiceClient, ) -from google.ads.googleads.v23.services.types.campaign_shared_set_service import ( +from google.ads.googleads.v24.services.types.campaign_shared_set_service import ( CampaignSharedSetOperation, MutateCampaignSharedSetsResponse, ) -from google.ads.googleads.v23.services.services.shared_criterion_service import ( +from google.ads.googleads.v24.services.services.shared_criterion_service import ( SharedCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.shared_set_service import ( +from google.ads.googleads.v24.services.services.shared_set_service import ( SharedSetServiceClient, ) -from google.ads.googleads.v23.services.types.shared_criterion_service import ( +from google.ads.googleads.v24.services.types.shared_criterion_service import ( MutateSharedCriteriaResponse, MutateSharedCriterionResult, SharedCriterionOperation, ) -from google.ads.googleads.v23.services.types.shared_set_service import ( +from google.ads.googleads.v24.services.types.shared_set_service import ( MutateSharedSetsResponse, SharedSetOperation, ) @@ -187,7 +186,7 @@ def handle_googleads_exception(exception: GoogleAdsException) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) main(googleads_client, args.customer_id, args.campaign_id) diff --git a/examples/advanced_operations/find_and_remove_criteria_from_shared_set.py b/examples/advanced_operations/find_and_remove_criteria_from_shared_set.py index f8e1737d6..76560fbd5 100755 --- a/examples/advanced_operations/find_and_remove_criteria_from_shared_set.py +++ b/examples/advanced_operations/find_and_remove_criteria_from_shared_set.py @@ -14,34 +14,33 @@ # limitations under the License. """Demonstrates how to find and remove shared sets, and shared set criteria.""" - import argparse import sys from typing import List from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.criteria import KeywordInfo -from google.ads.googleads.v23.enums.types.criterion_type import ( +from google.ads.googleads.v24.common.types.criteria import KeywordInfo +from google.ads.googleads.v24.enums.types.criterion_type import ( CriterionTypeEnum, ) -from google.ads.googleads.v23.errors.types.errors import GoogleAdsError -from google.ads.googleads.v23.resources.types.shared_criterion import ( +from google.ads.googleads.v24.errors.types.errors import GoogleAdsError +from google.ads.googleads.v24.resources.types.shared_criterion import ( SharedCriterion, ) -from google.ads.googleads.v23.resources.types.shared_set import SharedSet -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.resources.types.shared_set import SharedSet +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.services.shared_criterion_service import ( +from google.ads.googleads.v24.services.services.shared_criterion_service import ( SharedCriterionServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( GoogleAdsRow, SearchGoogleAdsRequest, SearchGoogleAdsResponse, ) -from google.ads.googleads.v23.services.types.shared_criterion_service import ( +from google.ads.googleads.v24.services.types.shared_criterion_service import ( MutateSharedCriteriaResponse, MutateSharedCriterionResult, SharedCriterionOperation, @@ -189,7 +188,7 @@ def handle_googleads_exception(exception: GoogleAdsException) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) main(googleads_client, args.customer_id, args.campaign_id) diff --git a/examples/advanced_operations/get_ad_group_bid_modifiers.py b/examples/advanced_operations/get_ad_group_bid_modifiers.py index faff1a433..942b6bcb0 100755 --- a/examples/advanced_operations/get_ad_group_bid_modifiers.py +++ b/examples/advanced_operations/get_ad_group_bid_modifiers.py @@ -14,20 +14,19 @@ # limitations under the License. """This example illustrates how to retrieve ad group bid modifiers.""" - import argparse import sys from typing import Optional from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.ad_group_bid_modifier import ( +from google.ads.googleads.v24.resources.types.ad_group_bid_modifier import ( AdGroupBidModifier, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( GoogleAdsRow, SearchGoogleAdsRequest, SearchGoogleAdsResponse, @@ -137,7 +136,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/advanced_operations/upload_video.py b/examples/advanced_operations/upload_video.py index f2125ad2c..86dbf017c 100644 --- a/examples/advanced_operations/upload_video.py +++ b/examples/advanced_operations/upload_video.py @@ -27,19 +27,19 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( SearchGoogleAdsStreamResponse, GoogleAdsRow, ) -from google.ads.googleads.v23.services.services.you_tube_video_upload_service.client import ( +from google.ads.googleads.v24.services.services.you_tube_video_upload_service.client import ( YouTubeVideoUploadServiceClient, ) -from google.ads.googleads.v23.services.types import youtube_video_upload_service -from google.ads.googleads.v23.services.types.youtube_video_upload_service import ( +from google.ads.googleads.v24.services.types import youtube_video_upload_service +from google.ads.googleads.v24.services.types.youtube_video_upload_service import ( CreateYouTubeVideoUploadRequest, CreateYouTubeVideoUploadResponse, UpdateYouTubeVideoUploadRequest, @@ -49,10 +49,12 @@ ) from google.protobuf import field_mask_pb2 -from google.ads.googleads.v23.resources.types import youtube_video_upload +from google.ads.googleads.v24.resources.types import youtube_video_upload -def main(client: GoogleAdsClient, customer_id: str, video_file_path: str) -> None: +def main( + client: GoogleAdsClient, customer_id: str, video_file_path: str +) -> None: """The main method that uploads a video and retrieves its state. Args: @@ -137,7 +139,9 @@ def main(client: GoogleAdsClient, customer_id: str, video_file_path: str) -> Non # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage(version="v23") + googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( + version="v24" + ) try: main( googleads_client, diff --git a/examples/advanced_operations/use_cross_account_bidding_strategy.py b/examples/advanced_operations/use_cross_account_bidding_strategy.py index a4730348a..82508226b 100755 --- a/examples/advanced_operations/use_cross_account_bidding_strategy.py +++ b/examples/advanced_operations/use_cross_account_bidding_strategy.py @@ -18,7 +18,6 @@ all manager-owned and customer accessible bidding strategies. """ - import argparse import sys from typing import Iterator @@ -28,32 +27,32 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.bidding import TargetSpend -from google.ads.googleads.v23.resources.types.accessible_bidding_strategy import ( +from google.ads.googleads.v24.common.types.bidding import TargetSpend +from google.ads.googleads.v24.resources.types.accessible_bidding_strategy import ( AccessibleBiddingStrategy, ) -from google.ads.googleads.v23.resources.types.bidding_strategy import ( +from google.ads.googleads.v24.resources.types.bidding_strategy import ( BiddingStrategy, ) -from google.ads.googleads.v23.resources.types.campaign import Campaign -from google.ads.googleads.v23.services.services.bidding_strategy_service import ( +from google.ads.googleads.v24.resources.types.campaign import Campaign +from google.ads.googleads.v24.services.services.bidding_strategy_service import ( BiddingStrategyServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.bidding_strategy_service import ( +from google.ads.googleads.v24.services.types.bidding_strategy_service import ( BiddingStrategyOperation, MutateBiddingStrategiesResponse, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, MutateCampaignsResponse, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( GoogleAdsRow, SearchGoogleAdsStreamResponse, ) @@ -311,7 +310,7 @@ def attach_cross_account_bidding_strategy_to_campaign( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/advanced_operations/use_portfolio_bidding_strategy.py b/examples/advanced_operations/use_portfolio_bidding_strategy.py index 6fe3d7fd8..9132737cf 100755 --- a/examples/advanced_operations/use_portfolio_bidding_strategy.py +++ b/examples/advanced_operations/use_portfolio_bidding_strategy.py @@ -14,39 +14,38 @@ # limitations under the License. """This example constructs a campaign with a Portfolio Bidding Strategy.""" - import argparse import sys import uuid from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.bidding import TargetSpend -from google.ads.googleads.v23.resources.types.bidding_strategy import ( +from google.ads.googleads.v24.common.types.bidding import TargetSpend +from google.ads.googleads.v24.resources.types.bidding_strategy import ( BiddingStrategy, ) -from google.ads.googleads.v23.resources.types.campaign import Campaign -from google.ads.googleads.v23.resources.types.campaign_budget import ( +from google.ads.googleads.v24.resources.types.campaign import Campaign +from google.ads.googleads.v24.resources.types.campaign_budget import ( CampaignBudget, ) -from google.ads.googleads.v23.services.services.bidding_strategy_service import ( +from google.ads.googleads.v24.services.services.bidding_strategy_service import ( BiddingStrategyServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_budget_service import ( +from google.ads.googleads.v24.services.services.campaign_budget_service import ( CampaignBudgetServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.types.bidding_strategy_service import ( +from google.ads.googleads.v24.services.types.bidding_strategy_service import ( BiddingStrategyOperation, MutateBiddingStrategiesResponse, ) -from google.ads.googleads.v23.services.types.campaign_budget_service import ( +from google.ads.googleads.v24.services.types.campaign_budget_service import ( CampaignBudgetOperation, MutateCampaignBudgetsResponse, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, MutateCampaignsResponse, ) @@ -187,7 +186,7 @@ def handle_googleads_exception(exception: GoogleAdsException) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) main(googleads_client, args.customer_id) diff --git a/examples/assets/add_call.py b/examples/assets/add_call.py index ac6687af1..3bd3245be 100755 --- a/examples/assets/add_call.py +++ b/examples/assets/add_call.py @@ -14,20 +14,19 @@ # limitations under the License. """This example adds a call asset to a specific account.""" - import argparse from typing import Optional import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.types.asset_service import AssetOperation -from google.ads.googleads.v23.resources.types.asset import Asset -from google.ads.googleads.v23.common.types.criteria import AdScheduleInfo -from google.ads.googleads.v23.services.types.customer_asset_service import ( +from google.ads.googleads.v24.services.types.asset_service import AssetOperation +from google.ads.googleads.v24.resources.types.asset import Asset +from google.ads.googleads.v24.common.types.criteria import AdScheduleInfo +from google.ads.googleads.v24.services.types.customer_asset_service import ( CustomerAssetOperation, ) -from google.ads.googleads.v23.resources.types.customer_asset import ( +from google.ads.googleads.v24.resources.types.customer_asset import ( CustomerAsset, ) @@ -184,7 +183,7 @@ def link_asset_to_account( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/assets/add_hotel_callout.py b/examples/assets/add_hotel_callout.py index 3f355fd3f..d4c08e26e 100755 --- a/examples/assets/add_hotel_callout.py +++ b/examples/assets/add_hotel_callout.py @@ -14,7 +14,6 @@ # limitations under the License. """This example adds a hotel callout extension asset to a specific account.""" - import argparse from typing import List import sys @@ -22,12 +21,12 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.types.asset_service import AssetOperation -from google.ads.googleads.v23.resources.types.asset import Asset -from google.ads.googleads.v23.services.types.customer_asset_service import ( +from google.ads.googleads.v24.services.types.asset_service import AssetOperation +from google.ads.googleads.v24.resources.types.asset import Asset +from google.ads.googleads.v24.services.types.customer_asset_service import ( CustomerAssetOperation, ) -from google.ads.googleads.v23.resources.types.customer_asset import ( +from google.ads.googleads.v24.resources.types.customer_asset import ( CustomerAsset, ) @@ -155,7 +154,7 @@ def link_asset_to_account( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/assets/add_lead_form_asset.py b/examples/assets/add_lead_form_asset.py index 3dfd33789..84e20ef9a 100755 --- a/examples/assets/add_lead_form_asset.py +++ b/examples/assets/add_lead_form_asset.py @@ -17,24 +17,23 @@ Run add_campaigns.py to create a campaign. """ - import argparse import sys from uuid import uuid4 from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.types.asset_service import AssetOperation -from google.ads.googleads.v23.resources.types.asset import Asset -from google.ads.googleads.v23.common.types.asset_types import LeadFormAsset -from google.ads.googleads.v23.common.types.asset_types import LeadFormField -from google.ads.googleads.v23.common.types.asset_types import ( +from google.ads.googleads.v24.services.types.asset_service import AssetOperation +from google.ads.googleads.v24.resources.types.asset import Asset +from google.ads.googleads.v24.common.types.asset_types import LeadFormAsset +from google.ads.googleads.v24.common.types.asset_types import LeadFormField +from google.ads.googleads.v24.common.types.asset_types import ( LeadFormDeliveryMethod, ) -from google.ads.googleads.v23.services.types.campaign_asset_service import ( +from google.ads.googleads.v24.services.types.campaign_asset_service import ( CampaignAssetOperation, ) -from google.ads.googleads.v23.resources.types.campaign_asset import ( +from google.ads.googleads.v24.resources.types.campaign_asset import ( CampaignAsset, ) @@ -219,7 +218,7 @@ def create_lead_form_campaign_asset( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/assets/add_prices.py b/examples/assets/add_prices.py index e9dcfe7f5..4b98563b1 100644 --- a/examples/assets/add_prices.py +++ b/examples/assets/add_prices.py @@ -14,7 +14,6 @@ # limitations under the License. """This example adds a price asset and associates it with an account.""" - import argparse from typing import Optional import sys @@ -22,17 +21,17 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.types.asset_service import AssetOperation -from google.ads.googleads.v23.resources.types.asset import Asset -from google.ads.googleads.v23.common.types.asset_types import PriceAsset -from google.ads.googleads.v23.common.types.asset_types import PriceOffering -from google.ads.googleads.v23.enums.types.price_extension_price_unit import ( +from google.ads.googleads.v24.services.types.asset_service import AssetOperation +from google.ads.googleads.v24.resources.types.asset import Asset +from google.ads.googleads.v24.common.types.asset_types import PriceAsset +from google.ads.googleads.v24.common.types.asset_types import PriceOffering +from google.ads.googleads.v24.enums.types.price_extension_price_unit import ( PriceExtensionPriceUnitEnum, ) -from google.ads.googleads.v23.services.types.customer_asset_service import ( +from google.ads.googleads.v24.services.types.customer_asset_service import ( CustomerAssetOperation, ) -from google.ads.googleads.v23.resources.types.customer_asset import ( +from google.ads.googleads.v24.resources.types.customer_asset import ( CustomerAsset, ) @@ -216,7 +215,7 @@ def add_asset_to_account( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/assets/add_sitelinks.py b/examples/assets/add_sitelinks.py index 96deaa048..06abbee6e 100755 --- a/examples/assets/add_sitelinks.py +++ b/examples/assets/add_sitelinks.py @@ -23,12 +23,12 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.types.asset_service import AssetOperation -from google.ads.googleads.v23.resources.types.asset import Asset -from google.ads.googleads.v23.services.types.campaign_asset_service import ( +from google.ads.googleads.v24.services.types.asset_service import AssetOperation +from google.ads.googleads.v24.resources.types.asset import Asset +from google.ads.googleads.v24.services.types.campaign_asset_service import ( CampaignAssetOperation, ) -from google.ads.googleads.v23.resources.types.campaign_asset import ( +from google.ads.googleads.v24.resources.types.campaign_asset import ( CampaignAsset, ) @@ -175,7 +175,7 @@ def link_sitelinks_to_campaign( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/assets/upload_image_asset.py b/examples/assets/upload_image_asset.py index 08aff07e5..fae530d0e 100644 --- a/examples/assets/upload_image_asset.py +++ b/examples/assets/upload_image_asset.py @@ -17,15 +17,14 @@ To get image assets, run get_all_image_assets.py. """ - import argparse import sys from examples.utils.example_helpers import get_image_bytes_from_url from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.types.asset_service import AssetOperation -from google.ads.googleads.v23.resources.types.asset import Asset +from google.ads.googleads.v24.services.types.asset_service import AssetOperation +from google.ads.googleads.v24.resources.types.asset import Asset # [START upload_image_asset] @@ -79,7 +78,7 @@ def main(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/asyncio/async_add_campaigns.py b/examples/asyncio/async_add_campaigns.py index b06818833..7bfbdd5cf 100644 --- a/examples/asyncio/async_add_campaigns.py +++ b/examples/asyncio/async_add_campaigns.py @@ -14,7 +14,6 @@ # limitations under the License. """This example illustrates how to add a campaign using asyncio.""" - import argparse import asyncio import datetime @@ -24,22 +23,21 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.campaign import Campaign -from google.ads.googleads.v23.resources.types.campaign_budget import ( +from google.ads.googleads.v24.resources.types.campaign import Campaign +from google.ads.googleads.v24.resources.types.campaign_budget import ( CampaignBudget, ) -from google.ads.googleads.v23.services.types.campaign_budget_service import ( +from google.ads.googleads.v24.services.types.campaign_budget_service import ( CampaignBudgetOperation, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( MutateGoogleAdsResponse, MutateOperation, ) - _START_DATE_FORMAT: str = "%Y%m%d 00:00:00" _END_DATE_FORMAT: str = "%Y%m%d 23:59:59" @@ -69,8 +67,12 @@ async def main(client: GoogleAdsClient, customer_id: str) -> None: ) campaign_budget.amount_micros = 500000 - mutate_operation_budget: MutateOperation = client.get_type("MutateOperation") - mutate_operation_budget.campaign_budget_operation = campaign_budget_operation + mutate_operation_budget: MutateOperation = client.get_type( + "MutateOperation" + ) + mutate_operation_budget.campaign_budget_operation = ( + campaign_budget_operation + ) mutate_operations.append(mutate_operation_budget) # Create campaign. @@ -111,7 +113,9 @@ async def main(client: GoogleAdsClient, customer_id: str) -> None: start_time: datetime.date = datetime.date.today() + datetime.timedelta( days=1 ) - campaign.start_date_time = datetime.date.strftime(start_time, _START_DATE_FORMAT) + campaign.start_date_time = datetime.date.strftime( + start_time, _START_DATE_FORMAT + ) # Optional: Set the end date. end_time: datetime.date = start_time + datetime.timedelta(weeks=4) @@ -152,7 +156,7 @@ async def main(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/asyncio/async_search.py b/examples/asyncio/async_search.py index 9e6d0a60c..ce12f7242 100755 --- a/examples/asyncio/async_search.py +++ b/examples/asyncio/async_search.py @@ -14,7 +14,6 @@ # limitations under the License. """This example illustrates how to get all campaigns using asyncio.""" - import argparse import asyncio import sys @@ -22,10 +21,10 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceAsyncClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( GoogleAdsRow, ) @@ -43,9 +42,7 @@ async def main(client: GoogleAdsClient, customer_id: str) -> None: ORDER BY campaign.id""" # Issues a search request using streaming. - stream = await ga_service.search( - customer_id=customer_id, query=query - ) + stream = await ga_service.search(customer_id=customer_id, query=query) async for row in stream: print( @@ -71,7 +68,7 @@ async def main(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/asyncio/async_search_stream.py b/examples/asyncio/async_search_stream.py index 1d1ef1edd..f47feea7a 100755 --- a/examples/asyncio/async_search_stream.py +++ b/examples/asyncio/async_search_stream.py @@ -14,7 +14,6 @@ # limitations under the License. """This example illustrates how to get all campaigns using asyncio.""" - import argparse import asyncio import sys @@ -22,10 +21,10 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceAsyncClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( GoogleAdsRow, ) @@ -72,7 +71,7 @@ async def main(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/audience_insights/generate_audience_insights.py b/examples/audience_insights/generate_audience_insights.py index ea76a2a54..af4cb6f75 100644 --- a/examples/audience_insights/generate_audience_insights.py +++ b/examples/audience_insights/generate_audience_insights.py @@ -20,16 +20,16 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.enums.types import ( +from google.ads.googleads.v24.enums.types import ( AudienceInsightsDimensionEnum, ) -from google.ads.googleads.v23.services.services.audience_insights_service import ( +from google.ads.googleads.v24.services.services.audience_insights_service import ( AudienceInsightsServiceClient, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.audience_insights_service import ( +from google.ads.googleads.v24.services.types.audience_insights_service import ( GenerateAudienceCompositionInsightsRequest, GenerateAudienceCompositionInsightsResponse, GenerateSuggestedTargetingInsightsRequest, @@ -38,7 +38,7 @@ ListAudienceInsightsAttributesRequest, ListAudienceInsightsAttributesResponse, ) -from google.ads.googleads.v23.common.types import ( +from google.ads.googleads.v24.common.types import ( AudienceInsightsAttribute, LocationInfo, ) @@ -271,7 +271,7 @@ def list_audience_insights_attributes( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/basic_operations/add_ad_groups.py b/examples/basic_operations/add_ad_groups.py index ed78bdbc0..b37ca9f67 100755 --- a/examples/basic_operations/add_ad_groups.py +++ b/examples/basic_operations/add_ad_groups.py @@ -17,7 +17,6 @@ To get ad groups, run get_ad_groups.py. """ - import argparse import sys from typing import List @@ -25,17 +24,17 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_service import ( +from google.ads.googleads.v24.services.types.ad_group_service import ( AdGroupOperation, MutateAdGroupsResponse, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.resources.types.ad_group import AdGroup +from google.ads.googleads.v24.resources.types.ad_group import AdGroup def main(client: GoogleAdsClient, customer_id: str, campaign_id: str) -> None: @@ -87,7 +86,7 @@ def main(client: GoogleAdsClient, customer_id: str, campaign_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/basic_operations/add_campaigns.py b/examples/basic_operations/add_campaigns.py index 20043136e..1b2f9f4b3 100755 --- a/examples/basic_operations/add_campaigns.py +++ b/examples/basic_operations/add_campaigns.py @@ -17,7 +17,6 @@ To get campaigns, run get_campaigns.py. """ - import argparse import datetime import sys @@ -26,25 +25,24 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.campaign_budget_service import ( +from google.ads.googleads.v24.services.services.campaign_budget_service import ( CampaignBudgetServiceClient, ) -from google.ads.googleads.v23.services.types.campaign_budget_service import ( +from google.ads.googleads.v24.services.types.campaign_budget_service import ( CampaignBudgetOperation, MutateCampaignBudgetsResponse, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, MutateCampaignsResponse, ) -from google.ads.googleads.v23.resources.types.campaign_budget import ( +from google.ads.googleads.v24.resources.types.campaign_budget import ( CampaignBudget, ) -from google.ads.googleads.v23.resources.types.campaign import Campaign - +from google.ads.googleads.v24.resources.types.campaign import Campaign _START_DATE_FORMAT: str = "%Y%m%d 00:00:00" _END_DATE_FORMAT: str = "%Y%m%d 23:59:59" @@ -127,7 +125,9 @@ def main(client: GoogleAdsClient, customer_id: str) -> None: start_time: datetime.date = datetime.date.today() + datetime.timedelta( days=1 ) - campaign.start_date_time = datetime.date.strftime(start_time, _START_DATE_FORMAT) + campaign.start_date_time = datetime.date.strftime( + start_time, _START_DATE_FORMAT + ) # Optional: Set the end date. end_time: datetime.date = start_time + datetime.timedelta(weeks=4) @@ -176,7 +176,7 @@ def handle_googleads_exception(exception: GoogleAdsException) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) main(googleads_client, args.customer_id) diff --git a/examples/basic_operations/get_campaigns.py b/examples/basic_operations/get_campaigns.py index d3844903d..1174f0565 100755 --- a/examples/basic_operations/get_campaigns.py +++ b/examples/basic_operations/get_campaigns.py @@ -17,17 +17,16 @@ To add campaigns, run add_campaigns.py. """ - import argparse import sys from typing import Iterator, List from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( SearchGoogleAdsStreamResponse, GoogleAdsRow, ) @@ -76,7 +75,7 @@ def main(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/basic_operations/get_responsive_search_ads.py b/examples/basic_operations/get_responsive_search_ads.py index d3e1ca8ac..438285517 100755 --- a/examples/basic_operations/get_responsive_search_ads.py +++ b/examples/basic_operations/get_responsive_search_ads.py @@ -24,12 +24,12 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.ad_asset import AdTextAsset -from google.ads.googleads.v23.resources.types.ad import Ad -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.common.types.ad_asset import AdTextAsset +from google.ads.googleads.v24.resources.types.ad import Ad +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( SearchGoogleAdsRequest, SearchGoogleAdsResponse, ) @@ -123,7 +123,7 @@ def ad_text_assets_to_strs(assets: Sequence[AdTextAsset]) -> List[str]: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/basic_operations/pause_ad.py b/examples/basic_operations/pause_ad.py index 24629fd75..b504bb4e2 100755 --- a/examples/basic_operations/pause_ad.py +++ b/examples/basic_operations/pause_ad.py @@ -14,7 +14,6 @@ # limitations under the License. """This example pauses an ad.""" - import argparse import sys from typing import List @@ -23,11 +22,11 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.ad_group_ad import AdGroupAd -from google.ads.googleads.v23.services.services.ad_group_ad_service import ( +from google.ads.googleads.v24.resources.types.ad_group_ad import AdGroupAd +from google.ads.googleads.v24.services.services.ad_group_ad_service import ( AdGroupAdServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_ad_service import ( +from google.ads.googleads.v24.services.types.ad_group_ad_service import ( AdGroupAdOperation, MutateAdGroupAdsResponse, ) @@ -94,7 +93,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/basic_operations/remove_campaign.py b/examples/basic_operations/remove_campaign.py index fa467a78d..13bfeebf5 100755 --- a/examples/basic_operations/remove_campaign.py +++ b/examples/basic_operations/remove_campaign.py @@ -14,17 +14,16 @@ # limitations under the License. """This example removes an existing campaign.""" - import argparse import sys from typing import List from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, MutateCampaignsResponse, ) @@ -73,7 +72,7 @@ def main(client: GoogleAdsClient, customer_id: str, campaign_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/basic_operations/search_for_google_ads_fields.py b/examples/basic_operations/search_for_google_ads_fields.py index 3edf56462..747a28359 100755 --- a/examples/basic_operations/search_for_google_ads_fields.py +++ b/examples/basic_operations/search_for_google_ads_fields.py @@ -20,19 +20,18 @@ campaign) or a field (such as metrics.impressions, campaign.id). """ - import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.google_ads_field import ( +from google.ads.googleads.v24.resources.types.google_ads_field import ( GoogleAdsField, ) -from google.ads.googleads.v23.services.services.google_ads_field_service import ( +from google.ads.googleads.v24.services.services.google_ads_field_service import ( GoogleAdsFieldServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_field_service import ( +from google.ads.googleads.v24.services.types.google_ads_field_service import ( SearchGoogleAdsFieldsRequest, SearchGoogleAdsFieldsResponse, ) @@ -124,7 +123,7 @@ def main(client: GoogleAdsClient, name_prefix: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/basic_operations/update_ad_group.py b/examples/basic_operations/update_ad_group.py index db6f55286..9adf016d4 100755 --- a/examples/basic_operations/update_ad_group.py +++ b/examples/basic_operations/update_ad_group.py @@ -17,7 +17,6 @@ To get ad groups, run get_ad_groups.py. """ - import argparse import sys from typing import List @@ -26,14 +25,14 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.ad_group import AdGroup -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.resources.types.ad_group import AdGroup +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_ad_service import ( +from google.ads.googleads.v24.services.types.ad_group_ad_service import ( AdGroupAdOperation, ) -from google.ads.googleads.v23.services.types.ad_group_service import ( +from google.ads.googleads.v24.services.types.ad_group_service import ( AdGroupOperation, MutateAdGroupsResponse, ) @@ -107,7 +106,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/basic_operations/update_campaign.py b/examples/basic_operations/update_campaign.py index b54b5e306..29a50fc32 100755 --- a/examples/basic_operations/update_campaign.py +++ b/examples/basic_operations/update_campaign.py @@ -17,7 +17,6 @@ To get campaigns, run get_campaigns.py. """ - import argparse import sys from typing import List @@ -26,11 +25,11 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.campaign import Campaign -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.resources.types.campaign import Campaign +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, MutateCampaignsResponse, ) @@ -89,7 +88,7 @@ def main(client: GoogleAdsClient, customer_id: str, campaign_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/basic_operations/update_responsive_search_ad.py b/examples/basic_operations/update_responsive_search_ad.py index 959578c40..f3fb9fb96 100755 --- a/examples/basic_operations/update_responsive_search_ad.py +++ b/examples/basic_operations/update_responsive_search_ad.py @@ -17,7 +17,6 @@ To get responsive search ads, run get_responsive_search_ads.py. """ - import argparse import sys from typing import List @@ -27,12 +26,12 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.ad_asset import AdTextAsset -from google.ads.googleads.v23.resources.types.ad import Ad -from google.ads.googleads.v23.services.services.ad_service import ( +from google.ads.googleads.v24.common.types.ad_asset import AdTextAsset +from google.ads.googleads.v24.resources.types.ad import Ad +from google.ads.googleads.v24.services.services.ad_service import ( AdServiceClient, ) -from google.ads.googleads.v23.services.types.ad_service import ( +from google.ads.googleads.v24.services.types.ad_service import ( AdOperation, MutateAdsResponse, ) @@ -112,7 +111,7 @@ def main(client: GoogleAdsClient, customer_id: str, ad_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/billing/add_account_budget_proposal.py b/examples/billing/add_account_budget_proposal.py index eb0007dde..b9218ebbd 100755 --- a/examples/billing/add_account_budget_proposal.py +++ b/examples/billing/add_account_budget_proposal.py @@ -17,7 +17,6 @@ To get account budget proposal, run get_account_budget_proposals.py """ - import argparse import sys @@ -100,7 +99,7 @@ def main(client: GoogleAdsClient, customer_id: str, billing_setup_id: str): # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main(googleads_client, args.customer_id, args.billing_setup_id) diff --git a/examples/billing/add_billing_setup.py b/examples/billing/add_billing_setup.py index 1601d49e2..042aeb9cf 100755 --- a/examples/billing/add_billing_setup.py +++ b/examples/billing/add_billing_setup.py @@ -23,7 +23,6 @@ manager account and is linked to a customer account via a billing setup. """ - import argparse from datetime import datetime, timedelta import sys @@ -231,7 +230,7 @@ def set_billing_setup_date_times( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main( diff --git a/examples/billing/get_invoices.py b/examples/billing/get_invoices.py index 024a7addb..3e8f0c7c0 100755 --- a/examples/billing/get_invoices.py +++ b/examples/billing/get_invoices.py @@ -14,7 +14,6 @@ # limitations under the License. """Retrieves the invoices issued last month for a given billing setup.""" - import argparse from datetime import date, timedelta import sys @@ -51,8 +50,7 @@ def main(client: GoogleAdsClient, customer_id: str, billing_setup_id: str): # [START get_invoices_1] for invoice in response.invoices: - print( - f""" + print(f""" - Found the invoice {invoice.resource_name} ID (also known as Invoice Number): '{invoice.id}' Type: {invoice.type_} @@ -79,11 +77,9 @@ def main(client: GoogleAdsClient, customer_id: str, billing_setup_id: str): Corrected invoice: {invoice.corrected_invoice or "none"} PDF URL: {invoice.pdf_url} Account budgets: - """ - ) + """) for account_budget_summary in invoice.account_budget_summaries: - print( - f""" + print(f""" - Account budget '{account_budget_summary.account_budget}': Name (also known as Account Budget): '{account_budget_summary.account_budget_name}' Customer (also known as Account ID): '{account_budget_summary.customer}' @@ -96,8 +92,7 @@ def main(client: GoogleAdsClient, customer_id: str, billing_setup_id: str): subtotal '{_micros_to_currency(account_budget_summary.subtotal_amount_micros)}' tax '{_micros_to_currency(account_budget_summary.tax_amount_micros)}' total '{_micros_to_currency(account_budget_summary.total_amount_micros)}' - """ - ) + """) # [END get_invoices_1] @@ -128,7 +123,7 @@ def micros_to_currency(micros: Optional[int]) -> Optional[float]: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main(googleads_client, args.customer_id, args.billing_setup_id) diff --git a/examples/campaign_management/add_campaign_labels.py b/examples/campaign_management/add_campaign_labels.py index 07bd768fd..38f7f55cd 100755 --- a/examples/campaign_management/add_campaign_labels.py +++ b/examples/campaign_management/add_campaign_labels.py @@ -23,19 +23,19 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.campaign_label_service import ( +from google.ads.googleads.v24.services.services.campaign_label_service import ( CampaignLabelServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.services.label_service import ( +from google.ads.googleads.v24.services.services.label_service import ( LabelServiceClient, ) -from google.ads.googleads.v23.services.types.campaign_label_service import ( +from google.ads.googleads.v24.services.types.campaign_label_service import ( MutateCampaignLabelsResponse, ) -from google.ads.googleads.v23.resources.types.campaign_label import ( +from google.ads.googleads.v24.resources.types.campaign_label import ( CampaignLabel, ) @@ -127,7 +127,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: main( diff --git a/examples/campaign_management/add_complete_campaigns_using_batch_job.py b/examples/campaign_management/add_complete_campaigns_using_batch_job.py index aff7063b5..6cd015d1f 100755 --- a/examples/campaign_management/add_complete_campaigns_using_batch_job.py +++ b/examples/campaign_management/add_complete_campaigns_using_batch_job.py @@ -17,7 +17,6 @@ Complete campaigns include campaign budgets, campaigns, ad groups and keywords. """ - import argparse import asyncio import sys @@ -28,42 +27,41 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.batch_job_service import ( +from google.ads.googleads.v24.services.services.batch_job_service import ( BatchJobServiceClient, ) -from google.ads.googleads.v23.services.types.batch_job_service import ( +from google.ads.googleads.v24.services.types.batch_job_service import ( MutateBatchJobResponse, AddBatchJobOperationsResponse, ListBatchJobResultsRequest, ListBatchJobResultsResponse, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( MutateOperation, ) -from google.ads.googleads.v23.resources.types.batch_job import BatchJob -from google.ads.googleads.v23.services.types.campaign_budget_service import ( +from google.ads.googleads.v24.resources.types.batch_job import BatchJob +from google.ads.googleads.v24.services.types.campaign_budget_service import ( CampaignBudgetOperation, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, ) -from google.ads.googleads.v23.services.types.campaign_criterion_service import ( +from google.ads.googleads.v24.services.types.campaign_criterion_service import ( CampaignCriterionOperation, ) -from google.ads.googleads.v23.services.types.ad_group_service import ( +from google.ads.googleads.v24.services.types.ad_group_service import ( AdGroupOperation, ) -from google.ads.googleads.v23.services.types.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation, ) -from google.ads.googleads.v23.services.types.ad_group_ad_service import ( +from google.ads.googleads.v24.services.types.ad_group_ad_service import ( AdGroupAdOperation, ) -from google.ads.googleads.v23.services.types.batch_job_service import ( +from google.ads.googleads.v24.services.types.batch_job_service import ( BatchJobOperation, ) - NUMBER_OF_CAMPAIGNS_TO_ADD: int = 2 NUMBER_OF_AD_GROUPS_TO_ADD: int = 2 NUMBER_OF_KEYWORDS_TO_ADD: int = 4 @@ -780,7 +778,7 @@ def handle_googleads_exception(exception: GoogleAdsException) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) asyncio.run(main(googleads_client, args.customer_id)) diff --git a/examples/campaign_management/create_experiment.py b/examples/campaign_management/create_experiment.py index be0f0517f..5c97999bd 100644 --- a/examples/campaign_management/create_experiment.py +++ b/examples/campaign_management/create_experiment.py @@ -28,32 +28,32 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.types.experiment_service import ( +from google.ads.googleads.v24.services.types.experiment_service import ( ExperimentOperation, MutateExperimentsResponse, ) -from google.ads.googleads.v23.services.types.experiment_arm_service import ( +from google.ads.googleads.v24.services.types.experiment_arm_service import ( ExperimentArmOperation, MutateExperimentArmsRequest, MutateExperimentArmsResponse, ) -from google.ads.googleads.v23.resources.types.experiment import Experiment -from google.ads.googleads.v23.resources.types.experiment_arm import ( +from google.ads.googleads.v24.resources.types.experiment import Experiment +from google.ads.googleads.v24.resources.types.experiment_arm import ( ExperimentArm, ) -from google.ads.googleads.v23.services.services.experiment_service import ( +from google.ads.googleads.v24.services.services.experiment_service import ( ExperimentServiceClient, ) -from google.ads.googleads.v23.services.services.experiment_arm_service import ( +from google.ads.googleads.v24.services.services.experiment_arm_service import ( ExperimentArmServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, ) -from google.ads.googleads.v23.resources.types.campaign import Campaign +from google.ads.googleads.v24.resources.types.campaign import Campaign def main( @@ -264,7 +264,7 @@ def modify_draft_campaign( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/campaign_management/get_all_disapproved_ads.py b/examples/campaign_management/get_all_disapproved_ads.py index d4e02b8a9..f776d7c1f 100755 --- a/examples/campaign_management/get_all_disapproved_ads.py +++ b/examples/campaign_management/get_all_disapproved_ads.py @@ -14,22 +14,21 @@ # limitations under the License. """This illustrates how to retrieve disapproved ads in a given campaign.""" - import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( SearchGoogleAdsRequest, SearchGoogleAdsResponse, ) -from google.ads.googleads.v23.resources.types.ad_group_ad import AdGroupAd -from google.ads.googleads.v23.resources.types.ad import Ad -from google.ads.googleads.v23.enums.types.policy_approval_status import ( +from google.ads.googleads.v24.resources.types.ad_group_ad import AdGroupAd +from google.ads.googleads.v24.resources.types.ad import Ad +from google.ads.googleads.v24.enums.types.policy_approval_status import ( PolicyApprovalStatusEnum, ) @@ -117,7 +116,7 @@ def main(client: GoogleAdsClient, customer_id: str, campaign_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/campaign_management/set_ad_parameters.py b/examples/campaign_management/set_ad_parameters.py index 10ca698fa..5dcc39a65 100755 --- a/examples/campaign_management/set_ad_parameters.py +++ b/examples/campaign_management/set_ad_parameters.py @@ -14,24 +14,23 @@ # limitations under the License. """This example sets ad parameters for an ad group criterion.""" - import argparse import sys from typing import List from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.ad_parameter_service import ( +from google.ads.googleads.v24.services.services.ad_parameter_service import ( AdParameterServiceClient, ) -from google.ads.googleads.v23.services.types.ad_parameter_service import ( +from google.ads.googleads.v24.services.types.ad_parameter_service import ( AdParameterOperation, MutateAdParametersResponse, ) -from google.ads.googleads.v23.resources.types.ad_parameter import AdParameter +from google.ads.googleads.v24.resources.types.ad_parameter import AdParameter def main( @@ -155,7 +154,7 @@ def create_ad_parameter( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) main( diff --git a/examples/campaign_management/update_campaign_criterion_bid_modifier.py b/examples/campaign_management/update_campaign_criterion_bid_modifier.py index 74cbaad02..37af08c67 100755 --- a/examples/campaign_management/update_campaign_criterion_bid_modifier.py +++ b/examples/campaign_management/update_campaign_criterion_bid_modifier.py @@ -21,14 +21,14 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.campaign_criterion_service import ( +from google.ads.googleads.v24.services.services.campaign_criterion_service import ( CampaignCriterionServiceClient, ) -from google.ads.googleads.v23.services.types.campaign_criterion_service import ( +from google.ads.googleads.v24.services.types.campaign_criterion_service import ( CampaignCriterionOperation, MutateCampaignCriteriaResponse, ) -from google.ads.googleads.v23.resources.types.campaign_criterion import ( +from google.ads.googleads.v24.resources.types.campaign_criterion import ( CampaignCriterion, ) @@ -110,7 +110,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/campaign_management/validate_ad.py b/examples/campaign_management/validate_ad.py index 6a44daff6..76061f61a 100755 --- a/examples/campaign_management/validate_ad.py +++ b/examples/campaign_management/validate_ad.py @@ -19,29 +19,28 @@ will still be thrown. """ - import argparse import sys from typing import List from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.types.ad_group_ad_service import ( +from google.ads.googleads.v24.services.types.ad_group_ad_service import ( AdGroupAdOperation, MutateAdGroupAdsRequest, ) -from google.ads.googleads.v23.resources.types.ad_group_ad import AdGroupAd -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.resources.types.ad_group_ad import AdGroupAd +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.common.types.ad_type_infos import AdTextAsset -from google.ads.googleads.v23.services.services.ad_group_ad_service import ( +from google.ads.googleads.v24.common.types.ad_type_infos import AdTextAsset +from google.ads.googleads.v24.services.services.ad_group_ad_service import ( AdGroupAdServiceClient, ) -from google.ads.googleads.v23.errors.types.policy_finding_error import ( +from google.ads.googleads.v24.errors.types.policy_finding_error import ( PolicyFindingErrorEnum, ) -from google.ads.googleads.v23.common.types.policy import PolicyTopicEntry +from google.ads.googleads.v24.common.types.policy import PolicyTopicEntry def main(client: GoogleAdsClient, customer_id: str, ad_group_id: str) -> None: @@ -163,7 +162,7 @@ def main(client: GoogleAdsClient, customer_id: str, ad_group_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) main(googleads_client, args.customer_id, args.ad_group_id) diff --git a/examples/custom_logging_interceptor/get_campaigns.py b/examples/custom_logging_interceptor/get_campaigns.py index b51cb1670..704fd49d3 100755 --- a/examples/custom_logging_interceptor/get_campaigns.py +++ b/examples/custom_logging_interceptor/get_campaigns.py @@ -23,13 +23,13 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( SearchGoogleAdsStreamResponse, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( GoogleAdsRow, ) @@ -40,7 +40,7 @@ def main(client: GoogleAdsClient, customer_id: str) -> None: # Instantiate the GoogleAdsService object with a custom interceptor. ga_service: GoogleAdsServiceClient = client.get_service( "GoogleAdsService", - interceptors=[CloudLoggingInterceptor(api_version="v23")], + interceptors=[CloudLoggingInterceptor(api_version="v24")], ) query: str = """ @@ -82,7 +82,7 @@ def main(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/error_handling/handle_keyword_policy_violations.py b/examples/error_handling/handle_keyword_policy_violations.py index 36f725a36..16c0658e8 100755 --- a/examples/error_handling/handle_keyword_policy_violations.py +++ b/examples/error_handling/handle_keyword_policy_violations.py @@ -31,13 +31,13 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation, ) -from google.ads.googleads.v23.common.types.policy import PolicyViolationKey +from google.ads.googleads.v24.common.types.policy import PolicyViolationKey def main( @@ -282,7 +282,7 @@ def request_exemption( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) main( diff --git a/examples/error_handling/handle_partial_failure.py b/examples/error_handling/handle_partial_failure.py index 2dce99a5b..02c7b540d 100755 --- a/examples/error_handling/handle_partial_failure.py +++ b/examples/error_handling/handle_partial_failure.py @@ -14,7 +14,6 @@ # limitations under the License. """This shows how to handle responses that may include partial_failure errors.""" - import argparse import sys import uuid @@ -22,13 +21,13 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_service import ( +from google.ads.googleads.v24.services.types.ad_group_service import ( AdGroupOperation, MutateAdGroupsResponse, MutateAdGroupsRequest, @@ -249,7 +248,7 @@ def print_results( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) main(googleads_client, args.customer_id, args.campaign_id) diff --git a/examples/error_handling/handle_rate_exceeded_error.py b/examples/error_handling/handle_rate_exceeded_error.py index 205cfdbb6..b7dfebde8 100755 --- a/examples/error_handling/handle_rate_exceeded_error.py +++ b/examples/error_handling/handle_rate_exceeded_error.py @@ -22,21 +22,20 @@ application. """ - import argparse from time import sleep from typing import List, Any from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.errors.types.quota_error import QuotaErrorEnum -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.errors.types.quota_error import QuotaErrorEnum +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation, MutateAdGroupCriteriaRequest, MutateAdGroupCriteriaResponse, @@ -231,7 +230,7 @@ def request_mutate_and_display_result( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) main(googleads_client, args.customer_id, args.ad_group_id) diff --git a/examples/error_handling/handle_responsive_search_ad_policy_violations.py b/examples/error_handling/handle_responsive_search_ad_policy_violations.py index 3f4bdacb2..e9c2bd83f 100755 --- a/examples/error_handling/handle_responsive_search_ad_policy_violations.py +++ b/examples/error_handling/handle_responsive_search_ad_policy_violations.py @@ -25,24 +25,24 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.ad_group_ad_service import ( +from google.ads.googleads.v24.services.services.ad_group_ad_service import ( AdGroupAdServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_ad_service import ( +from google.ads.googleads.v24.services.types.ad_group_ad_service import ( AdGroupAdOperation, MutateAdGroupAdsResponse, ) -from google.ads.googleads.v23.resources.types.ad_group_ad import AdGroupAd -from google.ads.googleads.v23.common.types.ad_type_infos import ( +from google.ads.googleads.v24.resources.types.ad_group_ad import AdGroupAd +from google.ads.googleads.v24.common.types.ad_type_infos import ( ResponsiveSearchAdInfo, ) -from google.ads.googleads.v23.common.types.ad_asset import ( +from google.ads.googleads.v24.common.types.ad_asset import ( AdTextAsset, ) -from google.ads.googleads.v23.errors.types.policy_finding_error import ( +from google.ads.googleads.v24.errors.types.policy_finding_error import ( PolicyFindingErrorEnum, ) @@ -264,7 +264,7 @@ def request_exemption( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/incentives/apply_incentive.py b/examples/incentives/apply_incentive.py index 369a90c08..f57534097 100644 --- a/examples/incentives/apply_incentive.py +++ b/examples/incentives/apply_incentive.py @@ -20,14 +20,16 @@ fetch_incentives.py example to get the available incentives. """ - import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services import ApplyIncentiveRequest, ApplyIncentiveResponse -from google.ads.googleads.v23.services.services.incentive_service.client import ( +from google.ads.googleads.v24.services import ( + ApplyIncentiveRequest, + ApplyIncentiveResponse, +) +from google.ads.googleads.v24.services.services.incentive_service.client import ( IncentiveServiceClient, ) @@ -46,7 +48,9 @@ def main( country_code: The country code of the user. incentive_id: The incentive ID to select. """ - incentive_service: IncentiveServiceClient = client.get_service("IncentiveService") + incentive_service: IncentiveServiceClient = client.get_service( + "IncentiveService" + ) apply_incentive_request: ApplyIncentiveRequest = client.get_type( "ApplyIncentiveRequest" ) @@ -96,7 +100,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main( @@ -115,4 +119,4 @@ def main( if error.location: for field_path_element in error.location.field_path_elements: print(f"\t\tOn field: {field_path_element.field_name}") - sys.exit(1) \ No newline at end of file + sys.exit(1) diff --git a/examples/incentives/fetch_incentives.py b/examples/incentives/fetch_incentives.py index 47151ac55..3fc40b7ba 100644 --- a/examples/incentives/fetch_incentives.py +++ b/examples/incentives/fetch_incentives.py @@ -17,14 +17,16 @@ To apply an incentive, use apply_incentive.py. """ - import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services import FetchIncentiveRequest, FetchIncentiveResponse -from google.ads.googleads.v23.services.services.incentive_service.client import ( +from google.ads.googleads.v24.services import ( + FetchIncentiveRequest, + FetchIncentiveResponse, +) +from google.ads.googleads.v24.services.services.incentive_service.client import ( IncentiveServiceClient, ) @@ -103,14 +105,14 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main( - googleads_client, - args.email_address, - args.language_code, - args.country_code, + googleads_client, + args.email_address, + args.language_code, + args.country_code, ) except GoogleAdsException as ex: print( diff --git a/examples/misc/add_ad_group_image_asset.py b/examples/misc/add_ad_group_image_asset.py index 588af7ada..745cdea46 100644 --- a/examples/misc/add_ad_group_image_asset.py +++ b/examples/misc/add_ad_group_image_asset.py @@ -17,17 +17,16 @@ To upload image assets, run misc/upload_image_asset.py. """ - import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.ad_group_asset import AdGroupAsset -from google.ads.googleads.v23.services.services.ad_group_asset_service.client import ( +from google.ads.googleads.v24.resources.types.ad_group_asset import AdGroupAsset +from google.ads.googleads.v24.services.services.ad_group_asset_service.client import ( AdGroupAssetServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_asset_service import ( +from google.ads.googleads.v24.services.types.ad_group_asset_service import ( AdGroupAssetOperation, MutateAdGroupAssetResult, MutateAdGroupAssetsResponse, @@ -98,7 +97,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main( diff --git a/examples/misc/campaign_report_to_csv.py b/examples/misc/campaign_report_to_csv.py index bafcc62d6..33f482efa 100755 --- a/examples/misc/campaign_report_to_csv.py +++ b/examples/misc/campaign_report_to_csv.py @@ -26,6 +26,7 @@ Write to file output.csv in the same directory as script without headers. $ python get_campaign_stats_to_csv.py -c 0123456789 -o output.csv """ + import argparse import csv from collections.abc import Iterator @@ -34,16 +35,15 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( GoogleAdsRow, SearchGoogleAdsStreamRequest, SearchGoogleAdsStreamResponse, ) - _DEFAULT_FILE_NAME = "campaign_report_to_csv_results.csv" _QUERY: str = """ SELECT @@ -168,7 +168,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main( diff --git a/examples/misc/set_custom_client_timeouts.py b/examples/misc/set_custom_client_timeouts.py index c8f05812b..73d3f5f04 100755 --- a/examples/misc/set_custom_client_timeouts.py +++ b/examples/misc/set_custom_client_timeouts.py @@ -22,7 +22,6 @@ https://grpc.io/docs/what-is-grpc/core-concepts/#rpc-life-cycle """ - import argparse from collections.abc import Iterator import sys @@ -30,10 +29,10 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.google_ads_service.client import ( +from google.ads.googleads.v24.services.services.google_ads_service.client import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( GoogleAdsRow, SearchGoogleAdsRequest, SearchGoogleAdsStreamRequest, @@ -42,7 +41,6 @@ from google.api_core.exceptions import DeadlineExceeded from google.api_core.retry import Retry - _CLIENT_TIMEOUT_SECONDS = 5 * 60 # 5 minutes. _QUERY: str = "SELECT campaign.id FROM campaign" @@ -194,6 +192,6 @@ def make_unary_call(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") main(googleads_client, args.customer_id) diff --git a/examples/misc/upload_image_asset.py b/examples/misc/upload_image_asset.py index 4ac5e6e06..0fbf2974a 100644 --- a/examples/misc/upload_image_asset.py +++ b/examples/misc/upload_image_asset.py @@ -17,18 +17,17 @@ To get image assets, run get_all_image_assets.py. """ - import argparse import sys from examples.utils.example_helpers import get_image_bytes_from_url from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.asset import Asset -from google.ads.googleads.v23.services.services.asset_service.client import ( +from google.ads.googleads.v24.resources.types.asset import Asset +from google.ads.googleads.v24.services.services.asset_service.client import ( AssetServiceClient, ) -from google.ads.googleads.v23.services.types.asset_service import ( +from google.ads.googleads.v24.services.types.asset_service import ( AssetOperation, MutateAssetResult, MutateAssetsResponse, @@ -85,7 +84,7 @@ def main(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main(googleads_client, args.customer_id) diff --git a/examples/planning/forecast_reach.py b/examples/planning/forecast_reach.py index 12ff84aa5..88b6140a0 100755 --- a/examples/planning/forecast_reach.py +++ b/examples/planning/forecast_reach.py @@ -20,19 +20,19 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.enums.types.reach_plan_age_range import ( +from google.ads.googleads.v24.enums.types.reach_plan_age_range import ( ReachPlanAgeRangeEnum, ) -from google.ads.googleads.v23.enums.types.gender_type import GenderTypeEnum -from google.ads.googleads.v23.enums.types.device import DeviceEnum -from google.ads.googleads.v23.common.types.criteria import ( +from google.ads.googleads.v24.enums.types.gender_type import GenderTypeEnum +from google.ads.googleads.v24.enums.types.device import DeviceEnum +from google.ads.googleads.v24.common.types.criteria import ( GenderInfo, DeviceInfo, ) -from google.ads.googleads.v23.services.services.reach_plan_service.client import ( +from google.ads.googleads.v24.services.services.reach_plan_service.client import ( ReachPlanServiceClient, ) -from google.ads.googleads.v23.services.types.reach_plan_service import ( +from google.ads.googleads.v24.services.types.reach_plan_service import ( ListPlannableLocationsResponse, PlannableLocation, ListPlannableProductsResponse, @@ -273,7 +273,7 @@ def forecast_manual_mix( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main(googleads_client, args.customer_id) diff --git a/examples/planning/generate_forecast_metrics.py b/examples/planning/generate_forecast_metrics.py index c4aff4f84..6ad0f3a30 100755 --- a/examples/planning/generate_forecast_metrics.py +++ b/examples/planning/generate_forecast_metrics.py @@ -24,20 +24,18 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.criteria import ( +from google.ads.googleads.v24.common.types.criteria import ( KeywordInfo, ) -from google.ads.googleads.v23.services.services.google_ads_service.client import ( +from google.ads.googleads.v24.services.services.google_ads_service.client import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.services.keyword_plan_idea_service.client import ( +from google.ads.googleads.v24.services.services.keyword_plan_idea_service.client import ( KeywordPlanIdeaServiceClient, ) -from google.ads.googleads.v23.services.types.keyword_plan_idea_service import ( +from google.ads.googleads.v24.services.types.keyword_plan_idea_service import ( CampaignToForecast, - CriterionBidModifier, ForecastAdGroup, - BiddableKeyword, GenerateKeywordForecastMetricsRequest, GenerateKeywordForecastMetricsResponse, ) @@ -79,10 +77,6 @@ def create_campaign_to_forecast(client: GoogleAdsClient) -> CampaignToForecast: campaign_to_forecast: CampaignToForecast = client.get_type( "CampaignToForecast" ) - campaign_to_forecast.keyword_plan_network = ( - client.enums.KeywordPlanNetworkEnum.GOOGLE_SEARCH - ) - # Set the bidding strategy. campaign_to_forecast.bidding_strategy.manual_cpc_bidding_strategy.max_cpc_bid_micros = ( 1000000 @@ -90,14 +84,10 @@ def create_campaign_to_forecast(client: GoogleAdsClient) -> CampaignToForecast: # For the list of geo target IDs, see: # https://developers.google.com/google-ads/api/reference/data/geotargets - criterion_bid_modifier: CriterionBidModifier = client.get_type( - "CriterionBidModifier" - ) # Geo target constant 2840 is for USA. - criterion_bid_modifier.geo_target_constant = ( + campaign_to_forecast.geo_target_constants.append( googleads_service.geo_target_constant_path("2840") ) - campaign_to_forecast.geo_modifiers.append(criterion_bid_modifier) # For the list of language criteria IDs, see: # https://developers.google.com/google-ads/api/reference/data/codes-formats#languages @@ -110,39 +100,21 @@ def create_campaign_to_forecast(client: GoogleAdsClient) -> CampaignToForecast: # product category, or cost per click. forecast_ad_group: ForecastAdGroup = client.get_type("ForecastAdGroup") - # Create and configure three BiddableKeyword instances. - biddable_keyword_1: BiddableKeyword = client.get_type("BiddableKeyword") - biddable_keyword_1.max_cpc_bid_micros = 2500000 - biddable_keyword_1.keyword.text = "mars cruise" - biddable_keyword_1.keyword.match_type = ( - client.enums.KeywordMatchTypeEnum.BROAD - ) - - biddable_keyword_2: BiddableKeyword = client.get_type("BiddableKeyword") - biddable_keyword_2.max_cpc_bid_micros = 1500000 - biddable_keyword_2.keyword.text = "cheap cruise" - biddable_keyword_2.keyword.match_type = ( - client.enums.KeywordMatchTypeEnum.PHRASE - ) + # Create and configure three KeywordInfo instances. + keyword_1: KeywordInfo = client.get_type("KeywordInfo") + keyword_1.text = "mars cruise" + keyword_1.match_type = client.enums.KeywordMatchTypeEnum.BROAD - biddable_keyword_3: BiddableKeyword = client.get_type("BiddableKeyword") - biddable_keyword_3.max_cpc_bid_micros = 1990000 - biddable_keyword_3.keyword.text = "cheap cruise" - biddable_keyword_3.keyword.match_type = ( - client.enums.KeywordMatchTypeEnum.EXACT - ) + keyword_2: KeywordInfo = client.get_type("KeywordInfo") + keyword_2.text = "cheap cruise" + keyword_2.match_type = client.enums.KeywordMatchTypeEnum.PHRASE - # Add the biddable keywords to the forecast ad group. - forecast_ad_group.biddable_keywords.extend( - [biddable_keyword_1, biddable_keyword_2, biddable_keyword_3] - ) + keyword_3: KeywordInfo = client.get_type("KeywordInfo") + keyword_3.text = "cheap cruise" + keyword_3.match_type = client.enums.KeywordMatchTypeEnum.EXACT - # Create and configure a negative keyword, then add it to the forecast ad - # group. - negative_keyword: KeywordInfo = client.get_type("KeywordInfo") - negative_keyword.text = "moon walk" - negative_keyword.match_type = client.enums.KeywordMatchTypeEnum.BROAD - forecast_ad_group.negative_keywords.append(negative_keyword) + # Add the keywords to the forecast ad group. + forecast_ad_group.keywords.extend([keyword_1, keyword_2, keyword_3]) campaign_to_forecast.ad_groups.append(forecast_ad_group) @@ -186,7 +158,6 @@ def generate_forecast_metrics( metrics = response.campaign_forecast_metrics print(f"Estimated daily clicks: {metrics.clicks}") - print(f"Estimated daily impressions: {metrics.impressions}") print(f"Estimated daily average CPC: {metrics.average_cpc_micros}") # [END generate_forecast_metrics] @@ -208,7 +179,7 @@ def generate_forecast_metrics( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main(googleads_client, args.customer_id) diff --git a/examples/planning/generate_historical_metrics.py b/examples/planning/generate_historical_metrics.py index 71de4c9ac..9e1daa3bb 100755 --- a/examples/planning/generate_historical_metrics.py +++ b/examples/planning/generate_historical_metrics.py @@ -24,17 +24,17 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.keyword_plan_common import ( +from google.ads.googleads.v24.common.types.keyword_plan_common import ( KeywordPlanHistoricalMetrics, MonthlySearchVolume, ) -from google.ads.googleads.v23.services.services.google_ads_service.client import ( +from google.ads.googleads.v24.services.services.google_ads_service.client import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.services.keyword_plan_idea_service.client import ( +from google.ads.googleads.v24.services.services.keyword_plan_idea_service.client import ( KeywordPlanIdeaServiceClient, ) -from google.ads.googleads.v23.services.types.keyword_plan_idea_service import ( +from google.ads.googleads.v24.services.types.keyword_plan_idea_service import ( GenerateKeywordHistoricalMetricsRequest, GenerateKeywordHistoricalMetricsResponse, GenerateKeywordHistoricalMetricsResult, @@ -153,7 +153,7 @@ def generate_historical_metrics(client: GoogleAdsClient, customer_id: str): # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main(googleads_client, args.customer_id) diff --git a/examples/planning/generate_keyword_ideas.py b/examples/planning/generate_keyword_ideas.py index e1597fa3a..8d70e59a8 100755 --- a/examples/planning/generate_keyword_ideas.py +++ b/examples/planning/generate_keyword_ideas.py @@ -14,27 +14,26 @@ # limitations under the License. """This example generates keyword ideas from a list of seed keywords.""" - import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.enums.types.keyword_plan_competition_level import ( +from google.ads.googleads.v24.enums.types.keyword_plan_competition_level import ( KeywordPlanCompetitionLevelEnum, ) -from google.ads.googleads.v23.enums.types.keyword_plan_network import ( +from google.ads.googleads.v24.enums.types.keyword_plan_network import ( KeywordPlanNetworkEnum, ) -from google.ads.googleads.v23.services.services.geo_target_constant_service.client import ( +from google.ads.googleads.v24.services.services.geo_target_constant_service.client import ( GeoTargetConstantServiceClient, ) -from google.ads.googleads.v23.services.services.google_ads_service.client import ( +from google.ads.googleads.v24.services.services.google_ads_service.client import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.services.keyword_plan_idea_service.client import ( +from google.ads.googleads.v24.services.services.keyword_plan_idea_service.client import ( KeywordPlanIdeaServiceClient, ) -from google.ads.googleads.v23.services.types.keyword_plan_idea_service import ( +from google.ads.googleads.v24.services.types.keyword_plan_idea_service import ( GenerateKeywordIdeasRequest, GenerateKeywordIdeaResult, ) @@ -205,7 +204,7 @@ def map_locations_ids_to_resource_names( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main( diff --git a/examples/planning/get_ad_group_criterion_cpc_bid_simulations.py b/examples/planning/get_ad_group_criterion_cpc_bid_simulations.py index 7889e314e..495dceda7 100755 --- a/examples/planning/get_ad_group_criterion_cpc_bid_simulations.py +++ b/examples/planning/get_ad_group_criterion_cpc_bid_simulations.py @@ -23,16 +23,16 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.ad_group_criterion_simulation import ( +from google.ads.googleads.v24.resources.types.ad_group_criterion_simulation import ( AdGroupCriterionSimulation, ) -from google.ads.googleads.v23.common.types.simulation import ( +from google.ads.googleads.v24.common.types.simulation import ( CpcBidSimulationPoint, ) -from google.ads.googleads.v23.services.services.google_ads_service.client import ( +from google.ads.googleads.v24.services.services.google_ads_service.client import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( SearchGoogleAdsStreamResponse, GoogleAdsRow, ) @@ -120,7 +120,7 @@ def main(client: GoogleAdsClient, customer_id: str, ad_group_id: str): # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main(googleads_client, args.customer_id, args.ad_group_id) diff --git a/examples/recommendations/detect_and_apply_recommendations.py b/examples/recommendations/detect_and_apply_recommendations.py index 295484da4..363fe85ba 100755 --- a/examples/recommendations/detect_and_apply_recommendations.py +++ b/examples/recommendations/detect_and_apply_recommendations.py @@ -28,17 +28,16 @@ https://developers.google.com/google-ads/api/docs/recommendations#recommendations-in-campaign-construction """ - import argparse import sys from typing import List, Iterable from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( GoogleAdsRow, ) -from google.ads.googleads.v23.services.types.recommendation_service import ( +from google.ads.googleads.v24.services.types.recommendation_service import ( ApplyRecommendationOperation, ApplyRecommendationResult, ) @@ -190,7 +189,7 @@ def apply_recommendations( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/recommendations/dismiss_recommendation.py b/examples/recommendations/dismiss_recommendation.py index cdfc61ee5..018f585fc 100755 --- a/examples/recommendations/dismiss_recommendation.py +++ b/examples/recommendations/dismiss_recommendation.py @@ -17,16 +17,15 @@ To retrieve recommendations for text ads, run get_text_ad_recommendations.py. """ - import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.recommendation_service import ( +from google.ads.googleads.v24.services.services.recommendation_service import ( RecommendationServiceClient, ) -from google.ads.googleads.v23.services.types.recommendation_service import ( +from google.ads.googleads.v24.services.types.recommendation_service import ( DismissRecommendationRequest, DismissRecommendationResponse, ) @@ -82,7 +81,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/recommendations/generate_budget_recommendations.py b/examples/recommendations/generate_budget_recommendations.py index a80884234..abe2b7073 100644 --- a/examples/recommendations/generate_budget_recommendations.py +++ b/examples/recommendations/generate_budget_recommendations.py @@ -24,21 +24,20 @@ To get impact metrics for a custom budget, run get_recommendation_impact_metrics.py. """ - import argparse import sys from typing import List, Dict, Any from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.recommendation_service import ( +from google.ads.googleads.v24.services.services.recommendation_service import ( RecommendationServiceClient, ) -from google.ads.googleads.v23.services.types.recommendation_service import ( +from google.ads.googleads.v24.services.types.recommendation_service import ( GenerateRecommendationsRequest, GenerateRecommendationsResponse, ) -from google.ads.googleads.v23.resources.types.recommendation import ( +from google.ads.googleads.v24.resources.types.recommendation import ( Recommendation, ) @@ -134,7 +133,7 @@ def main(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/recommendations/get_recommendation_impact_metrics.py b/examples/recommendations/get_recommendation_impact_metrics.py index 516724a45..0a2c8e1be 100644 --- a/examples/recommendations/get_recommendation_impact_metrics.py +++ b/examples/recommendations/get_recommendation_impact_metrics.py @@ -24,21 +24,20 @@ To get budget recommendations, run generate_budget_recommendations.py. """ - import argparse import sys from typing import List, Dict, Any from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.recommendation_service import ( +from google.ads.googleads.v24.services.services.recommendation_service import ( RecommendationServiceClient, ) -from google.ads.googleads.v23.services.types.recommendation_service import ( +from google.ads.googleads.v24.services.types.recommendation_service import ( GenerateRecommendationsRequest, GenerateRecommendationsResponse, ) -from google.ads.googleads.v23.resources.types.recommendation import ( +from google.ads.googleads.v24.resources.types.recommendation import ( Recommendation, ) @@ -143,7 +142,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/remarketing/add_conversion_action.py b/examples/remarketing/add_conversion_action.py index 64bf59b4c..58462fd4e 100755 --- a/examples/remarketing/add_conversion_action.py +++ b/examples/remarketing/add_conversion_action.py @@ -14,20 +14,19 @@ # limitations under the License. """This example illustrates adding a conversion action.""" - import argparse import sys import uuid from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.conversion_action import ( +from google.ads.googleads.v24.resources.types.conversion_action import ( ConversionAction, ) -from google.ads.googleads.v23.services.services.conversion_action_service import ( +from google.ads.googleads.v24.services.services.conversion_action_service import ( ConversionActionServiceClient, ) -from google.ads.googleads.v23.services.types.conversion_action_service import ( +from google.ads.googleads.v24.services.types.conversion_action_service import ( ConversionActionOperation, MutateConversionActionsResponse, ) @@ -99,7 +98,7 @@ def main(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/remarketing/add_conversion_based_user_list.py b/examples/remarketing/add_conversion_based_user_list.py index 56eb0180b..dc1ddaa25 100644 --- a/examples/remarketing/add_conversion_based_user_list.py +++ b/examples/remarketing/add_conversion_based_user_list.py @@ -26,15 +26,15 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.user_lists import UserListActionInfo -from google.ads.googleads.v23.resources.types.user_list import UserList -from google.ads.googleads.v23.services.services.conversion_action_service import ( +from google.ads.googleads.v24.common.types.user_lists import UserListActionInfo +from google.ads.googleads.v24.resources.types.user_list import UserList +from google.ads.googleads.v24.services.services.conversion_action_service import ( ConversionActionServiceClient, ) -from google.ads.googleads.v23.services.services.user_list_service import ( +from google.ads.googleads.v24.services.services.user_list_service import ( UserListServiceClient, ) -from google.ads.googleads.v23.services.types.user_list_service import ( +from google.ads.googleads.v24.services.types.user_list_service import ( UserListOperation, MutateUserListsResponse, ) @@ -127,7 +127,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/remarketing/add_custom_audience.py b/examples/remarketing/add_custom_audience.py index 9efc790ab..cc54c7413 100755 --- a/examples/remarketing/add_custom_audience.py +++ b/examples/remarketing/add_custom_audience.py @@ -19,25 +19,24 @@ https://support.google.com/google-ads/answer/9805516 """ - import argparse import sys from uuid import uuid4 from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.enums.types.custom_audience_member_type import ( +from google.ads.googleads.v24.enums.types.custom_audience_member_type import ( CustomAudienceMemberTypeEnum, ) -from google.ads.googleads.v23.resources.types.custom_audience import ( +from google.ads.googleads.v24.resources.types.custom_audience import ( CustomAudience, CustomAudienceMember, ) -from google.ads.googleads.v23.services.types.custom_audience_service import ( +from google.ads.googleads.v24.services.types.custom_audience_service import ( CustomAudienceOperation, MutateCustomAudiencesResponse, ) -from google.ads.googleads.v23.services.services.custom_audience_service import ( +from google.ads.googleads.v24.services.services.custom_audience_service import ( CustomAudienceServiceClient, ) @@ -166,7 +165,7 @@ def create_custom_audience_member( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/remarketing/add_customer_match_user_list.py b/examples/remarketing/add_customer_match_user_list.py index 7324003d2..57991eaf4 100755 --- a/examples/remarketing/add_customer_match_user_list.py +++ b/examples/remarketing/add_customer_match_user_list.py @@ -37,40 +37,40 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.services.user_list_service import ( +from google.ads.googleads.v24.services.services.user_list_service import ( UserListServiceClient, ) -from google.ads.googleads.v23.services.services.offline_user_data_job_service import ( +from google.ads.googleads.v24.services.services.offline_user_data_job_service import ( OfflineUserDataJobServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( SearchGoogleAdsStreamResponse, ) -from google.ads.googleads.v23.services.types.user_list_service import ( +from google.ads.googleads.v24.services.types.user_list_service import ( UserListOperation, MutateUserListsResponse, ) -from google.ads.googleads.v23.resources.types.user_list import UserList -from google.ads.googleads.v23.services.types.offline_user_data_job_service import ( +from google.ads.googleads.v24.resources.types.user_list import UserList +from google.ads.googleads.v24.services.types.offline_user_data_job_service import ( AddOfflineUserDataJobOperationsRequest, OfflineUserDataJobOperation, AddOfflineUserDataJobOperationsResponse, CreateOfflineUserDataJobResponse, ) -from google.ads.googleads.v23.resources.types.offline_user_data_job import ( +from google.ads.googleads.v24.resources.types.offline_user_data_job import ( OfflineUserDataJob, ) -from google.ads.googleads.v23.common.types.criteria import ( +from google.ads.googleads.v24.common.types.criteria import ( AddressInfo, ) -from google.ads.googleads.v23.common.types.offline_user_data import ( +from google.ads.googleads.v24.common.types.offline_user_data import ( UserData, UserIdentifier, ) -from google.ads.googleads.v23.errors.types.errors import ( +from google.ads.googleads.v24.errors.types.errors import ( GoogleAdsFailure, GoogleAdsError, ) @@ -623,7 +623,7 @@ def normalize_and_hash(s: str, remove_all_whitespace: bool) -> str: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) parser: argparse.ArgumentParser = argparse.ArgumentParser( diff --git a/examples/remarketing/add_dynamic_remarketing_asset.py b/examples/remarketing/add_dynamic_remarketing_asset.py index 14d0db826..9ca8b50d2 100755 --- a/examples/remarketing/add_dynamic_remarketing_asset.py +++ b/examples/remarketing/add_dynamic_remarketing_asset.py @@ -14,53 +14,52 @@ # limitations under the License. """Adds an asset for use in dynamic remarketing.""" - import argparse from datetime import datetime import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.asset_types import ( +from google.ads.googleads.v24.common.types.asset_types import ( DynamicEducationAsset, ) -from google.ads.googleads.v23.resources.types.asset import Asset -from google.ads.googleads.v23.resources.types.asset_set import AssetSet -from google.ads.googleads.v23.resources.types.asset_set_asset import ( +from google.ads.googleads.v24.resources.types.asset import Asset +from google.ads.googleads.v24.resources.types.asset_set import AssetSet +from google.ads.googleads.v24.resources.types.asset_set_asset import ( AssetSetAsset, ) -from google.ads.googleads.v23.resources.types.campaign_asset_set import ( +from google.ads.googleads.v24.resources.types.campaign_asset_set import ( CampaignAssetSet, ) -from google.ads.googleads.v23.services.services.asset_service import ( +from google.ads.googleads.v24.services.services.asset_service import ( AssetServiceClient, ) -from google.ads.googleads.v23.services.types.asset_service import ( +from google.ads.googleads.v24.services.types.asset_service import ( AssetOperation, MutateAssetsResponse, ) -from google.ads.googleads.v23.services.services.asset_set_service import ( +from google.ads.googleads.v24.services.services.asset_set_service import ( AssetSetServiceClient, ) -from google.ads.googleads.v23.services.types.asset_set_service import ( +from google.ads.googleads.v24.services.types.asset_set_service import ( AssetSetOperation, MutateAssetSetsResponse, ) -from google.ads.googleads.v23.services.services.asset_set_asset_service import ( +from google.ads.googleads.v24.services.services.asset_set_asset_service import ( AssetSetAssetServiceClient, ) -from google.ads.googleads.v23.services.types.asset_set_asset_service import ( +from google.ads.googleads.v24.services.types.asset_set_asset_service import ( AssetSetAssetOperation, MutateAssetSetAssetsResponse, ) -from google.ads.googleads.v23.services.services.campaign_asset_set_service import ( +from google.ads.googleads.v24.services.services.campaign_asset_set_service import ( CampaignAssetSetServiceClient, ) -from google.ads.googleads.v23.services.types.campaign_asset_set_service import ( +from google.ads.googleads.v24.services.types.campaign_asset_set_service import ( CampaignAssetSetOperation, MutateCampaignAssetSetsResponse, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) @@ -279,7 +278,7 @@ def link_asset_set_to_campaign( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/remarketing/add_flexible_rule_user_list.py b/examples/remarketing/add_flexible_rule_user_list.py index 9a271866a..1eb3cd84a 100644 --- a/examples/remarketing/add_flexible_rule_user_list.py +++ b/examples/remarketing/add_flexible_rule_user_list.py @@ -24,7 +24,7 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.user_lists import ( +from google.ads.googleads.v24.common.types.user_lists import ( FlexibleRuleOperandInfo, FlexibleRuleUserListInfo, RuleBasedUserListInfo, @@ -32,11 +32,11 @@ UserListRuleItemGroupInfo, UserListRuleItemInfo, ) -from google.ads.googleads.v23.resources.types.user_list import UserList -from google.ads.googleads.v23.services.services.user_list_service import ( +from google.ads.googleads.v24.resources.types.user_list import UserList +from google.ads.googleads.v24.services.services.user_list_service import ( UserListServiceClient, ) -from google.ads.googleads.v23.services.types.user_list_service import ( +from google.ads.googleads.v24.services.types.user_list_service import ( UserListOperation, MutateUserListsResponse, ) @@ -208,7 +208,7 @@ def create_user_list_rule_info_from_url( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/remarketing/add_logical_user_list.py b/examples/remarketing/add_logical_user_list.py index b8a1ef1f8..2cd9e9d79 100644 --- a/examples/remarketing/add_logical_user_list.py +++ b/examples/remarketing/add_logical_user_list.py @@ -25,15 +25,15 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.user_lists import ( +from google.ads.googleads.v24.common.types.user_lists import ( LogicalUserListOperandInfo, UserListLogicalRuleInfo, ) -from google.ads.googleads.v23.resources.types.user_list import UserList -from google.ads.googleads.v23.services.services.user_list_service import ( +from google.ads.googleads.v24.resources.types.user_list import UserList +from google.ads.googleads.v24.services.services.user_list_service import ( UserListServiceClient, ) -from google.ads.googleads.v23.services.types.user_list_service import ( +from google.ads.googleads.v24.services.types.user_list_service import ( UserListOperation, MutateUserListsResponse, ) @@ -130,7 +130,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/remarketing/add_merchant_center_dynamic_remarketing_campaign.py b/examples/remarketing/add_merchant_center_dynamic_remarketing_campaign.py index a8cd6cb56..97ec08957 100644 --- a/examples/remarketing/add_merchant_center_dynamic_remarketing_campaign.py +++ b/examples/remarketing/add_merchant_center_dynamic_remarketing_campaign.py @@ -18,7 +18,6 @@ targets a user list for remarketing purposes. """ - import argparse import requests import sys @@ -26,53 +25,53 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.ad_group import AdGroup -from google.ads.googleads.v23.resources.types.ad_group_ad import AdGroupAd -from google.ads.googleads.v23.resources.types.ad_group_criterion import ( +from google.ads.googleads.v24.resources.types.ad_group import AdGroup +from google.ads.googleads.v24.resources.types.ad_group_ad import AdGroupAd +from google.ads.googleads.v24.resources.types.ad_group_criterion import ( AdGroupCriterion, ) -from google.ads.googleads.v23.resources.types.asset import Asset -from google.ads.googleads.v23.resources.types.campaign import Campaign -from google.ads.googleads.v23.services.services.ad_group_ad_service import ( +from google.ads.googleads.v24.resources.types.asset import Asset +from google.ads.googleads.v24.resources.types.campaign import Campaign +from google.ads.googleads.v24.services.services.ad_group_ad_service import ( AdGroupAdServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.services.asset_service import ( +from google.ads.googleads.v24.services.services.asset_service import ( AssetServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_ad_service import ( +from google.ads.googleads.v24.services.types.ad_group_ad_service import ( AdGroupAdOperation, MutateAdGroupAdsResponse, ) -from google.ads.googleads.v23.services.types.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation, MutateAdGroupCriteriaResponse, ) -from google.ads.googleads.v23.services.types.ad_group_service import ( +from google.ads.googleads.v24.services.types.ad_group_service import ( AdGroupOperation, MutateAdGroupsResponse, ) -from google.ads.googleads.v23.services.types.asset_service import ( +from google.ads.googleads.v24.services.types.asset_service import ( AssetOperation, MutateAssetsResponse, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, MutateCampaignsResponse, ) -from google.ads.googleads.v23.common.types.ad_asset import ( +from google.ads.googleads.v24.common.types.ad_asset import ( AdImageAsset, AdTextAsset, ) -from google.ads.googleads.v23.common.types.ad_type_infos import ( +from google.ads.googleads.v24.common.types.ad_type_infos import ( ResponsiveDisplayAdInfo, ) @@ -427,7 +426,7 @@ def attach_user_list( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/remarketing/set_up_advanced_remarketing.py b/examples/remarketing/set_up_advanced_remarketing.py index ea138961a..3317d5085 100644 --- a/examples/remarketing/set_up_advanced_remarketing.py +++ b/examples/remarketing/set_up_advanced_remarketing.py @@ -25,7 +25,7 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.user_lists import ( +from google.ads.googleads.v24.common.types.user_lists import ( FlexibleRuleOperandInfo, FlexibleRuleUserListInfo, RuleBasedUserListInfo, @@ -35,14 +35,14 @@ UserListNumberRuleItemInfo, UserListStringRuleItemInfo, ) -from google.ads.googleads.v23.enums.types.user_list_date_rule_item_operator import ( +from google.ads.googleads.v24.enums.types.user_list_date_rule_item_operator import ( UserListDateRuleItemOperatorEnum, ) -from google.ads.googleads.v23.resources.types.user_list import UserList -from google.ads.googleads.v23.services.services.user_list_service import ( +from google.ads.googleads.v24.resources.types.user_list import UserList +from google.ads.googleads.v24.services.services.user_list_service import ( UserListServiceClient, ) -from google.ads.googleads.v23.services.types.user_list_service import ( +from google.ads.googleads.v24.services.types.user_list_service import ( MutateUserListsResponse, UserListOperation, ) @@ -246,7 +246,7 @@ def main(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/remarketing/set_up_remarketing.py b/examples/remarketing/set_up_remarketing.py index 77f1c0fe1..91259fefb 100755 --- a/examples/remarketing/set_up_remarketing.py +++ b/examples/remarketing/set_up_remarketing.py @@ -24,7 +24,6 @@ purposes. """ - import argparse import sys from typing import List @@ -34,45 +33,45 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.user_lists import ( +from google.ads.googleads.v24.common.types.user_lists import ( FlexibleRuleOperandInfo, FlexibleRuleUserListInfo, UserListRuleItemGroupInfo, UserListRuleItemInfo, ) -from google.ads.googleads.v23.resources.types.ad_group_criterion import ( +from google.ads.googleads.v24.resources.types.ad_group_criterion import ( AdGroupCriterion, ) -from google.ads.googleads.v23.resources.types.campaign_criterion import ( +from google.ads.googleads.v24.resources.types.campaign_criterion import ( CampaignCriterion, ) -from google.ads.googleads.v23.resources.types.user_list import UserList -from google.ads.googleads.v23.services.services.ad_group_criterion_service import ( +from google.ads.googleads.v24.resources.types.user_list import UserList +from google.ads.googleads.v24.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_criterion_service import ( +from google.ads.googleads.v24.services.services.campaign_criterion_service import ( CampaignCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.services.user_list_service import ( +from google.ads.googleads.v24.services.services.user_list_service import ( UserListServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation, MutateAdGroupCriteriaResponse, ) -from google.ads.googleads.v23.services.types.campaign_criterion_service import ( +from google.ads.googleads.v24.services.types.campaign_criterion_service import ( CampaignCriterionOperation, MutateCampaignCriteriaResponse, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( GoogleAdsRow, SearchGoogleAdsRequest, SearchGoogleAdsResponse, ) -from google.ads.googleads.v23.services.types.user_list_service import ( +from google.ads.googleads.v24.services.types.user_list_service import ( MutateUserListsResponse, UserListOperation, ) @@ -524,7 +523,7 @@ def modify_campaign_bids( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/remarketing/update_audience_target_restriction.py b/examples/remarketing/update_audience_target_restriction.py index 0af4faaaf..e6d729551 100644 --- a/examples/remarketing/update_audience_target_restriction.py +++ b/examples/remarketing/update_audience_target_restriction.py @@ -14,31 +14,30 @@ # limitations under the License. """Updates the audience target restriction of a given ad group to bid only.""" - import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.targeting_setting import ( +from google.ads.googleads.v24.common.types.targeting_setting import ( TargetingSetting, TargetRestriction, ) -from google.ads.googleads.v23.enums.types.targeting_dimension import ( +from google.ads.googleads.v24.enums.types.targeting_dimension import ( TargetingDimensionEnum, ) -from google.ads.googleads.v23.resources.types.ad_group import AdGroup -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.resources.types.ad_group import AdGroup +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_service import ( +from google.ads.googleads.v24.services.types.ad_group_service import ( AdGroupOperation, MutateAdGroupsResponse, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( SearchGoogleAdsResponse, ) from google.api_core import protobuf_helpers @@ -230,7 +229,7 @@ def update_targeting_setting( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/remarketing/upload_call_conversion.py b/examples/remarketing/upload_call_conversion.py index 850f575ad..e2170ab32 100644 --- a/examples/remarketing/upload_call_conversion.py +++ b/examples/remarketing/upload_call_conversion.py @@ -17,17 +17,16 @@ To set up a conversion action, run the add_conversion_action.py example. """ - import argparse import sys from typing import Optional from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.conversion_upload_service import ( +from google.ads.googleads.v24.services.services.conversion_upload_service import ( ConversionUploadServiceClient, ) -from google.ads.googleads.v23.services.types.conversion_upload_service import ( +from google.ads.googleads.v24.services.types.conversion_upload_service import ( CallConversion, CustomVariable, UploadCallConversionsResponse, @@ -151,7 +150,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) parser = argparse.ArgumentParser( diff --git a/examples/remarketing/upload_conversion_adjustment.py b/examples/remarketing/upload_conversion_adjustment.py index fe0511ac0..60f7c4e5f 100644 --- a/examples/remarketing/upload_conversion_adjustment.py +++ b/examples/remarketing/upload_conversion_adjustment.py @@ -17,7 +17,6 @@ To set up a conversion action, run the add_conversion_action.py example. """ - import argparse import sys from typing import Optional, Iterable @@ -26,20 +25,20 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.enums.types.conversion_adjustment_type import ( +from google.ads.googleads.v24.enums.types.conversion_adjustment_type import ( ConversionAdjustmentTypeEnum, ) -from google.ads.googleads.v23.errors.types.errors import ( +from google.ads.googleads.v24.errors.types.errors import ( GoogleAdsError, GoogleAdsFailure, ) -from google.ads.googleads.v23.services.services.conversion_action_service import ( +from google.ads.googleads.v24.services.services.conversion_action_service import ( ConversionActionServiceClient, ) -from google.ads.googleads.v23.services.services.conversion_adjustment_upload_service import ( +from google.ads.googleads.v24.services.services.conversion_adjustment_upload_service import ( ConversionAdjustmentUploadServiceClient, ) -from google.ads.googleads.v23.services.types.conversion_adjustment_upload_service import ( +from google.ads.googleads.v24.services.types.conversion_adjustment_upload_service import ( ConversionAdjustment, ConversionAdjustmentResult, UploadConversionAdjustmentsRequest, @@ -176,7 +175,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) parser: argparse.ArgumentParser = argparse.ArgumentParser( diff --git a/examples/remarketing/upload_enhanced_conversions_for_leads.py b/examples/remarketing/upload_enhanced_conversions_for_leads.py index 73f9f16c7..f8c6f3269 100644 --- a/examples/remarketing/upload_enhanced_conversions_for_leads.py +++ b/examples/remarketing/upload_enhanced_conversions_for_leads.py @@ -20,7 +20,6 @@ that drove the lead. """ - import argparse import hashlib import re @@ -29,16 +28,16 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.offline_user_data import ( +from google.ads.googleads.v24.common.types.offline_user_data import ( UserIdentifier, ) -from google.ads.googleads.v23.services.services.conversion_action_service import ( +from google.ads.googleads.v24.services.services.conversion_action_service import ( ConversionActionServiceClient, ) -from google.ads.googleads.v23.services.services.conversion_upload_service import ( +from google.ads.googleads.v24.services.services.conversion_upload_service import ( ConversionUploadServiceClient, ) -from google.ads.googleads.v23.services.types.conversion_upload_service import ( +from google.ads.googleads.v24.services.types.conversion_upload_service import ( ClickConversion, ClickConversionResult, SessionAttributeKeyValuePair, @@ -259,7 +258,7 @@ def normalize_and_hash_email_address(email_address: str) -> str: # Removes any '.' and '+' characters from the portion of the email address # before the domain chars_to_remove = ".+" - translation_table = str.maketrans('', '', chars_to_remove) + translation_table = str.maketrans("", "", chars_to_remove) email_parts[0] = email_parts[0].translate(translation_table) normalized_email = "@".join(email_parts) @@ -286,7 +285,7 @@ def normalize_and_hash(s: str) -> str: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) parser: argparse.ArgumentParser = argparse.ArgumentParser( diff --git a/examples/remarketing/upload_enhanced_conversions_for_web.py b/examples/remarketing/upload_enhanced_conversions_for_web.py index 024c62b33..aa2a3f578 100644 --- a/examples/remarketing/upload_enhanced_conversions_for_web.py +++ b/examples/remarketing/upload_enhanced_conversions_for_web.py @@ -17,7 +17,6 @@ The conversion adjustment contains hashed user identifiers and an order ID. """ - import argparse import hashlib import re @@ -236,7 +235,7 @@ def normalize_and_hash_email_address(email_address): # Removes any '.' and '+' characters from the portion of the email address # before the domain chars_to_remove = ".+" - translation_table = str.maketrans('', '', chars_to_remove) + translation_table = str.maketrans("", "", chars_to_remove) email_parts[0] = email_parts[0].translate(translation_table) normalized_email = "@".join(email_parts) @@ -306,7 +305,7 @@ def normalize_and_hash(s): # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v23") + googleads_client = GoogleAdsClient.load_from_storage(version="v24") try: main( diff --git a/examples/remarketing/upload_offline_conversion.py b/examples/remarketing/upload_offline_conversion.py index 6cd2a0633..4ca0f8b1d 100644 --- a/examples/remarketing/upload_offline_conversion.py +++ b/examples/remarketing/upload_offline_conversion.py @@ -19,20 +19,19 @@ To set up a conversion action, run the add_conversion_action.py example. """ - import argparse import sys from typing import Optional from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.services.services.conversion_action_service import ( +from google.ads.googleads.v24.services.services.conversion_action_service import ( ConversionActionServiceClient, ) -from google.ads.googleads.v23.services.services.conversion_upload_service import ( +from google.ads.googleads.v24.services.services.conversion_upload_service import ( ConversionUploadServiceClient, ) -from google.ads.googleads.v23.services.types.conversion_upload_service import ( +from google.ads.googleads.v24.services.types.conversion_upload_service import ( ClickConversion, ClickConversionResult, CustomVariable, @@ -161,7 +160,7 @@ def main( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) parser: argparse.ArgumentParser = argparse.ArgumentParser( diff --git a/examples/remarketing/upload_store_sales_transactions.py b/examples/remarketing/upload_store_sales_transactions.py index 3f10ffe8a..5e512f5ba 100644 --- a/examples/remarketing/upload_store_sales_transactions.py +++ b/examples/remarketing/upload_store_sales_transactions.py @@ -29,36 +29,36 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.offline_user_data import ( +from google.ads.googleads.v24.common.types.offline_user_data import ( ItemAttribute, StoreSalesMetadata, StoreSalesThirdPartyMetadata, UserData, UserIdentifier, ) -from google.ads.googleads.v23.enums.types.offline_user_data_job_status import ( +from google.ads.googleads.v24.enums.types.offline_user_data_job_status import ( OfflineUserDataJobStatusEnum, ) -from google.ads.googleads.v23.enums.types.offline_user_data_job_type import ( +from google.ads.googleads.v24.enums.types.offline_user_data_job_type import ( OfflineUserDataJobTypeEnum, ) -from google.ads.googleads.v23.errors.types.errors import ( +from google.ads.googleads.v24.errors.types.errors import ( GoogleAdsError, GoogleAdsFailure, ) -from google.ads.googleads.v23.resources.types.offline_user_data_job import ( +from google.ads.googleads.v24.resources.types.offline_user_data_job import ( OfflineUserDataJob, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.services.offline_user_data_job_service import ( +from google.ads.googleads.v24.services.services.offline_user_data_job_service import ( OfflineUserDataJobServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( GoogleAdsRow, ) -from google.ads.googleads.v23.services.types.offline_user_data_job_service import ( +from google.ads.googleads.v24.services.types.offline_user_data_job_service import ( AddOfflineUserDataJobOperationsRequest, AddOfflineUserDataJobOperationsResponse, CreateOfflineUserDataJobResponse, @@ -670,7 +670,7 @@ def check_job_status( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) parser: argparse.ArgumentParser = argparse.ArgumentParser( diff --git a/examples/reporting/parallel_report_download.py b/examples/reporting/parallel_report_download.py index 29daf6b34..2517b863e 100644 --- a/examples/reporting/parallel_report_download.py +++ b/examples/reporting/parallel_report_download.py @@ -27,14 +27,14 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.errors.types import ( +from google.ads.googleads.v24.errors.types import ( ErrorLocation, GoogleAdsError, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types import ( +from google.ads.googleads.v24.services.types import ( GoogleAdsRow, SearchGoogleAdsStreamResponse, ) @@ -224,7 +224,7 @@ def generate_inputs( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) # Override the login_customer_id on the GoogleAdsClient, if specified. if args.login_customer_id is not None: diff --git a/examples/shopping_ads/add_listing_scope.py b/examples/shopping_ads/add_listing_scope.py index 8b80b5f3e..9f506f485 100755 --- a/examples/shopping_ads/add_listing_scope.py +++ b/examples/shopping_ads/add_listing_scope.py @@ -33,25 +33,25 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.criteria import ( +from google.ads.googleads.v24.common.types.criteria import ( ListingDimensionInfo, ) -from google.ads.googleads.v23.enums.types.product_custom_attribute_index import ( +from google.ads.googleads.v24.enums.types.product_custom_attribute_index import ( ProductCustomAttributeIndexEnum, ) -from google.ads.googleads.v23.enums.types.product_type_level import ( +from google.ads.googleads.v24.enums.types.product_type_level import ( ProductTypeLevelEnum, ) -from google.ads.googleads.v23.resources.types.campaign_criterion import ( +from google.ads.googleads.v24.resources.types.campaign_criterion import ( CampaignCriterion, ) -from google.ads.googleads.v23.services.services.campaign_criterion_service import ( +from google.ads.googleads.v24.services.services.campaign_criterion_service import ( CampaignCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.types.campaign_criterion_service import ( +from google.ads.googleads.v24.services.types.campaign_criterion_service import ( CampaignCriterionOperation, MutateCampaignCriteriaResponse, ) @@ -154,7 +154,7 @@ def main(client: GoogleAdsClient, customer_id: str, campaign_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/shopping_ads/add_performance_max_product_listing_group_tree.py b/examples/shopping_ads/add_performance_max_product_listing_group_tree.py index 9e6a8ec18..1a52e3414 100644 --- a/examples/shopping_ads/add_performance_max_product_listing_group_tree.py +++ b/examples/shopping_ads/add_performance_max_product_listing_group_tree.py @@ -22,32 +22,30 @@ shopping_ads/add_performance_max_retail_campaign.py example. """ - import argparse import sys from typing import Dict, List, Optional from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.asset_group_listing_group_filter import ( +from google.ads.googleads.v24.resources.types.asset_group_listing_group_filter import ( ListingGroupFilterDimension, ) -from google.ads.googleads.v23.resources.types.asset_group_listing_group_filter import ( +from google.ads.googleads.v24.resources.types.asset_group_listing_group_filter import ( AssetGroupListingGroupFilter, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( MutateGoogleAdsResponse, SearchGoogleAdsRequest, SearchGoogleAdsResponse, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( MutateOperation, ) - # We specify temporary IDs that are specific to a single mutate request. # Temporary IDs are always negative and unique within one mutate request. # @@ -663,7 +661,7 @@ def print_response_details( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/shopping_ads/add_performance_max_retail_campaign.py b/examples/shopping_ads/add_performance_max_retail_campaign.py index b59c98835..ceaeabb7e 100644 --- a/examples/shopping_ads/add_performance_max_retail_campaign.py +++ b/examples/shopping_ads/add_performance_max_retail_campaign.py @@ -46,64 +46,64 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException from google.ads.googleads.util import convert_snake_case_to_upper_case -from google.ads.googleads.v23.enums.types.conversion_action_category import ( +from google.ads.googleads.v24.enums.types.conversion_action_category import ( ConversionActionCategoryEnum, ) -from google.ads.googleads.v23.enums.types.conversion_origin import ( +from google.ads.googleads.v24.enums.types.conversion_origin import ( ConversionOriginEnum, ) -from google.ads.googleads.v23.enums.types.asset_field_type import ( +from google.ads.googleads.v24.enums.types.asset_field_type import ( AssetFieldTypeEnum, ) -from google.ads.googleads.v23.resources.types.asset import Asset -from google.ads.googleads.v23.resources.types.asset_group import AssetGroup -from google.ads.googleads.v23.resources.types.asset_group_asset import ( +from google.ads.googleads.v24.resources.types.asset import Asset +from google.ads.googleads.v24.resources.types.asset_group import AssetGroup +from google.ads.googleads.v24.resources.types.asset_group_asset import ( AssetGroupAsset, ) -from google.ads.googleads.v23.resources.types.asset_group_listing_group_filter import ( +from google.ads.googleads.v24.resources.types.asset_group_listing_group_filter import ( AssetGroupListingGroupFilter, ) -from google.ads.googleads.v23.resources.types.campaign import Campaign -from google.ads.googleads.v23.resources.types.campaign_asset import ( +from google.ads.googleads.v24.resources.types.campaign import Campaign +from google.ads.googleads.v24.resources.types.campaign_asset import ( CampaignAsset, ) -from google.ads.googleads.v23.resources.types.campaign_budget import ( +from google.ads.googleads.v24.resources.types.campaign_budget import ( CampaignBudget, ) -from google.ads.googleads.v23.resources.types.campaign_conversion_goal import ( +from google.ads.googleads.v24.resources.types.campaign_conversion_goal import ( CampaignConversionGoal, ) -from google.ads.googleads.v23.resources.types.campaign_criterion import ( +from google.ads.googleads.v24.resources.types.campaign_criterion import ( CampaignCriterion, ) -from google.ads.googleads.v23.services.services.asset_group_service import ( +from google.ads.googleads.v24.services.services.asset_group_service import ( AssetGroupServiceClient, ) -from google.ads.googleads.v23.services.services.asset_service import ( +from google.ads.googleads.v24.services.services.asset_service import ( AssetServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_budget_service import ( +from google.ads.googleads.v24.services.services.campaign_budget_service import ( CampaignBudgetServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_conversion_goal_service import ( +from google.ads.googleads.v24.services.services.campaign_conversion_goal_service import ( CampaignConversionGoalServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.services.geo_target_constant_service import ( +from google.ads.googleads.v24.services.services.geo_target_constant_service import ( GeoTargetConstantServiceClient, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( MutateGoogleAdsResponse, MutateOperationResponse, SearchGoogleAdsRequest, SearchGoogleAdsResponse, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( MutateOperation, ) @@ -1260,7 +1260,7 @@ def print_response_details(response: MutateGoogleAdsResponse) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/shopping_ads/add_shopping_product_ad.py b/examples/shopping_ads/add_shopping_product_ad.py index a9d78dcf8..18b80b40f 100755 --- a/examples/shopping_ads/add_shopping_product_ad.py +++ b/examples/shopping_ads/add_shopping_product_ad.py @@ -24,50 +24,49 @@ This account must be linked to your Google Ads account. """ - import argparse import sys import uuid from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.ad_group import AdGroup -from google.ads.googleads.v23.resources.types.ad_group_ad import AdGroupAd -from google.ads.googleads.v23.resources.types.ad_group_criterion import ( +from google.ads.googleads.v24.resources.types.ad_group import AdGroup +from google.ads.googleads.v24.resources.types.ad_group_ad import AdGroupAd +from google.ads.googleads.v24.resources.types.ad_group_criterion import ( AdGroupCriterion, ) -from google.ads.googleads.v23.resources.types.campaign import Campaign -from google.ads.googleads.v23.resources.types.campaign_budget import ( +from google.ads.googleads.v24.resources.types.campaign import Campaign +from google.ads.googleads.v24.resources.types.campaign_budget import ( CampaignBudget, ) -from google.ads.googleads.v23.services.services.ad_group_ad_service import ( +from google.ads.googleads.v24.services.services.ad_group_ad_service import ( AdGroupAdServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_budget_service import ( +from google.ads.googleads.v24.services.services.campaign_budget_service import ( CampaignBudgetServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_ad_service import ( +from google.ads.googleads.v24.services.types.ad_group_ad_service import ( AdGroupAdOperation, ) -from google.ads.googleads.v23.services.types.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation, ) -from google.ads.googleads.v23.services.types.ad_group_service import ( +from google.ads.googleads.v24.services.types.ad_group_service import ( AdGroupOperation, ) -from google.ads.googleads.v23.services.types.campaign_budget_service import ( +from google.ads.googleads.v24.services.types.campaign_budget_service import ( CampaignBudgetOperation, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, ) @@ -361,7 +360,7 @@ def add_default_shopping_listing_group( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/shopping_ads/add_shopping_product_listing_group_tree.py b/examples/shopping_ads/add_shopping_product_listing_group_tree.py index e8191f049..0f36de255 100644 --- a/examples/shopping_ads/add_shopping_product_listing_group_tree.py +++ b/examples/shopping_ads/add_shopping_product_listing_group_tree.py @@ -31,29 +31,29 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.criteria import ( +from google.ads.googleads.v24.common.types.criteria import ( ListingDimensionInfo, ListingGroupInfo, ) -from google.ads.googleads.v23.enums.types.product_condition import ( +from google.ads.googleads.v24.enums.types.product_condition import ( ProductConditionEnum, ) -from google.ads.googleads.v23.resources.types.ad_group_criterion import ( +from google.ads.googleads.v24.resources.types.ad_group_criterion import ( AdGroupCriterion, ) -from google.ads.googleads.v23.services.services.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( MutateGoogleAdsResponse, SearchGoogleAdsResponse, ) @@ -485,7 +485,7 @@ def create_listing_group_unit_biddable( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/shopping_ads/get_product_category_constants.py b/examples/shopping_ads/get_product_category_constants.py index bee906b12..aa73dd559 100755 --- a/examples/shopping_ads/get_product_category_constants.py +++ b/examples/shopping_ads/get_product_category_constants.py @@ -14,7 +14,6 @@ # limitations under the License. """This example fetches the set of all ProductCategoryConstants.""" - import argparse import collections import sys @@ -22,13 +21,13 @@ from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.product_category_constant import ( +from google.ads.googleads.v24.resources.types.product_category_constant import ( ProductCategoryConstant, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( SearchGoogleAdsStreamRequest, SearchGoogleAdsStreamResponse, ) @@ -154,7 +153,7 @@ def main(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/targeting/add_campaign_targeting_criteria.py b/examples/targeting/add_campaign_targeting_criteria.py index 31020cc25..cde6bd672 100755 --- a/examples/targeting/add_campaign_targeting_criteria.py +++ b/examples/targeting/add_campaign_targeting_criteria.py @@ -14,29 +14,28 @@ # limitations under the License. """This example adds campaign targeting criteria.""" - import argparse from typing import List import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.criteria import ( +from google.ads.googleads.v24.common.types.criteria import ( KeywordInfo, ) -from google.ads.googleads.v23.resources.types.campaign_criterion import ( +from google.ads.googleads.v24.resources.types.campaign_criterion import ( CampaignCriterion, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_criterion_service import ( +from google.ads.googleads.v24.services.services.campaign_criterion_service import ( CampaignCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.geo_target_constant_service import ( +from google.ads.googleads.v24.services.services.geo_target_constant_service import ( GeoTargetConstantServiceClient, ) -from google.ads.googleads.v23.services.types.campaign_criterion_service import ( +from google.ads.googleads.v24.services.types.campaign_criterion_service import ( CampaignCriterionOperation, MutateCampaignCriteriaResponse, ) @@ -205,7 +204,7 @@ def create_proximity_op( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/targeting/add_customer_negative_criteria.py b/examples/targeting/add_customer_negative_criteria.py index 1fe9ce17d..d91e73c66 100755 --- a/examples/targeting/add_customer_negative_criteria.py +++ b/examples/targeting/add_customer_negative_criteria.py @@ -17,19 +17,18 @@ These criteria will be applied to all campaigns for the given customer. """ - import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.customer_negative_criterion import ( +from google.ads.googleads.v24.resources.types.customer_negative_criterion import ( CustomerNegativeCriterion, ) -from google.ads.googleads.v23.services.services.customer_negative_criterion_service import ( +from google.ads.googleads.v24.services.services.customer_negative_criterion_service import ( CustomerNegativeCriterionServiceClient, ) -from google.ads.googleads.v23.services.types.customer_negative_criterion_service import ( +from google.ads.googleads.v24.services.types.customer_negative_criterion_service import ( CustomerNegativeCriterionOperation, MutateCustomerNegativeCriteriaResponse, ) @@ -100,7 +99,7 @@ def main(client: GoogleAdsClient, customer_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/targeting/add_demographic_targeting_criteria.py b/examples/targeting/add_demographic_targeting_criteria.py index 5faacd6a8..760696152 100755 --- a/examples/targeting/add_demographic_targeting_criteria.py +++ b/examples/targeting/add_demographic_targeting_criteria.py @@ -16,22 +16,21 @@ positive ad group criterion and one as negative ad group criterion. To create ad groups, run add_ad_groups.py.""" - import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.ad_group_criterion import ( +from google.ads.googleads.v24.resources.types.ad_group_criterion import ( AdGroupCriterion, ) -from google.ads.googleads.v23.services.services.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation, MutateAdGroupCriteriaResponse, ) @@ -109,7 +108,7 @@ def main(client: GoogleAdsClient, customer_id: str, ad_group_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/targeting/get_geo_target_constants_by_names.py b/examples/targeting/get_geo_target_constants_by_names.py index 3eac3d753..f8f16c6b3 100755 --- a/examples/targeting/get_geo_target_constants_by_names.py +++ b/examples/targeting/get_geo_target_constants_by_names.py @@ -14,18 +14,17 @@ # limitations under the License. """This example illustrates getting GeoTargetConstants by given location names.""" - import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.geo_target_constant import ( +from google.ads.googleads.v24.resources.types.geo_target_constant import ( GeoTargetConstant, ) -from google.ads.googleads.v23.services.services.geo_target_constant_service import ( +from google.ads.googleads.v24.services.services.geo_target_constant_service import ( GeoTargetConstantServiceClient, ) -from google.ads.googleads.v23.services.types.geo_target_constant_service import ( +from google.ads.googleads.v24.services.types.geo_target_constant_service import ( GeoTargetConstantSuggestion, SuggestGeoTargetConstantsRequest, SuggestGeoTargetConstantsResponse, @@ -83,7 +82,7 @@ def main(client: GoogleAdsClient) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/travel/add_hotel_ad.py b/examples/travel/add_hotel_ad.py index 1550e0665..f5397a1be 100755 --- a/examples/travel/add_hotel_ad.py +++ b/examples/travel/add_hotel_ad.py @@ -20,44 +20,43 @@ https://support.google.com/hotelprices/answer/6101897. """ - import argparse import sys import uuid from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.ad_group import AdGroup -from google.ads.googleads.v23.resources.types.ad_group_ad import AdGroupAd -from google.ads.googleads.v23.resources.types.campaign import Campaign -from google.ads.googleads.v23.resources.types.campaign_budget import ( +from google.ads.googleads.v24.resources.types.ad_group import AdGroup +from google.ads.googleads.v24.resources.types.ad_group_ad import AdGroupAd +from google.ads.googleads.v24.resources.types.campaign import Campaign +from google.ads.googleads.v24.resources.types.campaign_budget import ( CampaignBudget, ) -from google.ads.googleads.v23.services.services.ad_group_ad_service import ( +from google.ads.googleads.v24.services.services.ad_group_ad_service import ( AdGroupAdServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_budget_service import ( +from google.ads.googleads.v24.services.services.campaign_budget_service import ( CampaignBudgetServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_ad_service import ( +from google.ads.googleads.v24.services.types.ad_group_ad_service import ( AdGroupAdOperation, MutateAdGroupAdsResponse, ) -from google.ads.googleads.v23.services.types.ad_group_service import ( +from google.ads.googleads.v24.services.types.ad_group_service import ( AdGroupOperation, MutateAdGroupsResponse, ) -from google.ads.googleads.v23.services.types.campaign_budget_service import ( +from google.ads.googleads.v24.services.types.campaign_budget_service import ( CampaignBudgetOperation, MutateCampaignBudgetsResponse, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, MutateCampaignsResponse, ) @@ -291,7 +290,7 @@ def add_hotel_campaign( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/travel/add_hotel_ad_group_bid_modifiers.py b/examples/travel/add_hotel_ad_group_bid_modifiers.py index 131de4474..28008b194 100755 --- a/examples/travel/add_hotel_ad_group_bid_modifiers.py +++ b/examples/travel/add_hotel_ad_group_bid_modifiers.py @@ -17,23 +17,22 @@ The bid modifiers will be based on hotel check-in day and length of stay. """ - import argparse import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.criteria import HotelLengthOfStayInfo -from google.ads.googleads.v23.resources.types.ad_group_bid_modifier import ( +from google.ads.googleads.v24.common.types.criteria import HotelLengthOfStayInfo +from google.ads.googleads.v24.resources.types.ad_group_bid_modifier import ( AdGroupBidModifier, ) -from google.ads.googleads.v23.services.services.ad_group_bid_modifier_service import ( +from google.ads.googleads.v24.services.services.ad_group_bid_modifier_service import ( AdGroupBidModifierServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_bid_modifier_service import ( +from google.ads.googleads.v24.services.types.ad_group_bid_modifier_service import ( AdGroupBidModifierOperation, MutateAdGroupBidModifierResult, MutateAdGroupBidModifiersResponse, @@ -123,7 +122,7 @@ def main(client: GoogleAdsClient, customer_id: str, ad_group_id: str) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/travel/add_hotel_listing_group_tree.py b/examples/travel/add_hotel_listing_group_tree.py index 4e6ca9561..71a594179 100755 --- a/examples/travel/add_hotel_listing_group_tree.py +++ b/examples/travel/add_hotel_listing_group_tree.py @@ -28,27 +28,26 @@ listing group tree to an ad group that already has one will fail. """ - import argparse import sys from typing import List, Optional from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.common.types.criteria import ( +from google.ads.googleads.v24.common.types.criteria import ( ListingDimensionInfo, ListingGroupInfo, ) -from google.ads.googleads.v23.enums.types.listing_group_type import ( +from google.ads.googleads.v24.enums.types.listing_group_type import ( ListingGroupTypeEnum, ) -from google.ads.googleads.v23.resources.types.ad_group_criterion import ( +from google.ads.googleads.v24.resources.types.ad_group_criterion import ( AdGroupCriterion, ) -from google.ads.googleads.v23.services.services.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.services.ad_group_criterion_service import ( AdGroupCriterionServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_criterion_service import ( +from google.ads.googleads.v24.services.types.ad_group_criterion_service import ( AdGroupCriterionOperation, MutateAdGroupCriteriaResponse, MutateAdGroupCriterionResult, @@ -532,7 +531,7 @@ def create_ad_group_criterion( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/travel/add_performance_max_for_travel_goals_campaign.py b/examples/travel/add_performance_max_for_travel_goals_campaign.py index ac5b1a4dd..0bd8301bf 100644 --- a/examples/travel/add_performance_max_for_travel_goals_campaign.py +++ b/examples/travel/add_performance_max_for_travel_goals_campaign.py @@ -35,7 +35,6 @@ advanced_operations/add_performance_max_campaign.py. """ - import argparse import sys from typing import Dict, List @@ -47,51 +46,50 @@ ) from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.enums.types.asset_field_type import ( +from google.ads.googleads.v24.enums.types.asset_field_type import ( AssetFieldTypeEnum, ) -from google.ads.googleads.v23.enums.types.hotel_asset_suggestion_status import ( +from google.ads.googleads.v24.enums.types.hotel_asset_suggestion_status import ( HotelAssetSuggestionStatusEnum, ) -from google.ads.googleads.v23.resources.types import CampaignBudget -from google.ads.googleads.v23.resources.types.campaign import Campaign -from google.ads.googleads.v23.resources.types.asset import Asset -from google.ads.googleads.v23.resources.types.asset_group import AssetGroup -from google.ads.googleads.v23.resources.types.asset_group_asset import ( +from google.ads.googleads.v24.resources.types import CampaignBudget +from google.ads.googleads.v24.resources.types.campaign import Campaign +from google.ads.googleads.v24.resources.types.asset import Asset +from google.ads.googleads.v24.resources.types.asset_group import AssetGroup +from google.ads.googleads.v24.resources.types.asset_group_asset import ( AssetGroupAsset, ) -from google.ads.googleads.v23.services.services.google_ads_service import ( +from google.ads.googleads.v24.services.services.google_ads_service import ( GoogleAdsServiceClient, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( MutateGoogleAdsResponse, MutateOperation, ) -from google.ads.googleads.v23.services.types.google_ads_service import ( +from google.ads.googleads.v24.services.types.google_ads_service import ( MutateOperationResponse, ) -from google.ads.googleads.v23.resources.types.asset_set import AssetSet -from google.ads.googleads.v23.resources.types.asset_set_asset import ( +from google.ads.googleads.v24.resources.types.asset_set import AssetSet +from google.ads.googleads.v24.resources.types.asset_set_asset import ( AssetSetAsset, ) -from google.ads.googleads.v23.services.services.asset_set_service import ( +from google.ads.googleads.v24.services.services.asset_set_service import ( AssetSetServiceClient, ) -from google.ads.googleads.v23.services.types.asset_set_service import ( +from google.ads.googleads.v24.services.types.asset_set_service import ( AssetSetOperation, MutateAssetSetsResponse, ) -from google.ads.googleads.v23.services.services.travel_asset_suggestion_service import ( +from google.ads.googleads.v24.services.services.travel_asset_suggestion_service import ( TravelAssetSuggestionServiceClient, ) -from google.ads.googleads.v23.services.types.travel_asset_suggestion_service import ( +from google.ads.googleads.v24.services.types.travel_asset_suggestion_service import ( HotelAssetSuggestion, SuggestTravelAssetsRequest, SuggestTravelAssetsResponse, ) - MIN_REQUIRED_TEXT_ASSET_COUNTS: Dict[str, int] = { "HEADLINE": 3, "LONG_HEADLINE": 1, @@ -1110,7 +1108,7 @@ def print_response_details(mutate_response: MutateGoogleAdsResponse) -> None: # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/examples/travel/add_things_to_do_ad.py b/examples/travel/add_things_to_do_ad.py index 4f61816bc..4ce89ddf5 100755 --- a/examples/travel/add_things_to_do_ad.py +++ b/examples/travel/add_things_to_do_ad.py @@ -19,44 +19,43 @@ https://support.google.com/google-ads/answer/13387362 """ - import argparse import sys from examples.utils.example_helpers import get_printable_datetime from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException -from google.ads.googleads.v23.resources.types.ad_group import AdGroup -from google.ads.googleads.v23.resources.types.ad_group_ad import AdGroupAd -from google.ads.googleads.v23.resources.types.campaign import Campaign -from google.ads.googleads.v23.resources.types.campaign_budget import ( +from google.ads.googleads.v24.resources.types.ad_group import AdGroup +from google.ads.googleads.v24.resources.types.ad_group_ad import AdGroupAd +from google.ads.googleads.v24.resources.types.campaign import Campaign +from google.ads.googleads.v24.resources.types.campaign_budget import ( CampaignBudget, ) -from google.ads.googleads.v23.services.services.ad_group_ad_service import ( +from google.ads.googleads.v24.services.services.ad_group_ad_service import ( AdGroupAdServiceClient, ) -from google.ads.googleads.v23.services.services.ad_group_service import ( +from google.ads.googleads.v24.services.services.ad_group_service import ( AdGroupServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_budget_service import ( +from google.ads.googleads.v24.services.services.campaign_budget_service import ( CampaignBudgetServiceClient, ) -from google.ads.googleads.v23.services.services.campaign_service import ( +from google.ads.googleads.v24.services.services.campaign_service import ( CampaignServiceClient, ) -from google.ads.googleads.v23.services.types.ad_group_ad_service import ( +from google.ads.googleads.v24.services.types.ad_group_ad_service import ( AdGroupAdOperation, MutateAdGroupAdsResponse, ) -from google.ads.googleads.v23.services.types.ad_group_service import ( +from google.ads.googleads.v24.services.types.ad_group_service import ( AdGroupOperation, MutateAdGroupsResponse, ) -from google.ads.googleads.v23.services.types.campaign_budget_service import ( +from google.ads.googleads.v24.services.types.campaign_budget_service import ( CampaignBudgetOperation, MutateCampaignBudgetsResponse, ) -from google.ads.googleads.v23.services.types.campaign_service import ( +from google.ads.googleads.v24.services.types.campaign_service import ( CampaignOperation, MutateCampaignsResponse, ) @@ -319,7 +318,7 @@ def add_ad_group_ad( # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage( - version="v23" + version="v24" ) try: diff --git a/google/ads/googleads/__init__.py b/google/ads/googleads/__init__.py index 0fea461fb..bdf48da1a 100644 --- a/google/ads/googleads/__init__.py +++ b/google/ads/googleads/__init__.py @@ -19,7 +19,7 @@ import google.ads.googleads.errors import google.ads.googleads.util -VERSION = "30.0.0" +VERSION = "30.1.0" # Checks if the current runtime is Python 3.9. if sys.version_info.major == 3 and sys.version_info.minor <= 9: diff --git a/google/ads/googleads/client.py b/google/ads/googleads/client.py index e1d26fa9b..8ea8998be 100644 --- a/google/ads/googleads/client.py +++ b/google/ads/googleads/client.py @@ -45,7 +45,7 @@ _SERVICE_CLIENT_TEMPLATE = "{}Client" _ASYNC_SERVICE_CLIENT_TEMPLATE = "{}AsyncClient" -_VALID_API_VERSIONS = ["v23", "v22", "v21", "v20"] +_VALID_API_VERSIONS = ["v24", "v23", "v22", "v21", "v20"] _MESSAGE_TYPES = ["common", "enums", "errors", "resources", "services"] _DEFAULT_VERSION = _VALID_API_VERSIONS[0] diff --git a/google/ads/googleads/v24/__init__.py b/google/ads/googleads/v24/__init__.py new file mode 100644 index 000000000..46a7ee77a --- /dev/null +++ b/google/ads/googleads/v24/__init__.py @@ -0,0 +1,141 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 google.ads.googleads.v24 import gapic_version as package_version + +import google.api_core as api_core +import sys + +__version__ = package_version.__version__ + +if sys.version_info >= (3, 8): # pragma: NO COVER + from importlib import metadata +else: # pragma: NO COVER + # TODO(https://github.com/googleapis/python-api-core/issues/835): Remove + # this code path once we drop support for Python 3.7 + import importlib_metadata as metadata + +from . import actions +from . import common +from . import enums +from . import errors +from . import resources +from . import services + + +if hasattr(api_core, "check_python_version") and hasattr( + api_core, "check_dependency_versions" +): # pragma: NO COVER + api_core.check_python_version("google.ads.googleads.v24") # type: ignore + api_core.check_dependency_versions("google.ads.googleads.v24") # type: ignore +else: # pragma: NO COVER + # An older version of api_core is installed which does not define the + # functions above. We do equivalent checks manually. + try: + import warnings + import sys + + _py_version_str = sys.version.split()[0] + _package_label = "google.ads.googleads.v24" + if sys.version_info < (3, 9): + warnings.warn( + "You are using a non-supported Python version " + + f"({_py_version_str}). Google will not post any further " + + f"updates to {_package_label} supporting this Python version. " + + "Please upgrade to the latest Python version, or at " + + f"least to Python 3.9, and then update {_package_label}.", + FutureWarning, + ) + if sys.version_info[:2] == (3, 9): + warnings.warn( + f"You are using a Python version ({_py_version_str}) " + + f"which Google will stop supporting in {_package_label} in " + + "January 2026. Please " + + "upgrade to the latest Python version, or at " + + "least to Python 3.10, before then, and " + + f"then update {_package_label}.", + FutureWarning, + ) + + def parse_version_to_tuple(version_string: str): + """Safely converts a semantic version string to a comparable tuple of integers. + Example: "4.25.8" -> (4, 25, 8) + Ignores non-numeric parts and handles common version formats. + Args: + version_string: Version string in the format "x.y.z" or "x.y.z" + Returns: + Tuple of integers for the parsed version string. + """ + parts = [] + for part in version_string.split("."): + try: + parts.append(int(part)) + except ValueError: + # If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here. + # This is a simplification compared to 'packaging.parse_version', but sufficient + # for comparing strictly numeric semantic versions. + break + return tuple(parts) + + def _get_version(dependency_name): + try: + version_string: str = metadata.version(dependency_name) + parsed_version = parse_version_to_tuple(version_string) + return (parsed_version, version_string) + except Exception: + # Catch exceptions from metadata.version() (e.g., PackageNotFoundError) + # or errors during parse_version_to_tuple + return (None, "--") + + _dependency_package = "google.protobuf" + _next_supported_version = "4.25.8" + _next_supported_version_tuple = (4, 25, 8) + _recommendation = " (we recommend 6.x)" + (_version_used, _version_used_string) = _get_version( + _dependency_package + ) + if _version_used and _version_used < _next_supported_version_tuple: + warnings.warn( + f"Package {_package_label} depends on " + + f"{_dependency_package}, currently installed at version " + + f"{_version_used_string}. Future updates to " + + f"{_package_label} will require {_dependency_package} at " + + f"version {_next_supported_version} or higher{_recommendation}." + + " Please ensure " + + "that either (a) your Python environment doesn't pin the " + + f"version of {_dependency_package}, so that updates to " + + f"{_package_label} can require the higher version, or " + + "(b) you manually update your Python environment to use at " + + f"least version {_next_supported_version} of " + + f"{_dependency_package}.", + FutureWarning, + ) + except Exception: + warnings.warn( + "Could not determine the version of Python " + + "currently being used. To continue receiving " + + "updates for {_package_label}, ensure you are " + + "using a supported version of Python; see " + + "https://devguide.python.org/versions/" + ) + +__all__ = ( + "actions", + "common", + "enums", + "errors", + "resources", + "services", +) diff --git a/google/ads/googleads/v24/actions/__init__.py b/google/ads/googleads/v24/actions/__init__.py new file mode 100644 index 000000000..45b8fd338 --- /dev/null +++ b/google/ads/googleads/v24/actions/__init__.py @@ -0,0 +1,151 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 google.ads.googleads.v24 import gapic_version as package_version + +import google.api_core as api_core +import sys + +__version__ = package_version.__version__ + +if sys.version_info >= (3, 8): # pragma: NO COVER + from importlib import metadata +else: # pragma: NO COVER + # TODO(https://github.com/googleapis/python-api-core/issues/835): Remove + # this code path once we drop support for Python 3.7 + import importlib_metadata as metadata + + +from .types.book_campaigns import BookCampaignsOperation +from .types.book_campaigns import BookCampaignsResult +from .types.generate_shareable_previews import ( + GenerateShareablePreviewsOperation, +) +from .types.generate_shareable_previews import GenerateShareablePreviewsResult +from .types.generate_shareable_previews import ShareablePreview +from .types.generate_shareable_previews import ShareablePreviewResult +from .types.generate_shareable_previews import UiPreviewResult +from .types.generate_shareable_previews import YouTubeLivePreviewResult +from .types.quote_campaigns import QuoteCampaignsOperation +from .types.quote_campaigns import QuoteCampaignsResult + +if hasattr(api_core, "check_python_version") and hasattr( + api_core, "check_dependency_versions" +): # pragma: NO COVER + api_core.check_python_version("google.ads.googleads.v24") # type: ignore + api_core.check_dependency_versions("google.ads.googleads.v24") # type: ignore +else: # pragma: NO COVER + # An older version of api_core is installed which does not define the + # functions above. We do equivalent checks manually. + try: + import warnings + import sys + + _py_version_str = sys.version.split()[0] + _package_label = "google.ads.googleads.v24" + if sys.version_info < (3, 9): + warnings.warn( + "You are using a non-supported Python version " + + f"({_py_version_str}). Google will not post any further " + + f"updates to {_package_label} supporting this Python version. " + + "Please upgrade to the latest Python version, or at " + + f"least to Python 3.9, and then update {_package_label}.", + FutureWarning, + ) + if sys.version_info[:2] == (3, 9): + warnings.warn( + f"You are using a Python version ({_py_version_str}) " + + f"which Google will stop supporting in {_package_label} in " + + "January 2026. Please " + + "upgrade to the latest Python version, or at " + + "least to Python 3.10, before then, and " + + f"then update {_package_label}.", + FutureWarning, + ) + + def parse_version_to_tuple(version_string: str): + """Safely converts a semantic version string to a comparable tuple of integers. + Example: "4.25.8" -> (4, 25, 8) + Ignores non-numeric parts and handles common version formats. + Args: + version_string: Version string in the format "x.y.z" or "x.y.z" + Returns: + Tuple of integers for the parsed version string. + """ + parts = [] + for part in version_string.split("."): + try: + parts.append(int(part)) + except ValueError: + # If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here. + # This is a simplification compared to 'packaging.parse_version', but sufficient + # for comparing strictly numeric semantic versions. + break + return tuple(parts) + + def _get_version(dependency_name): + try: + version_string: str = metadata.version(dependency_name) + parsed_version = parse_version_to_tuple(version_string) + return (parsed_version, version_string) + except Exception: + # Catch exceptions from metadata.version() (e.g., PackageNotFoundError) + # or errors during parse_version_to_tuple + return (None, "--") + + _dependency_package = "google.protobuf" + _next_supported_version = "4.25.8" + _next_supported_version_tuple = (4, 25, 8) + _recommendation = " (we recommend 6.x)" + (_version_used, _version_used_string) = _get_version( + _dependency_package + ) + if _version_used and _version_used < _next_supported_version_tuple: + warnings.warn( + f"Package {_package_label} depends on " + + f"{_dependency_package}, currently installed at version " + + f"{_version_used_string}. Future updates to " + + f"{_package_label} will require {_dependency_package} at " + + f"version {_next_supported_version} or higher{_recommendation}." + + " Please ensure " + + "that either (a) your Python environment doesn't pin the " + + f"version of {_dependency_package}, so that updates to " + + f"{_package_label} can require the higher version, or " + + "(b) you manually update your Python environment to use at " + + f"least version {_next_supported_version} of " + + f"{_dependency_package}.", + FutureWarning, + ) + except Exception: + warnings.warn( + "Could not determine the version of Python " + + "currently being used. To continue receiving " + + "updates for {_package_label}, ensure you are " + + "using a supported version of Python; see " + + "https://devguide.python.org/versions/" + ) + +__all__ = ( + "BookCampaignsOperation", + "BookCampaignsResult", + "GenerateShareablePreviewsOperation", + "GenerateShareablePreviewsResult", + "QuoteCampaignsOperation", + "QuoteCampaignsResult", + "ShareablePreview", + "ShareablePreviewResult", + "UiPreviewResult", + "YouTubeLivePreviewResult", +) diff --git a/google/ads/googleads/v24/actions/services/__init__.py b/google/ads/googleads/v24/actions/services/__init__.py new file mode 100644 index 000000000..cbf94b283 --- /dev/null +++ b/google/ads/googleads/v24/actions/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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. +# diff --git a/google/ads/googleads/v24/actions/types/__init__.py b/google/ads/googleads/v24/actions/types/__init__.py new file mode 100644 index 000000000..dd4779591 --- /dev/null +++ b/google/ads/googleads/v24/actions/types/__init__.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .book_campaigns import ( + BookCampaignsOperation, + BookCampaignsResult, +) +from .generate_shareable_previews import ( + GenerateShareablePreviewsOperation, + GenerateShareablePreviewsResult, + ShareablePreview, + ShareablePreviewResult, + UiPreviewResult, + YouTubeLivePreviewResult, +) +from .quote_campaigns import ( + QuoteCampaignsOperation, + QuoteCampaignsResult, +) + +__all__ = ( + "BookCampaignsOperation", + "BookCampaignsResult", + "GenerateShareablePreviewsOperation", + "GenerateShareablePreviewsResult", + "ShareablePreview", + "ShareablePreviewResult", + "UiPreviewResult", + "YouTubeLivePreviewResult", + "QuoteCampaignsOperation", + "QuoteCampaignsResult", +) diff --git a/google/ads/googleads/v24/actions/types/book_campaigns.py b/google/ads/googleads/v24/actions/types/book_campaigns.py new file mode 100644 index 000000000..c6b271f65 --- /dev/null +++ b/google/ads/googleads/v24/actions/types/book_campaigns.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import reservation_request_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.actions", + marshal="google.ads.googleads.v24", + manifest={ + "BookCampaignsOperation", + "BookCampaignsResult", + }, +) + + +class BookCampaignsOperation(proto.Message): + r"""Request message for the BookCampaigns action. + Request including this operation can have a latency of up to 30 + seconds. This feature is not publicly available. + + Attributes: + campaigns (MutableSequence[google.ads.googleads.v24.actions.types.BookCampaignsOperation.Campaign]): + Campaigns to book. Maximum 2 campaigns per + request. + quote_signature (str): + If provided, the signature of the previous + quote. Clients should always provide the quote + signature from previous quotes if they haven't + changed the campaigns to prevent price + fluctuations within a user session. + """ + + class Campaign(proto.Message): + r"""A single campaign to book. + + Attributes: + campaign (str): + Campaign resource to book. Format: + customers/{customer_id}/campaigns/{campaign_id} + request_type (google.ads.googleads.v24.enums.types.ReservationRequestTypeEnum.ReservationRequestType): + Determines if the current request should book + the inventory or hold it. + """ + + campaign: str = proto.Field( + proto.STRING, + number=1, + ) + request_type: ( + reservation_request_type.ReservationRequestTypeEnum.ReservationRequestType + ) = proto.Field( + proto.ENUM, + number=2, + enum=reservation_request_type.ReservationRequestTypeEnum.ReservationRequestType, + ) + + campaigns: MutableSequence[Campaign] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=Campaign, + ) + quote_signature: str = proto.Field( + proto.STRING, + number=2, + ) + + +class BookCampaignsResult(proto.Message): + r"""Response message for the BookCampaigns action. Note that if the + response contains errors, the action response will not be returned, + but a quote may still be returned in the + ErrorDetails.reservation_error_details field. + + """ + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/actions/types/generate_shareable_previews.py b/google/ads/googleads/v24/actions/types/generate_shareable_previews.py new file mode 100644 index 000000000..d916b9b52 --- /dev/null +++ b/google/ads/googleads/v24/actions/types/generate_shareable_previews.py @@ -0,0 +1,215 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + preview_type as gage_preview_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.actions", + marshal="google.ads.googleads.v24", + manifest={ + "GenerateShareablePreviewsOperation", + "ShareablePreview", + "GenerateShareablePreviewsResult", + "ShareablePreviewResult", + "UiPreviewResult", + "YouTubeLivePreviewResult", + }, +) + + +class GenerateShareablePreviewsOperation(proto.Message): + r"""Operation to generate shareable previews. + + Attributes: + shareable_previews (MutableSequence[google.ads.googleads.v24.actions.types.ShareablePreview]): + Required. The list of shareable previews to + generate. + """ + + shareable_previews: MutableSequence["ShareablePreview"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ShareablePreview", + ) + ) + + +class ShareablePreview(proto.Message): + r"""A shareable preview with its identifier. + + 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: + preview_type (google.ads.googleads.v24.enums.types.PreviewTypeEnum.PreviewType): + Required. The type of preview to generate. + ad_group_ad (str): + Ad group ad of the shareable preview. Only supported for + preview type YOUTUBE_LIVE_PREVIEW. Format: + customers/{customer_id}/adGroupAds/{ad_group_id}~{ad_id} + + This field is a member of `oneof`_ ``identifier``. + asset_group (str): + Asset group of the shareable preview. Format: + customers/{customer_id}/assetGroups/{asset_group_id} + + This field is a member of `oneof`_ ``identifier``. + """ + + preview_type: gage_preview_type.PreviewTypeEnum.PreviewType = proto.Field( + proto.ENUM, + number=1, + enum=gage_preview_type.PreviewTypeEnum.PreviewType, + ) + ad_group_ad: str = proto.Field( + proto.STRING, + number=2, + oneof="identifier", + ) + asset_group: str = proto.Field( + proto.STRING, + number=3, + oneof="identifier", + ) + + +class GenerateShareablePreviewsResult(proto.Message): + r"""Result of the GenerateShareablePreviews action. + + Attributes: + previews (MutableSequence[google.ads.googleads.v24.actions.types.ShareablePreviewResult]): + List of previews. + """ + + previews: MutableSequence["ShareablePreviewResult"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ShareablePreviewResult", + ) + + +class ShareablePreviewResult(proto.Message): + r"""Message to hold a shareable preview result. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + expiration_date_time (str): + Expiration date time using the ISO-8601 + format. + ui_preview_result (google.ads.googleads.v24.actions.types.UiPreviewResult): + The result of a UI preview. Only populated for preview type + UI_PREVIEW. + + This field is a member of `oneof`_ ``result``. + youtube_live_preview_result (google.ads.googleads.v24.actions.types.YouTubeLivePreviewResult): + The result of a YouTube live preview. Only populated for + preview type YOUTUBE_LIVE_PREVIEW. + + This field is a member of `oneof`_ ``result``. + ad_group_ad (str): + Ad group ad of the shareable preview. Format: + customers/{customer_id}/adGroupAds/{ad_group_id}~{ad_id} + + This field is a member of `oneof`_ ``identifier``. + asset_group (str): + Asset group of the shareable preview. Format: + customers/{customer_id}/assetGroups/{asset_group_id} + + This field is a member of `oneof`_ ``identifier``. + """ + + expiration_date_time: str = proto.Field( + proto.STRING, + number=3, + ) + ui_preview_result: "UiPreviewResult" = proto.Field( + proto.MESSAGE, + number=1, + oneof="result", + message="UiPreviewResult", + ) + youtube_live_preview_result: "YouTubeLivePreviewResult" = proto.Field( + proto.MESSAGE, + number=2, + oneof="result", + message="YouTubeLivePreviewResult", + ) + ad_group_ad: str = proto.Field( + proto.STRING, + number=4, + oneof="identifier", + ) + asset_group: str = proto.Field( + proto.STRING, + number=5, + oneof="identifier", + ) + + +class UiPreviewResult(proto.Message): + r"""Message to hold a UI preview result. + + Attributes: + shareable_preview_url (str): + The shareable preview URL. + """ + + shareable_preview_url: str = proto.Field( + proto.STRING, + number=1, + ) + + +class YouTubeLivePreviewResult(proto.Message): + r"""Message to hold a YouTube live preview result. + + Attributes: + youtube_preview_url (str): + The shareable preview URL for YouTube videos. + youtube_tv_preview_url (str): + The shareable preview URL for YouTube TV. + """ + + youtube_preview_url: str = proto.Field( + proto.STRING, + number=1, + ) + youtube_tv_preview_url: str = proto.Field( + proto.STRING, + number=2, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/actions/types/quote_campaigns.py b/google/ads/googleads/v24/actions/types/quote_campaigns.py new file mode 100644 index 000000000..b4caa93b9 --- /dev/null +++ b/google/ads/googleads/v24/actions/types/quote_campaigns.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import campaign_reservation_quote + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.actions", + marshal="google.ads.googleads.v24", + manifest={ + "QuoteCampaignsOperation", + "QuoteCampaignsResult", + }, +) + + +class QuoteCampaignsOperation(proto.Message): + r"""Request message for the QuoteCampaigns action. + Request including this operation can have a latency of up to 30 + seconds. This feature is not publicly available. + + Attributes: + campaigns (MutableSequence[google.ads.googleads.v24.actions.types.QuoteCampaignsOperation.Campaign]): + Campaigns for which the quotes are requested. + Maximum 2 campaigns per request. + quote_signature (str): + If provided, the signature of the previous + quote. Clients should always provide the quote + signature from previous quotes if they haven't + changed the campaigns to prevent price + fluctuations within a user session. + """ + + class Campaign(proto.Message): + r"""A campaign for which the quote is requested. + + Attributes: + campaign (str): + Campaign for which the quote is requested. Format: + customers/{customer_id}/campaigns/{campaign_id} + """ + + campaign: str = proto.Field( + proto.STRING, + number=1, + ) + + campaigns: MutableSequence[Campaign] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=Campaign, + ) + quote_signature: str = proto.Field( + proto.STRING, + number=2, + ) + + +class QuoteCampaignsResult(proto.Message): + r"""The response of the QuoteCampaigns action, when the action is + successful. Note that if the response contains errors, the action + response will not be returned, but a quote may still be returned in + the ErrorDetails.reservation_error_details field. + + Attributes: + quotes (MutableSequence[google.ads.googleads.v24.common.types.CampaignReservationQuote]): + The quotes for the requested campaigns. + quote_signature (str): + The signature of the quote. This signature + should be used when booking the quote. + """ + + quotes: MutableSequence[ + campaign_reservation_quote.CampaignReservationQuote + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=campaign_reservation_quote.CampaignReservationQuote, + ) + quote_signature: str = proto.Field( + proto.STRING, + number=2, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/__init__.py b/google/ads/googleads/v24/common/__init__.py new file mode 100644 index 000000000..e35224c3c --- /dev/null +++ b/google/ads/googleads/v24/common/__init__.py @@ -0,0 +1,843 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 google.ads.googleads.v24 import gapic_version as package_version + +import google.api_core as api_core +import sys + +__version__ = package_version.__version__ + +if sys.version_info >= (3, 8): # pragma: NO COVER + from importlib import metadata +else: # pragma: NO COVER + # TODO(https://github.com/googleapis/python-api-core/issues/835): Remove + # this code path once we drop support for Python 3.7 + import importlib_metadata as metadata + + +from .types.ad_asset import AdAppDeepLinkAsset +from .types.ad_asset import AdCallToActionAsset +from .types.ad_asset import AdDemandGenCarouselCardAsset +from .types.ad_asset import AdImageAsset +from .types.ad_asset import AdMediaBundleAsset +from .types.ad_asset import AdTextAsset +from .types.ad_asset import AdVideoAsset +from .types.ad_asset import AdVideoAssetInfo +from .types.ad_asset import AdVideoAssetInventoryPreferences +from .types.ad_asset import AdVideoAssetLinkFeatureControl +from .types.ad_type_infos import AppAdInfo +from .types.ad_type_infos import AppEngagementAdInfo +from .types.ad_type_infos import AppPreRegistrationAdInfo +from .types.ad_type_infos import DemandGenCarouselAdInfo +from .types.ad_type_infos import DemandGenMultiAssetAdInfo +from .types.ad_type_infos import DemandGenProductAdInfo +from .types.ad_type_infos import DemandGenVideoResponsiveAdInfo +from .types.ad_type_infos import DisplayUploadAdInfo +from .types.ad_type_infos import ExpandedDynamicSearchAdInfo +from .types.ad_type_infos import ExpandedTextAdInfo +from .types.ad_type_infos import HotelAdInfo +from .types.ad_type_infos import ImageAdInfo +from .types.ad_type_infos import InFeedVideoAdInfo +from .types.ad_type_infos import LegacyAppInstallAdInfo +from .types.ad_type_infos import LegacyResponsiveDisplayAdInfo +from .types.ad_type_infos import LocalAdInfo +from .types.ad_type_infos import ResponsiveDisplayAdControlSpec +from .types.ad_type_infos import ResponsiveDisplayAdInfo +from .types.ad_type_infos import ResponsiveSearchAdInfo +from .types.ad_type_infos import ShoppingComparisonListingAdInfo +from .types.ad_type_infos import ShoppingProductAdInfo +from .types.ad_type_infos import ShoppingSmartAdInfo +from .types.ad_type_infos import SmartCampaignAdInfo +from .types.ad_type_infos import TextAdInfo +from .types.ad_type_infos import TravelAdInfo +from .types.ad_type_infos import VideoAdInfo +from .types.ad_type_infos import VideoBumperInStreamAdInfo +from .types.ad_type_infos import VideoNonSkippableInStreamAdInfo +from .types.ad_type_infos import VideoOutstreamAdInfo +from .types.ad_type_infos import VideoResponsiveAdInfo +from .types.ad_type_infos import VideoTrueViewInStreamAdInfo +from .types.ad_type_infos import YouTubeAudioAdInfo +from .types.additional_application_info import AdditionalApplicationInfo +from .types.asset_policy import AdAssetPolicySummary +from .types.asset_policy import AssetDisapproved +from .types.asset_policy import AssetLinkPrimaryStatusDetails +from .types.asset_set_types import BusinessProfileBusinessNameFilter +from .types.asset_set_types import BusinessProfileLocationGroup +from .types.asset_set_types import BusinessProfileLocationSet +from .types.asset_set_types import ChainFilter +from .types.asset_set_types import ChainLocationGroup +from .types.asset_set_types import ChainSet +from .types.asset_set_types import DynamicBusinessProfileLocationGroupFilter +from .types.asset_set_types import LocationSet +from .types.asset_set_types import MapsLocationInfo +from .types.asset_set_types import MapsLocationSet +from .types.asset_types import AppDeepLinkAsset +from .types.asset_types import BookOnGoogleAsset +from .types.asset_types import BusinessMessageAsset +from .types.asset_types import BusinessMessageCallToActionInfo +from .types.asset_types import BusinessProfileLocation +from .types.asset_types import CallAsset +from .types.asset_types import CalloutAsset +from .types.asset_types import CallToActionAsset +from .types.asset_types import DemandGenCarouselCardAsset +from .types.asset_types import DynamicCustomAsset +from .types.asset_types import DynamicEducationAsset +from .types.asset_types import DynamicFlightsAsset +from .types.asset_types import DynamicHotelsAndRentalsAsset +from .types.asset_types import DynamicJobsAsset +from .types.asset_types import DynamicLocalAsset +from .types.asset_types import DynamicRealEstateAsset +from .types.asset_types import DynamicTravelAsset +from .types.asset_types import FacebookMessengerBusinessMessageInfo +from .types.asset_types import HotelCalloutAsset +from .types.asset_types import HotelPropertyAsset +from .types.asset_types import ImageAsset +from .types.asset_types import ImageDimension +from .types.asset_types import LeadFormAsset +from .types.asset_types import LeadFormCustomQuestionField +from .types.asset_types import LeadFormDeliveryMethod +from .types.asset_types import LeadFormField +from .types.asset_types import LeadFormSingleChoiceAnswers +from .types.asset_types import LocationAsset +from .types.asset_types import MediaBundleAsset +from .types.asset_types import MobileAppAsset +from .types.asset_types import PageFeedAsset +from .types.asset_types import PriceAsset +from .types.asset_types import PriceOffering +from .types.asset_types import PromotionAsset +from .types.asset_types import PromotionBarcodeInfo +from .types.asset_types import PromotionQrCodeInfo +from .types.asset_types import SitelinkAsset +from .types.asset_types import StructuredSnippetAsset +from .types.asset_types import TextAsset +from .types.asset_types import WebhookDelivery +from .types.asset_types import WhatsappBusinessMessageInfo +from .types.asset_types import YoutubeVideoAsset +from .types.asset_types import YouTubeVideoListAsset +from .types.asset_types import ZaloBusinessMessageInfo +from .types.asset_usage import AssetUsage +from .types.audience_insights_attribute import AudienceInsightsAttribute +from .types.audience_insights_attribute import AudienceInsightsAttributeMetadata +from .types.audience_insights_attribute import ( + AudienceInsightsAttributeMetadataGroup, +) +from .types.audience_insights_attribute import AudienceInsightsCategory +from .types.audience_insights_attribute import AudienceInsightsEntity +from .types.audience_insights_attribute import AudienceInsightsLineup +from .types.audience_insights_attribute import InsightsAudienceAttributeGroup +from .types.audience_insights_attribute import KnowledgeGraphAttributeMetadata +from .types.audience_insights_attribute import LineupAttributeMetadata +from .types.audience_insights_attribute import LocationAttributeMetadata +from .types.audience_insights_attribute import UserInterestAttributeMetadata +from .types.audience_insights_attribute import UserListAttributeMetadata +from .types.audience_insights_attribute import YouTubeChannelAttributeMetadata +from .types.audience_insights_attribute import YouTubeVideoAttributeMetadata +from .types.audiences import AgeDimension +from .types.audiences import AgeSegment +from .types.audiences import AudienceDimension +from .types.audiences import AudienceExclusionDimension +from .types.audiences import AudienceSegment +from .types.audiences import AudienceSegmentDimension +from .types.audiences import CustomAudienceSegment +from .types.audiences import DetailedDemographicSegment +from .types.audiences import ExclusionSegment +from .types.audiences import GenderDimension +from .types.audiences import HouseholdIncomeDimension +from .types.audiences import LifeEventSegment +from .types.audiences import ParentalStatusDimension +from .types.audiences import UserInterestSegment +from .types.audiences import UserListSegment +from .types.bidding import Commission +from .types.bidding import EnhancedCpc +from .types.bidding import FixedCpm +from .types.bidding import FixedCpmTargetFrequencyGoalInfo +from .types.bidding import ManualCpa +from .types.bidding import ManualCpc +from .types.bidding import ManualCpm +from .types.bidding import ManualCpv +from .types.bidding import MaximizeConversions +from .types.bidding import MaximizeConversionValue +from .types.bidding import PercentCpc +from .types.bidding import TargetCpa +from .types.bidding import TargetCpc +from .types.bidding import TargetCpm +from .types.bidding import TargetCpmTargetFrequencyGoal +from .types.bidding import TargetCpv +from .types.bidding import TargetImpressionShare +from .types.bidding import TargetRoas +from .types.bidding import TargetSpend +from .types.campaign_goal_settings import CampaignGoalSettings +from .types.campaign_reservation_quote import CampaignReservationQuote +from .types.click_location import ClickLocation +from .types.consent import Consent +from .types.criteria import ActivityCityInfo +from .types.criteria import ActivityCountryInfo +from .types.criteria import ActivityIdInfo +from .types.criteria import ActivityRatingInfo +from .types.criteria import ActivityStateInfo +from .types.criteria import AddressInfo +from .types.criteria import AdScheduleInfo +from .types.criteria import AgeRangeInfo +from .types.criteria import AppPaymentModelInfo +from .types.criteria import AudienceInfo +from .types.criteria import BrandInfo +from .types.criteria import BrandListInfo +from .types.criteria import CarrierInfo +from .types.criteria import CombinedAudienceInfo +from .types.criteria import ContentLabelInfo +from .types.criteria import CustomAffinityInfo +from .types.criteria import CustomAudienceInfo +from .types.criteria import CustomIntentInfo +from .types.criteria import DeviceInfo +from .types.criteria import ExtendedDemographicInfo +from .types.criteria import GenderInfo +from .types.criteria import GeoPointInfo +from .types.criteria import HotelAdvanceBookingWindowInfo +from .types.criteria import HotelCheckInDateRangeInfo +from .types.criteria import HotelCheckInDayInfo +from .types.criteria import HotelCityInfo +from .types.criteria import HotelClassInfo +from .types.criteria import HotelCountryRegionInfo +from .types.criteria import HotelDateSelectionTypeInfo +from .types.criteria import HotelIdInfo +from .types.criteria import HotelLengthOfStayInfo +from .types.criteria import HotelStateInfo +from .types.criteria import IncomeRangeInfo +from .types.criteria import InteractionTypeInfo +from .types.criteria import IpBlockInfo +from .types.criteria import KeywordInfo +from .types.criteria import KeywordThemeInfo +from .types.criteria import LanguageInfo +from .types.criteria import LifeEventInfo +from .types.criteria import ListingDimensionInfo +from .types.criteria import ListingDimensionPath +from .types.criteria import ListingGroupInfo +from .types.criteria import ListingScopeInfo +from .types.criteria import LocalServiceIdInfo +from .types.criteria import LocationGroupInfo +from .types.criteria import LocationInfo +from .types.criteria import MobileAppCategoryInfo +from .types.criteria import MobileApplicationInfo +from .types.criteria import MobileDeviceInfo +from .types.criteria import NegativeKeywordListInfo +from .types.criteria import OperatingSystemVersionInfo +from .types.criteria import ParentalStatusInfo +from .types.criteria import PlacementInfo +from .types.criteria import PlacementListInfo +from .types.criteria import ProductBrandInfo +from .types.criteria import ProductCategoryInfo +from .types.criteria import ProductChannelExclusivityInfo +from .types.criteria import ProductChannelInfo +from .types.criteria import ProductConditionInfo +from .types.criteria import ProductCustomAttributeInfo +from .types.criteria import ProductGroupingInfo +from .types.criteria import ProductItemIdInfo +from .types.criteria import ProductLabelsInfo +from .types.criteria import ProductLegacyConditionInfo +from .types.criteria import ProductTypeFullInfo +from .types.criteria import ProductTypeInfo +from .types.criteria import ProximityInfo +from .types.criteria import RetailFilter +from .types.criteria import RetailFilterBundle +from .types.criteria import RetailFilterExpression +from .types.criteria import RetailTag +from .types.criteria import SearchThemeInfo +from .types.criteria import TopicInfo +from .types.criteria import UnknownListingDimensionInfo +from .types.criteria import UserInterestInfo +from .types.criteria import UserListInfo +from .types.criteria import VerticalAdsItemGroupRuleInfo +from .types.criteria import VerticalAdsItemGroupRuleListInfo +from .types.criteria import VideoLineupInfo +from .types.criteria import WebpageConditionInfo +from .types.criteria import WebpageInfo +from .types.criteria import WebpageListInfo +from .types.criteria import WebpageSampleInfo +from .types.criteria import YouTubeChannelInfo +from .types.criteria import YouTubeVideoInfo +from .types.criterion_category_availability import CriterionCategoryAvailability +from .types.criterion_category_availability import ( + CriterionCategoryChannelAvailability, +) +from .types.criterion_category_availability import ( + CriterionCategoryLocaleAvailability, +) +from .types.custom_parameter import CustomParameter +from .types.customizer_value import CustomizerValue +from .types.dates import DateRange +from .types.dates import YearMonth +from .types.dates import YearMonthRange +from .types.extensions import CallFeedItem +from .types.extensions import CalloutFeedItem +from .types.extensions import SitelinkFeedItem +from .types.feed_common import Money +from .types.final_app_url import FinalAppUrl +from .types.frequency_cap import FrequencyCapEntry +from .types.frequency_cap import FrequencyCapKey +from .types.goal_common import CustomerLifecycleOptimizationValueSettings +from .types.goal_setting import GoalSetting +from .types.keyword_plan_common import ConceptGroup +from .types.keyword_plan_common import HistoricalMetricsOptions +from .types.keyword_plan_common import KeywordAnnotations +from .types.keyword_plan_common import KeywordConcept +from .types.keyword_plan_common import KeywordPlanAggregateMetricResults +from .types.keyword_plan_common import KeywordPlanAggregateMetrics +from .types.keyword_plan_common import KeywordPlanDeviceSearches +from .types.keyword_plan_common import KeywordPlanHistoricalMetrics +from .types.keyword_plan_common import MonthlySearchVolume +from .types.lifecycle_goals import LifecycleGoalValueSettings +from .types.local_services import LocalServicesDocumentReadOnly +from .types.metric_goal import MetricGoal +from .types.metrics import Metrics +from .types.metrics import SearchVolumeRange +from .types.offline_user_data import CustomerMatchUserListMetadata +from .types.offline_user_data import EventAttribute +from .types.offline_user_data import EventItemAttribute +from .types.offline_user_data import ItemAttribute +from .types.offline_user_data import OfflineUserAddressInfo +from .types.offline_user_data import ShoppingLoyalty +from .types.offline_user_data import StoreAttribute +from .types.offline_user_data import StoreSalesMetadata +from .types.offline_user_data import StoreSalesThirdPartyMetadata +from .types.offline_user_data import TransactionAttribute +from .types.offline_user_data import UserAttribute +from .types.offline_user_data import UserData +from .types.offline_user_data import UserIdentifier +from .types.policy import PolicyTopicConstraint +from .types.policy import PolicyTopicEntry +from .types.policy import PolicyTopicEvidence +from .types.policy import PolicyValidationParameter +from .types.policy import PolicyViolationKey +from .types.policy_summary import PolicySummary +from .types.real_time_bidding_setting import RealTimeBiddingSetting +from .types.segments import AssetInteractionTarget +from .types.segments import BudgetCampaignAssociationStatus +from .types.segments import Keyword +from .types.segments import Segments +from .types.segments import SkAdNetworkSourceApp +from .types.simulation import BudgetSimulationPoint +from .types.simulation import BudgetSimulationPointList +from .types.simulation import CpcBidSimulationPoint +from .types.simulation import CpcBidSimulationPointList +from .types.simulation import CpvBidSimulationPoint +from .types.simulation import CpvBidSimulationPointList +from .types.simulation import PercentCpcBidSimulationPoint +from .types.simulation import PercentCpcBidSimulationPointList +from .types.simulation import TargetCpaSimulationPoint +from .types.simulation import TargetCpaSimulationPointList +from .types.simulation import TargetImpressionShareSimulationPoint +from .types.simulation import TargetImpressionShareSimulationPointList +from .types.simulation import TargetRoasSimulationPoint +from .types.simulation import TargetRoasSimulationPointList +from .types.tag_snippet import TagSnippet +from .types.targeting_setting import TargetingSetting +from .types.targeting_setting import TargetRestriction +from .types.targeting_setting import TargetRestrictionOperation +from .types.text_label import TextLabel +from .types.third_party_integration_partners import ( + CampaignThirdPartyBrandLiftIntegrationPartner, +) +from .types.third_party_integration_partners import ( + CampaignThirdPartyBrandSafetyIntegrationPartner, +) +from .types.third_party_integration_partners import ( + CampaignThirdPartyIntegrationPartners, +) +from .types.third_party_integration_partners import ( + CampaignThirdPartyReachIntegrationPartner, +) +from .types.third_party_integration_partners import ( + CampaignThirdPartyViewabilityIntegrationPartner, +) +from .types.third_party_integration_partners import ( + CustomerThirdPartyBrandLiftIntegrationPartner, +) +from .types.third_party_integration_partners import ( + CustomerThirdPartyBrandSafetyIntegrationPartner, +) +from .types.third_party_integration_partners import ( + CustomerThirdPartyIntegrationPartners, +) +from .types.third_party_integration_partners import ( + CustomerThirdPartyReachIntegrationPartner, +) +from .types.third_party_integration_partners import ( + CustomerThirdPartyViewabilityIntegrationPartner, +) +from .types.third_party_integration_partners import ( + ThirdPartyIntegrationPartnerData, +) +from .types.url_collection import UrlCollection +from .types.user_lists import BasicUserListInfo +from .types.user_lists import CrmBasedUserListInfo +from .types.user_lists import FlexibleRuleOperandInfo +from .types.user_lists import FlexibleRuleUserListInfo +from .types.user_lists import LogicalUserListInfo +from .types.user_lists import LogicalUserListOperandInfo +from .types.user_lists import LookalikeUserListInfo +from .types.user_lists import RuleBasedUserListInfo +from .types.user_lists import SimilarUserListInfo +from .types.user_lists import UserListActionInfo +from .types.user_lists import UserListDateRuleItemInfo +from .types.user_lists import UserListLogicalRuleInfo +from .types.user_lists import UserListNumberRuleItemInfo +from .types.user_lists import UserListRuleInfo +from .types.user_lists import UserListRuleItemGroupInfo +from .types.user_lists import UserListRuleItemInfo +from .types.user_lists import UserListStringRuleItemInfo +from .types.value import Value + +if hasattr(api_core, "check_python_version") and hasattr( + api_core, "check_dependency_versions" +): # pragma: NO COVER + api_core.check_python_version("google.ads.googleads.v24") # type: ignore + api_core.check_dependency_versions("google.ads.googleads.v24") # type: ignore +else: # pragma: NO COVER + # An older version of api_core is installed which does not define the + # functions above. We do equivalent checks manually. + try: + import warnings + import sys + + _py_version_str = sys.version.split()[0] + _package_label = "google.ads.googleads.v24" + if sys.version_info < (3, 9): + warnings.warn( + "You are using a non-supported Python version " + + f"({_py_version_str}). Google will not post any further " + + f"updates to {_package_label} supporting this Python version. " + + "Please upgrade to the latest Python version, or at " + + f"least to Python 3.9, and then update {_package_label}.", + FutureWarning, + ) + if sys.version_info[:2] == (3, 9): + warnings.warn( + f"You are using a Python version ({_py_version_str}) " + + f"which Google will stop supporting in {_package_label} in " + + "January 2026. Please " + + "upgrade to the latest Python version, or at " + + "least to Python 3.10, before then, and " + + f"then update {_package_label}.", + FutureWarning, + ) + + def parse_version_to_tuple(version_string: str): + """Safely converts a semantic version string to a comparable tuple of integers. + Example: "4.25.8" -> (4, 25, 8) + Ignores non-numeric parts and handles common version formats. + Args: + version_string: Version string in the format "x.y.z" or "x.y.z" + Returns: + Tuple of integers for the parsed version string. + """ + parts = [] + for part in version_string.split("."): + try: + parts.append(int(part)) + except ValueError: + # If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here. + # This is a simplification compared to 'packaging.parse_version', but sufficient + # for comparing strictly numeric semantic versions. + break + return tuple(parts) + + def _get_version(dependency_name): + try: + version_string: str = metadata.version(dependency_name) + parsed_version = parse_version_to_tuple(version_string) + return (parsed_version, version_string) + except Exception: + # Catch exceptions from metadata.version() (e.g., PackageNotFoundError) + # or errors during parse_version_to_tuple + return (None, "--") + + _dependency_package = "google.protobuf" + _next_supported_version = "4.25.8" + _next_supported_version_tuple = (4, 25, 8) + _recommendation = " (we recommend 6.x)" + (_version_used, _version_used_string) = _get_version( + _dependency_package + ) + if _version_used and _version_used < _next_supported_version_tuple: + warnings.warn( + f"Package {_package_label} depends on " + + f"{_dependency_package}, currently installed at version " + + f"{_version_used_string}. Future updates to " + + f"{_package_label} will require {_dependency_package} at " + + f"version {_next_supported_version} or higher{_recommendation}." + + " Please ensure " + + "that either (a) your Python environment doesn't pin the " + + f"version of {_dependency_package}, so that updates to " + + f"{_package_label} can require the higher version, or " + + "(b) you manually update your Python environment to use at " + + f"least version {_next_supported_version} of " + + f"{_dependency_package}.", + FutureWarning, + ) + except Exception: + warnings.warn( + "Could not determine the version of Python " + + "currently being used. To continue receiving " + + "updates for {_package_label}, ensure you are " + + "using a supported version of Python; see " + + "https://devguide.python.org/versions/" + ) + +__all__ = ( + "ActivityCityInfo", + "ActivityCountryInfo", + "ActivityIdInfo", + "ActivityRatingInfo", + "ActivityStateInfo", + "AdAppDeepLinkAsset", + "AdAssetPolicySummary", + "AdCallToActionAsset", + "AdDemandGenCarouselCardAsset", + "AdImageAsset", + "AdMediaBundleAsset", + "AdScheduleInfo", + "AdTextAsset", + "AdVideoAsset", + "AdVideoAssetInfo", + "AdVideoAssetInventoryPreferences", + "AdVideoAssetLinkFeatureControl", + "AdditionalApplicationInfo", + "AddressInfo", + "AgeDimension", + "AgeRangeInfo", + "AgeSegment", + "AppAdInfo", + "AppDeepLinkAsset", + "AppEngagementAdInfo", + "AppPaymentModelInfo", + "AppPreRegistrationAdInfo", + "AssetDisapproved", + "AssetInteractionTarget", + "AssetLinkPrimaryStatusDetails", + "AssetUsage", + "AudienceDimension", + "AudienceExclusionDimension", + "AudienceInfo", + "AudienceInsightsAttribute", + "AudienceInsightsAttributeMetadata", + "AudienceInsightsAttributeMetadataGroup", + "AudienceInsightsCategory", + "AudienceInsightsEntity", + "AudienceInsightsLineup", + "AudienceSegment", + "AudienceSegmentDimension", + "BasicUserListInfo", + "BookOnGoogleAsset", + "BrandInfo", + "BrandListInfo", + "BudgetCampaignAssociationStatus", + "BudgetSimulationPoint", + "BudgetSimulationPointList", + "BusinessMessageAsset", + "BusinessMessageCallToActionInfo", + "BusinessProfileBusinessNameFilter", + "BusinessProfileLocation", + "BusinessProfileLocationGroup", + "BusinessProfileLocationSet", + "CallAsset", + "CallFeedItem", + "CallToActionAsset", + "CalloutAsset", + "CalloutFeedItem", + "CampaignGoalSettings", + "CampaignReservationQuote", + "CampaignThirdPartyBrandLiftIntegrationPartner", + "CampaignThirdPartyBrandSafetyIntegrationPartner", + "CampaignThirdPartyIntegrationPartners", + "CampaignThirdPartyReachIntegrationPartner", + "CampaignThirdPartyViewabilityIntegrationPartner", + "CarrierInfo", + "ChainFilter", + "ChainLocationGroup", + "ChainSet", + "ClickLocation", + "CombinedAudienceInfo", + "Commission", + "ConceptGroup", + "Consent", + "ContentLabelInfo", + "CpcBidSimulationPoint", + "CpcBidSimulationPointList", + "CpvBidSimulationPoint", + "CpvBidSimulationPointList", + "CriterionCategoryAvailability", + "CriterionCategoryChannelAvailability", + "CriterionCategoryLocaleAvailability", + "CrmBasedUserListInfo", + "CustomAffinityInfo", + "CustomAudienceInfo", + "CustomAudienceSegment", + "CustomIntentInfo", + "CustomParameter", + "CustomerLifecycleOptimizationValueSettings", + "CustomerMatchUserListMetadata", + "CustomerThirdPartyBrandLiftIntegrationPartner", + "CustomerThirdPartyBrandSafetyIntegrationPartner", + "CustomerThirdPartyIntegrationPartners", + "CustomerThirdPartyReachIntegrationPartner", + "CustomerThirdPartyViewabilityIntegrationPartner", + "CustomizerValue", + "DateRange", + "DemandGenCarouselAdInfo", + "DemandGenCarouselCardAsset", + "DemandGenMultiAssetAdInfo", + "DemandGenProductAdInfo", + "DemandGenVideoResponsiveAdInfo", + "DetailedDemographicSegment", + "DeviceInfo", + "DisplayUploadAdInfo", + "DynamicBusinessProfileLocationGroupFilter", + "DynamicCustomAsset", + "DynamicEducationAsset", + "DynamicFlightsAsset", + "DynamicHotelsAndRentalsAsset", + "DynamicJobsAsset", + "DynamicLocalAsset", + "DynamicRealEstateAsset", + "DynamicTravelAsset", + "EnhancedCpc", + "EventAttribute", + "EventItemAttribute", + "ExclusionSegment", + "ExpandedDynamicSearchAdInfo", + "ExpandedTextAdInfo", + "ExtendedDemographicInfo", + "FacebookMessengerBusinessMessageInfo", + "FinalAppUrl", + "FixedCpm", + "FixedCpmTargetFrequencyGoalInfo", + "FlexibleRuleOperandInfo", + "FlexibleRuleUserListInfo", + "FrequencyCapEntry", + "FrequencyCapKey", + "GenderDimension", + "GenderInfo", + "GeoPointInfo", + "GoalSetting", + "HistoricalMetricsOptions", + "HotelAdInfo", + "HotelAdvanceBookingWindowInfo", + "HotelCalloutAsset", + "HotelCheckInDateRangeInfo", + "HotelCheckInDayInfo", + "HotelCityInfo", + "HotelClassInfo", + "HotelCountryRegionInfo", + "HotelDateSelectionTypeInfo", + "HotelIdInfo", + "HotelLengthOfStayInfo", + "HotelPropertyAsset", + "HotelStateInfo", + "HouseholdIncomeDimension", + "ImageAdInfo", + "ImageAsset", + "ImageDimension", + "InFeedVideoAdInfo", + "IncomeRangeInfo", + "InsightsAudienceAttributeGroup", + "InteractionTypeInfo", + "IpBlockInfo", + "ItemAttribute", + "Keyword", + "KeywordAnnotations", + "KeywordConcept", + "KeywordInfo", + "KeywordPlanAggregateMetricResults", + "KeywordPlanAggregateMetrics", + "KeywordPlanDeviceSearches", + "KeywordPlanHistoricalMetrics", + "KeywordThemeInfo", + "KnowledgeGraphAttributeMetadata", + "LanguageInfo", + "LeadFormAsset", + "LeadFormCustomQuestionField", + "LeadFormDeliveryMethod", + "LeadFormField", + "LeadFormSingleChoiceAnswers", + "LegacyAppInstallAdInfo", + "LegacyResponsiveDisplayAdInfo", + "LifeEventInfo", + "LifeEventSegment", + "LifecycleGoalValueSettings", + "LineupAttributeMetadata", + "ListingDimensionInfo", + "ListingDimensionPath", + "ListingGroupInfo", + "ListingScopeInfo", + "LocalAdInfo", + "LocalServiceIdInfo", + "LocalServicesDocumentReadOnly", + "LocationAsset", + "LocationAttributeMetadata", + "LocationGroupInfo", + "LocationInfo", + "LocationSet", + "LogicalUserListInfo", + "LogicalUserListOperandInfo", + "LookalikeUserListInfo", + "ManualCpa", + "ManualCpc", + "ManualCpm", + "ManualCpv", + "MapsLocationInfo", + "MapsLocationSet", + "MaximizeConversionValue", + "MaximizeConversions", + "MediaBundleAsset", + "MetricGoal", + "Metrics", + "MobileAppAsset", + "MobileAppCategoryInfo", + "MobileApplicationInfo", + "MobileDeviceInfo", + "Money", + "MonthlySearchVolume", + "NegativeKeywordListInfo", + "OfflineUserAddressInfo", + "OperatingSystemVersionInfo", + "PageFeedAsset", + "ParentalStatusDimension", + "ParentalStatusInfo", + "PercentCpc", + "PercentCpcBidSimulationPoint", + "PercentCpcBidSimulationPointList", + "PlacementInfo", + "PlacementListInfo", + "PolicySummary", + "PolicyTopicConstraint", + "PolicyTopicEntry", + "PolicyTopicEvidence", + "PolicyValidationParameter", + "PolicyViolationKey", + "PriceAsset", + "PriceOffering", + "ProductBrandInfo", + "ProductCategoryInfo", + "ProductChannelExclusivityInfo", + "ProductChannelInfo", + "ProductConditionInfo", + "ProductCustomAttributeInfo", + "ProductGroupingInfo", + "ProductItemIdInfo", + "ProductLabelsInfo", + "ProductLegacyConditionInfo", + "ProductTypeFullInfo", + "ProductTypeInfo", + "PromotionAsset", + "PromotionBarcodeInfo", + "PromotionQrCodeInfo", + "ProximityInfo", + "RealTimeBiddingSetting", + "ResponsiveDisplayAdControlSpec", + "ResponsiveDisplayAdInfo", + "ResponsiveSearchAdInfo", + "RetailFilter", + "RetailFilterBundle", + "RetailFilterExpression", + "RetailTag", + "RuleBasedUserListInfo", + "SearchThemeInfo", + "SearchVolumeRange", + "Segments", + "ShoppingComparisonListingAdInfo", + "ShoppingLoyalty", + "ShoppingProductAdInfo", + "ShoppingSmartAdInfo", + "SimilarUserListInfo", + "SitelinkAsset", + "SitelinkFeedItem", + "SkAdNetworkSourceApp", + "SmartCampaignAdInfo", + "StoreAttribute", + "StoreSalesMetadata", + "StoreSalesThirdPartyMetadata", + "StructuredSnippetAsset", + "TagSnippet", + "TargetCpa", + "TargetCpaSimulationPoint", + "TargetCpaSimulationPointList", + "TargetCpc", + "TargetCpm", + "TargetCpmTargetFrequencyGoal", + "TargetCpv", + "TargetImpressionShare", + "TargetImpressionShareSimulationPoint", + "TargetImpressionShareSimulationPointList", + "TargetRestriction", + "TargetRestrictionOperation", + "TargetRoas", + "TargetRoasSimulationPoint", + "TargetRoasSimulationPointList", + "TargetSpend", + "TargetingSetting", + "TextAdInfo", + "TextAsset", + "TextLabel", + "ThirdPartyIntegrationPartnerData", + "TopicInfo", + "TransactionAttribute", + "TravelAdInfo", + "UnknownListingDimensionInfo", + "UrlCollection", + "UserAttribute", + "UserData", + "UserIdentifier", + "UserInterestAttributeMetadata", + "UserInterestInfo", + "UserInterestSegment", + "UserListActionInfo", + "UserListAttributeMetadata", + "UserListDateRuleItemInfo", + "UserListInfo", + "UserListLogicalRuleInfo", + "UserListNumberRuleItemInfo", + "UserListRuleInfo", + "UserListRuleItemGroupInfo", + "UserListRuleItemInfo", + "UserListSegment", + "UserListStringRuleItemInfo", + "Value", + "VerticalAdsItemGroupRuleInfo", + "VerticalAdsItemGroupRuleListInfo", + "VideoAdInfo", + "VideoBumperInStreamAdInfo", + "VideoLineupInfo", + "VideoNonSkippableInStreamAdInfo", + "VideoOutstreamAdInfo", + "VideoResponsiveAdInfo", + "VideoTrueViewInStreamAdInfo", + "WebhookDelivery", + "WebpageConditionInfo", + "WebpageInfo", + "WebpageListInfo", + "WebpageSampleInfo", + "WhatsappBusinessMessageInfo", + "YearMonth", + "YearMonthRange", + "YouTubeAudioAdInfo", + "YouTubeChannelAttributeMetadata", + "YouTubeChannelInfo", + "YouTubeVideoAttributeMetadata", + "YouTubeVideoInfo", + "YouTubeVideoListAsset", + "YoutubeVideoAsset", + "ZaloBusinessMessageInfo", +) diff --git a/google/ads/googleads/v24/common/services/__init__.py b/google/ads/googleads/v24/common/services/__init__.py new file mode 100644 index 000000000..cbf94b283 --- /dev/null +++ b/google/ads/googleads/v24/common/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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. +# diff --git a/google/ads/googleads/v24/common/types/__init__.py b/google/ads/googleads/v24/common/types/__init__.py new file mode 100644 index 000000000..f53d27600 --- /dev/null +++ b/google/ads/googleads/v24/common/types/__init__.py @@ -0,0 +1,790 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .ad_asset import ( + AdAppDeepLinkAsset, + AdCallToActionAsset, + AdDemandGenCarouselCardAsset, + AdImageAsset, + AdMediaBundleAsset, + AdTextAsset, + AdVideoAsset, + AdVideoAssetInfo, + AdVideoAssetInventoryPreferences, + AdVideoAssetLinkFeatureControl, +) +from .ad_type_infos import ( + AppAdInfo, + AppEngagementAdInfo, + AppPreRegistrationAdInfo, + DemandGenCarouselAdInfo, + DemandGenMultiAssetAdInfo, + DemandGenProductAdInfo, + DemandGenVideoResponsiveAdInfo, + DisplayUploadAdInfo, + ExpandedDynamicSearchAdInfo, + ExpandedTextAdInfo, + HotelAdInfo, + ImageAdInfo, + InFeedVideoAdInfo, + LegacyAppInstallAdInfo, + LegacyResponsiveDisplayAdInfo, + LocalAdInfo, + ResponsiveDisplayAdControlSpec, + ResponsiveDisplayAdInfo, + ResponsiveSearchAdInfo, + ShoppingComparisonListingAdInfo, + ShoppingProductAdInfo, + ShoppingSmartAdInfo, + SmartCampaignAdInfo, + TextAdInfo, + TravelAdInfo, + VideoAdInfo, + VideoBumperInStreamAdInfo, + VideoNonSkippableInStreamAdInfo, + VideoOutstreamAdInfo, + VideoResponsiveAdInfo, + VideoTrueViewInStreamAdInfo, + YouTubeAudioAdInfo, +) +from .additional_application_info import ( + AdditionalApplicationInfo, +) +from .asset_policy import ( + AdAssetPolicySummary, + AssetDisapproved, + AssetLinkPrimaryStatusDetails, +) +from .asset_set_types import ( + BusinessProfileBusinessNameFilter, + BusinessProfileLocationGroup, + BusinessProfileLocationSet, + ChainFilter, + ChainLocationGroup, + ChainSet, + DynamicBusinessProfileLocationGroupFilter, + LocationSet, + MapsLocationInfo, + MapsLocationSet, +) +from .asset_types import ( + AppDeepLinkAsset, + BookOnGoogleAsset, + BusinessMessageAsset, + BusinessMessageCallToActionInfo, + BusinessProfileLocation, + CallAsset, + CalloutAsset, + CallToActionAsset, + DemandGenCarouselCardAsset, + DynamicCustomAsset, + DynamicEducationAsset, + DynamicFlightsAsset, + DynamicHotelsAndRentalsAsset, + DynamicJobsAsset, + DynamicLocalAsset, + DynamicRealEstateAsset, + DynamicTravelAsset, + FacebookMessengerBusinessMessageInfo, + HotelCalloutAsset, + HotelPropertyAsset, + ImageAsset, + ImageDimension, + LeadFormAsset, + LeadFormCustomQuestionField, + LeadFormDeliveryMethod, + LeadFormField, + LeadFormSingleChoiceAnswers, + LocationAsset, + MediaBundleAsset, + MobileAppAsset, + PageFeedAsset, + PriceAsset, + PriceOffering, + PromotionAsset, + PromotionBarcodeInfo, + PromotionQrCodeInfo, + SitelinkAsset, + StructuredSnippetAsset, + TextAsset, + WebhookDelivery, + WhatsappBusinessMessageInfo, + YoutubeVideoAsset, + YouTubeVideoListAsset, + ZaloBusinessMessageInfo, +) +from .asset_usage import ( + AssetUsage, +) +from .audience_insights_attribute import ( + AudienceInsightsAttribute, + AudienceInsightsAttributeMetadata, + AudienceInsightsAttributeMetadataGroup, + AudienceInsightsCategory, + AudienceInsightsEntity, + AudienceInsightsLineup, + InsightsAudienceAttributeGroup, + KnowledgeGraphAttributeMetadata, + LineupAttributeMetadata, + LocationAttributeMetadata, + UserInterestAttributeMetadata, + UserListAttributeMetadata, + YouTubeChannelAttributeMetadata, + YouTubeVideoAttributeMetadata, +) +from .audiences import ( + AgeDimension, + AgeSegment, + AudienceDimension, + AudienceExclusionDimension, + AudienceSegment, + AudienceSegmentDimension, + CustomAudienceSegment, + DetailedDemographicSegment, + ExclusionSegment, + GenderDimension, + HouseholdIncomeDimension, + LifeEventSegment, + ParentalStatusDimension, + UserInterestSegment, + UserListSegment, +) +from .bidding import ( + Commission, + EnhancedCpc, + FixedCpm, + FixedCpmTargetFrequencyGoalInfo, + ManualCpa, + ManualCpc, + ManualCpm, + ManualCpv, + MaximizeConversions, + MaximizeConversionValue, + PercentCpc, + TargetCpa, + TargetCpc, + TargetCpm, + TargetCpmTargetFrequencyGoal, + TargetCpv, + TargetImpressionShare, + TargetRoas, + TargetSpend, +) +from .campaign_goal_settings import ( + CampaignGoalSettings, +) +from .campaign_reservation_quote import ( + CampaignReservationQuote, +) +from .click_location import ( + ClickLocation, +) +from .consent import ( + Consent, +) +from .criteria import ( + ActivityCityInfo, + ActivityCountryInfo, + ActivityIdInfo, + ActivityRatingInfo, + ActivityStateInfo, + AddressInfo, + AdScheduleInfo, + AgeRangeInfo, + AppPaymentModelInfo, + AudienceInfo, + BrandInfo, + BrandListInfo, + CarrierInfo, + CombinedAudienceInfo, + ContentLabelInfo, + CustomAffinityInfo, + CustomAudienceInfo, + CustomIntentInfo, + DeviceInfo, + ExtendedDemographicInfo, + GenderInfo, + GeoPointInfo, + HotelAdvanceBookingWindowInfo, + HotelCheckInDateRangeInfo, + HotelCheckInDayInfo, + HotelCityInfo, + HotelClassInfo, + HotelCountryRegionInfo, + HotelDateSelectionTypeInfo, + HotelIdInfo, + HotelLengthOfStayInfo, + HotelStateInfo, + IncomeRangeInfo, + InteractionTypeInfo, + IpBlockInfo, + KeywordInfo, + KeywordThemeInfo, + LanguageInfo, + LifeEventInfo, + ListingDimensionInfo, + ListingDimensionPath, + ListingGroupInfo, + ListingScopeInfo, + LocalServiceIdInfo, + LocationGroupInfo, + LocationInfo, + MobileAppCategoryInfo, + MobileApplicationInfo, + MobileDeviceInfo, + NegativeKeywordListInfo, + OperatingSystemVersionInfo, + ParentalStatusInfo, + PlacementInfo, + PlacementListInfo, + ProductBrandInfo, + ProductCategoryInfo, + ProductChannelExclusivityInfo, + ProductChannelInfo, + ProductConditionInfo, + ProductCustomAttributeInfo, + ProductGroupingInfo, + ProductItemIdInfo, + ProductLabelsInfo, + ProductLegacyConditionInfo, + ProductTypeFullInfo, + ProductTypeInfo, + ProximityInfo, + RetailFilter, + RetailFilterBundle, + RetailFilterExpression, + RetailTag, + SearchThemeInfo, + TopicInfo, + UnknownListingDimensionInfo, + UserInterestInfo, + UserListInfo, + VerticalAdsItemGroupRuleInfo, + VerticalAdsItemGroupRuleListInfo, + VideoLineupInfo, + WebpageConditionInfo, + WebpageInfo, + WebpageListInfo, + WebpageSampleInfo, + YouTubeChannelInfo, + YouTubeVideoInfo, +) +from .criterion_category_availability import ( + CriterionCategoryAvailability, + CriterionCategoryChannelAvailability, + CriterionCategoryLocaleAvailability, +) +from .custom_parameter import ( + CustomParameter, +) +from .customizer_value import ( + CustomizerValue, +) +from .dates import ( + DateRange, + YearMonth, + YearMonthRange, +) +from .extensions import ( + CallFeedItem, + CalloutFeedItem, + SitelinkFeedItem, +) +from .feed_common import ( + Money, +) +from .final_app_url import ( + FinalAppUrl, +) +from .frequency_cap import ( + FrequencyCapEntry, + FrequencyCapKey, +) +from .goal_common import ( + CustomerLifecycleOptimizationValueSettings, +) +from .goal_setting import ( + GoalSetting, +) +from .keyword_plan_common import ( + ConceptGroup, + HistoricalMetricsOptions, + KeywordAnnotations, + KeywordConcept, + KeywordPlanAggregateMetricResults, + KeywordPlanAggregateMetrics, + KeywordPlanDeviceSearches, + KeywordPlanHistoricalMetrics, + MonthlySearchVolume, +) +from .lifecycle_goals import ( + LifecycleGoalValueSettings, +) +from .local_services import ( + LocalServicesDocumentReadOnly, +) +from .metric_goal import ( + MetricGoal, +) +from .metrics import ( + Metrics, + SearchVolumeRange, +) +from .offline_user_data import ( + CustomerMatchUserListMetadata, + EventAttribute, + EventItemAttribute, + ItemAttribute, + OfflineUserAddressInfo, + ShoppingLoyalty, + StoreAttribute, + StoreSalesMetadata, + StoreSalesThirdPartyMetadata, + TransactionAttribute, + UserAttribute, + UserData, + UserIdentifier, +) +from .policy import ( + PolicyTopicConstraint, + PolicyTopicEntry, + PolicyTopicEvidence, + PolicyValidationParameter, + PolicyViolationKey, +) +from .policy_summary import ( + PolicySummary, +) +from .real_time_bidding_setting import ( + RealTimeBiddingSetting, +) +from .segments import ( + AssetInteractionTarget, + BudgetCampaignAssociationStatus, + Keyword, + Segments, + SkAdNetworkSourceApp, +) +from .simulation import ( + BudgetSimulationPoint, + BudgetSimulationPointList, + CpcBidSimulationPoint, + CpcBidSimulationPointList, + CpvBidSimulationPoint, + CpvBidSimulationPointList, + PercentCpcBidSimulationPoint, + PercentCpcBidSimulationPointList, + TargetCpaSimulationPoint, + TargetCpaSimulationPointList, + TargetImpressionShareSimulationPoint, + TargetImpressionShareSimulationPointList, + TargetRoasSimulationPoint, + TargetRoasSimulationPointList, +) +from .tag_snippet import ( + TagSnippet, +) +from .targeting_setting import ( + TargetingSetting, + TargetRestriction, + TargetRestrictionOperation, +) +from .text_label import ( + TextLabel, +) +from .third_party_integration_partners import ( + CampaignThirdPartyBrandLiftIntegrationPartner, + CampaignThirdPartyBrandSafetyIntegrationPartner, + CampaignThirdPartyIntegrationPartners, + CampaignThirdPartyReachIntegrationPartner, + CampaignThirdPartyViewabilityIntegrationPartner, + CustomerThirdPartyBrandLiftIntegrationPartner, + CustomerThirdPartyBrandSafetyIntegrationPartner, + CustomerThirdPartyIntegrationPartners, + CustomerThirdPartyReachIntegrationPartner, + CustomerThirdPartyViewabilityIntegrationPartner, + ThirdPartyIntegrationPartnerData, +) +from .url_collection import ( + UrlCollection, +) +from .user_lists import ( + BasicUserListInfo, + CrmBasedUserListInfo, + FlexibleRuleOperandInfo, + FlexibleRuleUserListInfo, + LogicalUserListInfo, + LogicalUserListOperandInfo, + LookalikeUserListInfo, + RuleBasedUserListInfo, + SimilarUserListInfo, + UserListActionInfo, + UserListDateRuleItemInfo, + UserListLogicalRuleInfo, + UserListNumberRuleItemInfo, + UserListRuleInfo, + UserListRuleItemGroupInfo, + UserListRuleItemInfo, + UserListStringRuleItemInfo, +) +from .value import ( + Value, +) + +__all__ = ( + "AdAppDeepLinkAsset", + "AdCallToActionAsset", + "AdDemandGenCarouselCardAsset", + "AdImageAsset", + "AdMediaBundleAsset", + "AdTextAsset", + "AdVideoAsset", + "AdVideoAssetInfo", + "AdVideoAssetInventoryPreferences", + "AdVideoAssetLinkFeatureControl", + "AppAdInfo", + "AppEngagementAdInfo", + "AppPreRegistrationAdInfo", + "DemandGenCarouselAdInfo", + "DemandGenMultiAssetAdInfo", + "DemandGenProductAdInfo", + "DemandGenVideoResponsiveAdInfo", + "DisplayUploadAdInfo", + "ExpandedDynamicSearchAdInfo", + "ExpandedTextAdInfo", + "HotelAdInfo", + "ImageAdInfo", + "InFeedVideoAdInfo", + "LegacyAppInstallAdInfo", + "LegacyResponsiveDisplayAdInfo", + "LocalAdInfo", + "ResponsiveDisplayAdControlSpec", + "ResponsiveDisplayAdInfo", + "ResponsiveSearchAdInfo", + "ShoppingComparisonListingAdInfo", + "ShoppingProductAdInfo", + "ShoppingSmartAdInfo", + "SmartCampaignAdInfo", + "TextAdInfo", + "TravelAdInfo", + "VideoAdInfo", + "VideoBumperInStreamAdInfo", + "VideoNonSkippableInStreamAdInfo", + "VideoOutstreamAdInfo", + "VideoResponsiveAdInfo", + "VideoTrueViewInStreamAdInfo", + "YouTubeAudioAdInfo", + "AdditionalApplicationInfo", + "AdAssetPolicySummary", + "AssetDisapproved", + "AssetLinkPrimaryStatusDetails", + "BusinessProfileBusinessNameFilter", + "BusinessProfileLocationGroup", + "BusinessProfileLocationSet", + "ChainFilter", + "ChainLocationGroup", + "ChainSet", + "DynamicBusinessProfileLocationGroupFilter", + "LocationSet", + "MapsLocationInfo", + "MapsLocationSet", + "AppDeepLinkAsset", + "BookOnGoogleAsset", + "BusinessMessageAsset", + "BusinessMessageCallToActionInfo", + "BusinessProfileLocation", + "CallAsset", + "CalloutAsset", + "CallToActionAsset", + "DemandGenCarouselCardAsset", + "DynamicCustomAsset", + "DynamicEducationAsset", + "DynamicFlightsAsset", + "DynamicHotelsAndRentalsAsset", + "DynamicJobsAsset", + "DynamicLocalAsset", + "DynamicRealEstateAsset", + "DynamicTravelAsset", + "FacebookMessengerBusinessMessageInfo", + "HotelCalloutAsset", + "HotelPropertyAsset", + "ImageAsset", + "ImageDimension", + "LeadFormAsset", + "LeadFormCustomQuestionField", + "LeadFormDeliveryMethod", + "LeadFormField", + "LeadFormSingleChoiceAnswers", + "LocationAsset", + "MediaBundleAsset", + "MobileAppAsset", + "PageFeedAsset", + "PriceAsset", + "PriceOffering", + "PromotionAsset", + "PromotionBarcodeInfo", + "PromotionQrCodeInfo", + "SitelinkAsset", + "StructuredSnippetAsset", + "TextAsset", + "WebhookDelivery", + "WhatsappBusinessMessageInfo", + "YoutubeVideoAsset", + "YouTubeVideoListAsset", + "ZaloBusinessMessageInfo", + "AssetUsage", + "AudienceInsightsAttribute", + "AudienceInsightsAttributeMetadata", + "AudienceInsightsAttributeMetadataGroup", + "AudienceInsightsCategory", + "AudienceInsightsEntity", + "AudienceInsightsLineup", + "InsightsAudienceAttributeGroup", + "KnowledgeGraphAttributeMetadata", + "LineupAttributeMetadata", + "LocationAttributeMetadata", + "UserInterestAttributeMetadata", + "UserListAttributeMetadata", + "YouTubeChannelAttributeMetadata", + "YouTubeVideoAttributeMetadata", + "AgeDimension", + "AgeSegment", + "AudienceDimension", + "AudienceExclusionDimension", + "AudienceSegment", + "AudienceSegmentDimension", + "CustomAudienceSegment", + "DetailedDemographicSegment", + "ExclusionSegment", + "GenderDimension", + "HouseholdIncomeDimension", + "LifeEventSegment", + "ParentalStatusDimension", + "UserInterestSegment", + "UserListSegment", + "Commission", + "EnhancedCpc", + "FixedCpm", + "FixedCpmTargetFrequencyGoalInfo", + "ManualCpa", + "ManualCpc", + "ManualCpm", + "ManualCpv", + "MaximizeConversions", + "MaximizeConversionValue", + "PercentCpc", + "TargetCpa", + "TargetCpc", + "TargetCpm", + "TargetCpmTargetFrequencyGoal", + "TargetCpv", + "TargetImpressionShare", + "TargetRoas", + "TargetSpend", + "CampaignGoalSettings", + "CampaignReservationQuote", + "ClickLocation", + "Consent", + "ActivityCityInfo", + "ActivityCountryInfo", + "ActivityIdInfo", + "ActivityRatingInfo", + "ActivityStateInfo", + "AddressInfo", + "AdScheduleInfo", + "AgeRangeInfo", + "AppPaymentModelInfo", + "AudienceInfo", + "BrandInfo", + "BrandListInfo", + "CarrierInfo", + "CombinedAudienceInfo", + "ContentLabelInfo", + "CustomAffinityInfo", + "CustomAudienceInfo", + "CustomIntentInfo", + "DeviceInfo", + "ExtendedDemographicInfo", + "GenderInfo", + "GeoPointInfo", + "HotelAdvanceBookingWindowInfo", + "HotelCheckInDateRangeInfo", + "HotelCheckInDayInfo", + "HotelCityInfo", + "HotelClassInfo", + "HotelCountryRegionInfo", + "HotelDateSelectionTypeInfo", + "HotelIdInfo", + "HotelLengthOfStayInfo", + "HotelStateInfo", + "IncomeRangeInfo", + "InteractionTypeInfo", + "IpBlockInfo", + "KeywordInfo", + "KeywordThemeInfo", + "LanguageInfo", + "LifeEventInfo", + "ListingDimensionInfo", + "ListingDimensionPath", + "ListingGroupInfo", + "ListingScopeInfo", + "LocalServiceIdInfo", + "LocationGroupInfo", + "LocationInfo", + "MobileAppCategoryInfo", + "MobileApplicationInfo", + "MobileDeviceInfo", + "NegativeKeywordListInfo", + "OperatingSystemVersionInfo", + "ParentalStatusInfo", + "PlacementInfo", + "PlacementListInfo", + "ProductBrandInfo", + "ProductCategoryInfo", + "ProductChannelExclusivityInfo", + "ProductChannelInfo", + "ProductConditionInfo", + "ProductCustomAttributeInfo", + "ProductGroupingInfo", + "ProductItemIdInfo", + "ProductLabelsInfo", + "ProductLegacyConditionInfo", + "ProductTypeFullInfo", + "ProductTypeInfo", + "ProximityInfo", + "RetailFilter", + "RetailFilterBundle", + "RetailFilterExpression", + "RetailTag", + "SearchThemeInfo", + "TopicInfo", + "UnknownListingDimensionInfo", + "UserInterestInfo", + "UserListInfo", + "VerticalAdsItemGroupRuleInfo", + "VerticalAdsItemGroupRuleListInfo", + "VideoLineupInfo", + "WebpageConditionInfo", + "WebpageInfo", + "WebpageListInfo", + "WebpageSampleInfo", + "YouTubeChannelInfo", + "YouTubeVideoInfo", + "CriterionCategoryAvailability", + "CriterionCategoryChannelAvailability", + "CriterionCategoryLocaleAvailability", + "CustomParameter", + "CustomizerValue", + "DateRange", + "YearMonth", + "YearMonthRange", + "CallFeedItem", + "CalloutFeedItem", + "SitelinkFeedItem", + "Money", + "FinalAppUrl", + "FrequencyCapEntry", + "FrequencyCapKey", + "CustomerLifecycleOptimizationValueSettings", + "GoalSetting", + "ConceptGroup", + "HistoricalMetricsOptions", + "KeywordAnnotations", + "KeywordConcept", + "KeywordPlanAggregateMetricResults", + "KeywordPlanAggregateMetrics", + "KeywordPlanDeviceSearches", + "KeywordPlanHistoricalMetrics", + "MonthlySearchVolume", + "LifecycleGoalValueSettings", + "LocalServicesDocumentReadOnly", + "MetricGoal", + "Metrics", + "SearchVolumeRange", + "CustomerMatchUserListMetadata", + "EventAttribute", + "EventItemAttribute", + "ItemAttribute", + "OfflineUserAddressInfo", + "ShoppingLoyalty", + "StoreAttribute", + "StoreSalesMetadata", + "StoreSalesThirdPartyMetadata", + "TransactionAttribute", + "UserAttribute", + "UserData", + "UserIdentifier", + "PolicyTopicConstraint", + "PolicyTopicEntry", + "PolicyTopicEvidence", + "PolicyValidationParameter", + "PolicyViolationKey", + "PolicySummary", + "RealTimeBiddingSetting", + "AssetInteractionTarget", + "BudgetCampaignAssociationStatus", + "Keyword", + "Segments", + "SkAdNetworkSourceApp", + "BudgetSimulationPoint", + "BudgetSimulationPointList", + "CpcBidSimulationPoint", + "CpcBidSimulationPointList", + "CpvBidSimulationPoint", + "CpvBidSimulationPointList", + "PercentCpcBidSimulationPoint", + "PercentCpcBidSimulationPointList", + "TargetCpaSimulationPoint", + "TargetCpaSimulationPointList", + "TargetImpressionShareSimulationPoint", + "TargetImpressionShareSimulationPointList", + "TargetRoasSimulationPoint", + "TargetRoasSimulationPointList", + "TagSnippet", + "TargetingSetting", + "TargetRestriction", + "TargetRestrictionOperation", + "TextLabel", + "CampaignThirdPartyBrandLiftIntegrationPartner", + "CampaignThirdPartyBrandSafetyIntegrationPartner", + "CampaignThirdPartyIntegrationPartners", + "CampaignThirdPartyReachIntegrationPartner", + "CampaignThirdPartyViewabilityIntegrationPartner", + "CustomerThirdPartyBrandLiftIntegrationPartner", + "CustomerThirdPartyBrandSafetyIntegrationPartner", + "CustomerThirdPartyIntegrationPartners", + "CustomerThirdPartyReachIntegrationPartner", + "CustomerThirdPartyViewabilityIntegrationPartner", + "ThirdPartyIntegrationPartnerData", + "UrlCollection", + "BasicUserListInfo", + "CrmBasedUserListInfo", + "FlexibleRuleOperandInfo", + "FlexibleRuleUserListInfo", + "LogicalUserListInfo", + "LogicalUserListOperandInfo", + "LookalikeUserListInfo", + "RuleBasedUserListInfo", + "SimilarUserListInfo", + "UserListActionInfo", + "UserListDateRuleItemInfo", + "UserListLogicalRuleInfo", + "UserListNumberRuleItemInfo", + "UserListRuleInfo", + "UserListRuleItemGroupInfo", + "UserListRuleItemInfo", + "UserListStringRuleItemInfo", + "Value", +) diff --git a/google/ads/googleads/v24/common/types/ad_asset.py b/google/ads/googleads/v24/common/types/ad_asset.py new file mode 100644 index 000000000..9cfbbe562 --- /dev/null +++ b/google/ads/googleads/v24/common/types/ad_asset.py @@ -0,0 +1,334 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import asset_policy +from google.ads.googleads.v24.enums.types import ( + asset_performance_label as gage_asset_performance_label, +) +from google.ads.googleads.v24.enums.types import served_asset_field_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "AdTextAsset", + "AdImageAsset", + "AdVideoAsset", + "AdVideoAssetInfo", + "AdVideoAssetInventoryPreferences", + "AdVideoAssetLinkFeatureControl", + "AdMediaBundleAsset", + "AdDemandGenCarouselCardAsset", + "AdCallToActionAsset", + "AdAppDeepLinkAsset", + }, +) + + +class AdTextAsset(proto.Message): + r"""A text asset used inside an ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + text (str): + Asset text. + + This field is a member of `oneof`_ ``_text``. + pinned_field (google.ads.googleads.v24.enums.types.ServedAssetFieldTypeEnum.ServedAssetFieldType): + The pinned field of the asset. This restricts + the asset to only serve within this field. + Multiple assets can be pinned to the same field. + An asset that is unpinned or pinned to a + different field will not serve in a field where + some other asset has been pinned. + asset_performance_label (google.ads.googleads.v24.enums.types.AssetPerformanceLabelEnum.AssetPerformanceLabel): + The performance label of this text asset. + policy_summary_info (google.ads.googleads.v24.common.types.AdAssetPolicySummary): + The policy summary of this text asset. + """ + + text: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + pinned_field: ( + served_asset_field_type.ServedAssetFieldTypeEnum.ServedAssetFieldType + ) = proto.Field( + proto.ENUM, + number=2, + enum=served_asset_field_type.ServedAssetFieldTypeEnum.ServedAssetFieldType, + ) + asset_performance_label: ( + gage_asset_performance_label.AssetPerformanceLabelEnum.AssetPerformanceLabel + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_asset_performance_label.AssetPerformanceLabelEnum.AssetPerformanceLabel, + ) + policy_summary_info: asset_policy.AdAssetPolicySummary = proto.Field( + proto.MESSAGE, + number=6, + message=asset_policy.AdAssetPolicySummary, + ) + + +class AdImageAsset(proto.Message): + r"""An image asset used inside an ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + asset (str): + The Asset resource name of this image. + + This field is a member of `oneof`_ ``_asset``. + """ + + asset: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class AdVideoAsset(proto.Message): + r"""A video asset used inside an ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + asset (str): + The Asset resource name of this video. + + This field is a member of `oneof`_ ``_asset``. + ad_video_asset_info (google.ads.googleads.v24.common.types.AdVideoAssetInfo): + Contains info fields for this AdVideoAsset. + + This field is a member of `oneof`_ ``_ad_video_asset_info``. + """ + + asset: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + ad_video_asset_info: "AdVideoAssetInfo" = proto.Field( + proto.MESSAGE, + number=4, + optional=True, + message="AdVideoAssetInfo", + ) + + +class AdVideoAssetInfo(proto.Message): + r"""Contains info fields for AdVideoAssets. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + ad_video_asset_inventory_preferences (google.ads.googleads.v24.common.types.AdVideoAssetInventoryPreferences): + List of inventory preferences for this + AdVideoAsset. This field can only be set for + DiscoveryVideoResponsiveAd. The video assets + with an inventory asset preference set will be + preferred over other videos from the same ad + during serving time. For example, consider this + ad being served for a specific inventory. The + server will first try to match an eligible video + with a matching preference for that inventory. + Videos with no preferences are chosen only when + a video with matching preference and eligible + for a given ad slot can be found. + + This field is a member of `oneof`_ ``_ad_video_asset_inventory_preferences``. + ad_video_asset_feature_control (google.ads.googleads.v24.common.types.AdVideoAssetLinkFeatureControl): + Defines feature controls for this + AdVideoAsset during serving time. For example, + whether YouTube comments should be enabled for + Partnership Ads served on YouTube Shorts. + + This field is a member of `oneof`_ ``_ad_video_asset_feature_control``. + """ + + ad_video_asset_inventory_preferences: "AdVideoAssetInventoryPreferences" = ( + proto.Field( + proto.MESSAGE, + number=1, + optional=True, + message="AdVideoAssetInventoryPreferences", + ) + ) + ad_video_asset_feature_control: "AdVideoAssetLinkFeatureControl" = ( + proto.Field( + proto.MESSAGE, + number=2, + optional=True, + message="AdVideoAssetLinkFeatureControl", + ) + ) + + +class AdVideoAssetInventoryPreferences(proto.Message): + r"""YouTube Video Asset inventory preferences. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + in_feed_preference (bool): + When true, YouTube Video Asset with this + inventory preference will be preferred when + choosing a video to serve In Feed. + + This field is a member of `oneof`_ ``_in_feed_preference``. + in_stream_preference (bool): + When true, YouTube Video Asset with this + inventory preference will be preferred when + choosing a video to serve In Stream. + + This field is a member of `oneof`_ ``_in_stream_preference``. + shorts_preference (bool): + When true, YouTube Video Asset with this + inventory preference will be preferred when + choosing a video to serve on YouTube Shorts. + + This field is a member of `oneof`_ ``_shorts_preference``. + """ + + in_feed_preference: bool = proto.Field( + proto.BOOL, + number=1, + optional=True, + ) + in_stream_preference: bool = proto.Field( + proto.BOOL, + number=2, + optional=True, + ) + shorts_preference: bool = proto.Field( + proto.BOOL, + number=3, + optional=True, + ) + + +class AdVideoAssetLinkFeatureControl(proto.Message): + r"""YouTube Video Asset feature controls. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + allow_youtube_comments (bool): + Defines if YouTube comments should be enabled + for the creative using this YouTube video asset + served on YouTube Shorts. + + This field is a member of `oneof`_ ``_allow_youtube_comments``. + """ + + allow_youtube_comments: bool = proto.Field( + proto.BOOL, + number=1, + optional=True, + ) + + +class AdMediaBundleAsset(proto.Message): + r"""A media bundle asset used inside an ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + asset (str): + The Asset resource name of this media bundle. + + This field is a member of `oneof`_ ``_asset``. + """ + + asset: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class AdDemandGenCarouselCardAsset(proto.Message): + r"""A Demand Gen carousel card asset used inside an ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + asset (str): + The Asset resource name of this discovery + carousel card. + + This field is a member of `oneof`_ ``_asset``. + """ + + asset: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class AdCallToActionAsset(proto.Message): + r"""A call to action asset used inside an ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + asset (str): + The Asset resource name of this call to + action asset. + + This field is a member of `oneof`_ ``_asset``. + """ + + asset: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class AdAppDeepLinkAsset(proto.Message): + r"""An app deep link used inside an ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + asset (str): + The Asset resource name of this app deep link + asset. + + This field is a member of `oneof`_ ``_asset``. + """ + + asset: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/ad_type_infos.py b/google/ads/googleads/v24/common/types/ad_type_infos.py new file mode 100644 index 000000000..e491d5ddf --- /dev/null +++ b/google/ads/googleads/v24/common/types/ad_type_infos.py @@ -0,0 +1,1852 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import ad_asset +from google.ads.googleads.v24.enums.types import display_ad_format_setting +from google.ads.googleads.v24.enums.types import ( + display_upload_product_type as gage_display_upload_product_type, +) +from google.ads.googleads.v24.enums.types import legacy_app_install_ad_app_store +from google.ads.googleads.v24.enums.types import mime_type as gage_mime_type +from google.ads.googleads.v24.enums.types import video_thumbnail + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "TextAdInfo", + "ExpandedTextAdInfo", + "ExpandedDynamicSearchAdInfo", + "HotelAdInfo", + "TravelAdInfo", + "ShoppingSmartAdInfo", + "ShoppingProductAdInfo", + "ShoppingComparisonListingAdInfo", + "ImageAdInfo", + "VideoBumperInStreamAdInfo", + "VideoNonSkippableInStreamAdInfo", + "VideoTrueViewInStreamAdInfo", + "VideoOutstreamAdInfo", + "InFeedVideoAdInfo", + "YouTubeAudioAdInfo", + "VideoAdInfo", + "VideoResponsiveAdInfo", + "ResponsiveSearchAdInfo", + "LegacyResponsiveDisplayAdInfo", + "AppAdInfo", + "AppEngagementAdInfo", + "AppPreRegistrationAdInfo", + "LegacyAppInstallAdInfo", + "ResponsiveDisplayAdInfo", + "LocalAdInfo", + "DisplayUploadAdInfo", + "ResponsiveDisplayAdControlSpec", + "SmartCampaignAdInfo", + "DemandGenMultiAssetAdInfo", + "DemandGenCarouselAdInfo", + "DemandGenVideoResponsiveAdInfo", + "DemandGenProductAdInfo", + }, +) + + +class TextAdInfo(proto.Message): + r"""A text ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + headline (str): + The headline of the ad. + + This field is a member of `oneof`_ ``_headline``. + description1 (str): + The first line of the ad's description. + + This field is a member of `oneof`_ ``_description1``. + description2 (str): + The second line of the ad's description. + + This field is a member of `oneof`_ ``_description2``. + """ + + headline: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + description1: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + description2: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + + +class ExpandedTextAdInfo(proto.Message): + r"""An expanded text ad. Expanded text ads are deprecated. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + headline_part1 (str): + The first part of the ad's headline. + + This field is a member of `oneof`_ ``_headline_part1``. + headline_part2 (str): + The second part of the ad's headline. + + This field is a member of `oneof`_ ``_headline_part2``. + headline_part3 (str): + The third part of the ad's headline. + + This field is a member of `oneof`_ ``_headline_part3``. + description (str): + The description of the ad. + + This field is a member of `oneof`_ ``_description``. + description2 (str): + The second description of the ad. + + This field is a member of `oneof`_ ``_description2``. + path1 (str): + The text that can appear alongside the ad's + displayed URL. + + This field is a member of `oneof`_ ``_path1``. + path2 (str): + Additional text that can appear alongside the + ad's displayed URL. + + This field is a member of `oneof`_ ``_path2``. + """ + + headline_part1: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + headline_part2: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + headline_part3: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + description: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + description2: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + path1: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + path2: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + + +class ExpandedDynamicSearchAdInfo(proto.Message): + r"""An expanded dynamic search ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + description (str): + The description of the ad. + + This field is a member of `oneof`_ ``_description``. + description2 (str): + The second description of the ad. + + This field is a member of `oneof`_ ``_description2``. + """ + + description: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + description2: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + + +class HotelAdInfo(proto.Message): + r"""A hotel ad.""" + + +class TravelAdInfo(proto.Message): + r"""A travel ad.""" + + +class ShoppingSmartAdInfo(proto.Message): + r"""A Smart Shopping ad.""" + + +class ShoppingProductAdInfo(proto.Message): + r"""A standard Shopping ad.""" + + +class ShoppingComparisonListingAdInfo(proto.Message): + r"""A Shopping Comparison Listing ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + headline (str): + Headline of the ad. This field is required. + Allowed length is between 25 and 45 characters. + + This field is a member of `oneof`_ ``_headline``. + """ + + headline: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class ImageAdInfo(proto.Message): + r"""An image ad. + + 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: + pixel_width (int): + Width in pixels of the full size image. + + This field is a member of `oneof`_ ``_pixel_width``. + pixel_height (int): + Height in pixels of the full size image. + + This field is a member of `oneof`_ ``_pixel_height``. + image_url (str): + URL of the full size image. + + This field is a member of `oneof`_ ``_image_url``. + preview_pixel_width (int): + Width in pixels of the preview size image. + + This field is a member of `oneof`_ ``_preview_pixel_width``. + preview_pixel_height (int): + Height in pixels of the preview size image. + + This field is a member of `oneof`_ ``_preview_pixel_height``. + preview_image_url (str): + URL of the preview size image. + + This field is a member of `oneof`_ ``_preview_image_url``. + mime_type (google.ads.googleads.v24.enums.types.MimeTypeEnum.MimeType): + The mime type of the image. + name (str): + The name of the image. If the image was + created from a MediaFile, this is the + MediaFile's name. If the image was created from + bytes, this is empty. + + This field is a member of `oneof`_ ``_name``. + image_asset (google.ads.googleads.v24.common.types.AdImageAsset): + The image assets used for the ad. + + This field is a member of `oneof`_ ``image``. + data (bytes): + Raw image data as bytes. + + This field is a member of `oneof`_ ``image``. + ad_id_to_copy_image_from (int): + An ad ID to copy the image from. + + This field is a member of `oneof`_ ``image``. + """ + + pixel_width: int = proto.Field( + proto.INT64, + number=15, + optional=True, + ) + pixel_height: int = proto.Field( + proto.INT64, + number=16, + optional=True, + ) + image_url: str = proto.Field( + proto.STRING, + number=17, + optional=True, + ) + preview_pixel_width: int = proto.Field( + proto.INT64, + number=18, + optional=True, + ) + preview_pixel_height: int = proto.Field( + proto.INT64, + number=19, + optional=True, + ) + preview_image_url: str = proto.Field( + proto.STRING, + number=20, + optional=True, + ) + mime_type: gage_mime_type.MimeTypeEnum.MimeType = proto.Field( + proto.ENUM, + number=10, + enum=gage_mime_type.MimeTypeEnum.MimeType, + ) + name: str = proto.Field( + proto.STRING, + number=21, + optional=True, + ) + image_asset: ad_asset.AdImageAsset = proto.Field( + proto.MESSAGE, + number=22, + oneof="image", + message=ad_asset.AdImageAsset, + ) + data: bytes = proto.Field( + proto.BYTES, + number=13, + oneof="image", + ) + ad_id_to_copy_image_from: int = proto.Field( + proto.INT64, + number=14, + oneof="image", + ) + + +class VideoBumperInStreamAdInfo(proto.Message): + r"""Representation of video bumper in-stream ad format (very + short in-stream non-skippable video ad). + + Attributes: + companion_banner (google.ads.googleads.v24.common.types.AdImageAsset): + The image assets of the companion banner used + with the ad. + action_button_label (str): + Label on the "Call To Action" button taking + the user to the video ad's final URL. + action_headline (str): + Additional text displayed with the CTA + (call-to-action) button to give context and + encourage clicking on the button. + """ + + companion_banner: ad_asset.AdImageAsset = proto.Field( + proto.MESSAGE, + number=3, + message=ad_asset.AdImageAsset, + ) + action_button_label: str = proto.Field( + proto.STRING, + number=4, + ) + action_headline: str = proto.Field( + proto.STRING, + number=5, + ) + + +class VideoNonSkippableInStreamAdInfo(proto.Message): + r"""Representation of video non-skippable in-stream ad format (15 + second in-stream non-skippable video ad). + + Attributes: + companion_banner (google.ads.googleads.v24.common.types.AdImageAsset): + The image assets of the companion banner used + with the ad. + action_button_label (str): + Label on the "Call To Action" button taking + the user to the video ad's final URL. + action_headline (str): + Additional text displayed with the "Call To + Action" button to give context and encourage + clicking on the button. + """ + + companion_banner: ad_asset.AdImageAsset = proto.Field( + proto.MESSAGE, + number=5, + message=ad_asset.AdImageAsset, + ) + action_button_label: str = proto.Field( + proto.STRING, + number=3, + ) + action_headline: str = proto.Field( + proto.STRING, + number=4, + ) + + +class VideoTrueViewInStreamAdInfo(proto.Message): + r"""Representation of video TrueView in-stream ad format (ad + shown during video playback, often at beginning, which displays + a skip button a few seconds into the video). + + Attributes: + action_button_label (str): + Label on the CTA (call-to-action) button + taking the user to the video ad's final URL. + Required for TrueView for action campaigns, + optional otherwise. + action_headline (str): + Additional text displayed with the CTA + (call-to-action) button to give context and + encourage clicking on the button. + companion_banner (google.ads.googleads.v24.common.types.AdImageAsset): + The image assets of the companion banner used + with the ad. + """ + + action_button_label: str = proto.Field( + proto.STRING, + number=4, + ) + action_headline: str = proto.Field( + proto.STRING, + number=5, + ) + companion_banner: ad_asset.AdImageAsset = proto.Field( + proto.MESSAGE, + number=7, + message=ad_asset.AdImageAsset, + ) + + +class VideoOutstreamAdInfo(proto.Message): + r"""Representation of video out-stream ad format (ad shown + alongside a feed with automatic playback, without sound). + + Attributes: + headline (str): + The headline of the ad. + description (str): + The description line. + """ + + headline: str = proto.Field( + proto.STRING, + number=3, + ) + description: str = proto.Field( + proto.STRING, + number=4, + ) + + +class InFeedVideoAdInfo(proto.Message): + r"""Representation of In-feed video ad format. + + Attributes: + headline (str): + The headline of the ad. + description1 (str): + First text line for the ad. + description2 (str): + Second text line for the ad. + thumbnail (google.ads.googleads.v24.enums.types.VideoThumbnailEnum.VideoThumbnail): + Video thumbnail image to use. + """ + + headline: str = proto.Field( + proto.STRING, + number=1, + ) + description1: str = proto.Field( + proto.STRING, + number=2, + ) + description2: str = proto.Field( + proto.STRING, + number=3, + ) + thumbnail: video_thumbnail.VideoThumbnailEnum.VideoThumbnail = proto.Field( + proto.ENUM, + number=4, + enum=video_thumbnail.VideoThumbnailEnum.VideoThumbnail, + ) + + +class YouTubeAudioAdInfo(proto.Message): + r"""Representation of YouTube Audio ad format.""" + + +class VideoAdInfo(proto.Message): + r"""A video ad. + + 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: + video (google.ads.googleads.v24.common.types.AdVideoAsset): + The YouTube video assets used for the ad. + in_stream (google.ads.googleads.v24.common.types.VideoTrueViewInStreamAdInfo): + Video TrueView in-stream ad format. + + This field is a member of `oneof`_ ``format``. + bumper (google.ads.googleads.v24.common.types.VideoBumperInStreamAdInfo): + Video bumper in-stream ad format. + + This field is a member of `oneof`_ ``format``. + out_stream (google.ads.googleads.v24.common.types.VideoOutstreamAdInfo): + Video out-stream ad format. + + This field is a member of `oneof`_ ``format``. + non_skippable (google.ads.googleads.v24.common.types.VideoNonSkippableInStreamAdInfo): + Video non-skippable in-stream ad format. + + This field is a member of `oneof`_ ``format``. + in_feed (google.ads.googleads.v24.common.types.InFeedVideoAdInfo): + In-feed video ad format. + + This field is a member of `oneof`_ ``format``. + audio (google.ads.googleads.v24.common.types.YouTubeAudioAdInfo): + YouTube Audio ad format. + + This field is a member of `oneof`_ ``format``. + """ + + video: ad_asset.AdVideoAsset = proto.Field( + proto.MESSAGE, + number=8, + message=ad_asset.AdVideoAsset, + ) + in_stream: "VideoTrueViewInStreamAdInfo" = proto.Field( + proto.MESSAGE, + number=2, + oneof="format", + message="VideoTrueViewInStreamAdInfo", + ) + bumper: "VideoBumperInStreamAdInfo" = proto.Field( + proto.MESSAGE, + number=3, + oneof="format", + message="VideoBumperInStreamAdInfo", + ) + out_stream: "VideoOutstreamAdInfo" = proto.Field( + proto.MESSAGE, + number=4, + oneof="format", + message="VideoOutstreamAdInfo", + ) + non_skippable: "VideoNonSkippableInStreamAdInfo" = proto.Field( + proto.MESSAGE, + number=5, + oneof="format", + message="VideoNonSkippableInStreamAdInfo", + ) + in_feed: "InFeedVideoAdInfo" = proto.Field( + proto.MESSAGE, + number=9, + oneof="format", + message="InFeedVideoAdInfo", + ) + audio: "YouTubeAudioAdInfo" = proto.Field( + proto.MESSAGE, + number=10, + oneof="format", + message="YouTubeAudioAdInfo", + ) + + +class VideoResponsiveAdInfo(proto.Message): + r"""A video responsive ad. + + Attributes: + headlines (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets used for the short + headline. Currently, only a single value for the + short headline is supported. + long_headlines (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets used for the long + headline. Currently, only a single value for the + long headline is supported. + descriptions (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets used for the description. + Currently, only a single value for the + description is supported. + call_to_actions (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets used for the button, for + example, the "Call To Action" button. Currently, + only a single value for the button is supported. + videos (MutableSequence[google.ads.googleads.v24.common.types.AdVideoAsset]): + Required. List of YouTube video assets used + for the ad. Currently, only a single value for + the YouTube video asset is supported. + business_name (google.ads.googleads.v24.common.types.AdTextAsset): + Required. Advertiser/brand name. Maximum + display width is 25 characters. + logo_images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + Required. Logo image to be used in the ad. + The minimum size is 128x128 and the aspect ratio + must be 1:1(+-1%). + companion_banners (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + List of image assets used for the companion + banner. Currently, only a single value for the + companion banner asset is supported. + breadcrumb1 (str): + First part of text that appears in the ad + with the displayed URL. + breadcrumb2 (str): + Second part of text that appears in the ad + with the displayed URL. + """ + + headlines: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=ad_asset.AdTextAsset, + ) + long_headlines: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=ad_asset.AdTextAsset, + ) + descriptions: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=ad_asset.AdTextAsset, + ) + call_to_actions: MutableSequence[ad_asset.AdTextAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=4, + message=ad_asset.AdTextAsset, + ) + ) + videos: MutableSequence[ad_asset.AdVideoAsset] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message=ad_asset.AdVideoAsset, + ) + business_name: ad_asset.AdTextAsset = proto.Field( + proto.MESSAGE, + number=9, + message=ad_asset.AdTextAsset, + ) + logo_images: MutableSequence[ad_asset.AdImageAsset] = proto.RepeatedField( + proto.MESSAGE, + number=10, + message=ad_asset.AdImageAsset, + ) + companion_banners: MutableSequence[ad_asset.AdImageAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=6, + message=ad_asset.AdImageAsset, + ) + ) + breadcrumb1: str = proto.Field( + proto.STRING, + number=7, + ) + breadcrumb2: str = proto.Field( + proto.STRING, + number=8, + ) + + +class ResponsiveSearchAdInfo(proto.Message): + r"""A responsive search ad. + + Responsive search ads let you create an ad that adapts to show + more text, and more relevant messages, to your customers. Enter + multiple headlines and descriptions when creating a responsive + search ad, and over time, Google Ads will automatically test + different combinations and learn which combinations perform + best. By adapting your ad's content to more closely match + potential customers' search terms, responsive search ads may + improve your campaign's performance. + + More information at + https://support.google.com/google-ads/answer/7684791 + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + headlines (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets for headlines. When the + ad serves the headlines will be selected from + this list. + descriptions (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets for descriptions. When + the ad serves the descriptions will be selected + from this list. + path1 (str): + First part of text that can be appended to + the URL in the ad. + + This field is a member of `oneof`_ ``_path1``. + path2 (str): + Second part of text that can be appended to the URL in the + ad. This field can only be set when ``path1`` is also set. + + This field is a member of `oneof`_ ``_path2``. + """ + + headlines: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=ad_asset.AdTextAsset, + ) + descriptions: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=ad_asset.AdTextAsset, + ) + path1: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + path2: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + + +class LegacyResponsiveDisplayAdInfo(proto.Message): + r"""A legacy responsive display ad. Ads of this type are labeled + 'Responsive ads' in the Google Ads UI. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + short_headline (str): + The short version of the ad's headline. + + This field is a member of `oneof`_ ``_short_headline``. + long_headline (str): + The long version of the ad's headline. + + This field is a member of `oneof`_ ``_long_headline``. + description (str): + The description of the ad. + + This field is a member of `oneof`_ ``_description``. + business_name (str): + The business name in the ad. + + This field is a member of `oneof`_ ``_business_name``. + allow_flexible_color (bool): + Advertiser's consent to allow flexible color. When true, the + ad may be served with different color if necessary. When + false, the ad will be served with the specified colors or a + neutral color. The default value is ``true``. Must be true + if ``main_color`` and ``accent_color`` are not set. + + This field is a member of `oneof`_ ``_allow_flexible_color``. + accent_color (str): + The accent color of the ad in hexadecimal, for example, + #ffffff for white. If one of ``main_color`` and + ``accent_color`` is set, the other is required as well. + + This field is a member of `oneof`_ ``_accent_color``. + main_color (str): + The main color of the ad in hexadecimal, for example, + #ffffff for white. If one of ``main_color`` and + ``accent_color`` is set, the other is required as well. + + This field is a member of `oneof`_ ``_main_color``. + call_to_action_text (str): + The call-to-action text for the ad. + + This field is a member of `oneof`_ ``_call_to_action_text``. + logo_image (str): + The MediaFile resource name of the logo image + used in the ad. + + This field is a member of `oneof`_ ``_logo_image``. + square_logo_image (str): + The MediaFile resource name of the square + logo image used in the ad. + + This field is a member of `oneof`_ ``_square_logo_image``. + marketing_image (str): + The MediaFile resource name of the marketing + image used in the ad. + + This field is a member of `oneof`_ ``_marketing_image``. + square_marketing_image (str): + The MediaFile resource name of the square + marketing image used in the ad. + + This field is a member of `oneof`_ ``_square_marketing_image``. + format_setting (google.ads.googleads.v24.enums.types.DisplayAdFormatSettingEnum.DisplayAdFormatSetting): + Specifies which format the ad will be served in. Default is + ALL_FORMATS. + price_prefix (str): + Prefix before price. For example, 'as low + as'. + + This field is a member of `oneof`_ ``_price_prefix``. + promo_text (str): + Promotion text used for dynamic formats of + responsive ads. For example 'Free two-day + shipping'. + + This field is a member of `oneof`_ ``_promo_text``. + """ + + short_headline: str = proto.Field( + proto.STRING, + number=16, + optional=True, + ) + long_headline: str = proto.Field( + proto.STRING, + number=17, + optional=True, + ) + description: str = proto.Field( + proto.STRING, + number=18, + optional=True, + ) + business_name: str = proto.Field( + proto.STRING, + number=19, + optional=True, + ) + allow_flexible_color: bool = proto.Field( + proto.BOOL, + number=20, + optional=True, + ) + accent_color: str = proto.Field( + proto.STRING, + number=21, + optional=True, + ) + main_color: str = proto.Field( + proto.STRING, + number=22, + optional=True, + ) + call_to_action_text: str = proto.Field( + proto.STRING, + number=23, + optional=True, + ) + logo_image: str = proto.Field( + proto.STRING, + number=24, + optional=True, + ) + square_logo_image: str = proto.Field( + proto.STRING, + number=25, + optional=True, + ) + marketing_image: str = proto.Field( + proto.STRING, + number=26, + optional=True, + ) + square_marketing_image: str = proto.Field( + proto.STRING, + number=27, + optional=True, + ) + format_setting: ( + display_ad_format_setting.DisplayAdFormatSettingEnum.DisplayAdFormatSetting + ) = proto.Field( + proto.ENUM, + number=13, + enum=display_ad_format_setting.DisplayAdFormatSettingEnum.DisplayAdFormatSetting, + ) + price_prefix: str = proto.Field( + proto.STRING, + number=28, + optional=True, + ) + promo_text: str = proto.Field( + proto.STRING, + number=29, + optional=True, + ) + + +class AppAdInfo(proto.Message): + r"""An app ad. + + Attributes: + mandatory_ad_text (google.ads.googleads.v24.common.types.AdTextAsset): + Mandatory ad text. + headlines (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets for headlines. When the + ad serves the headlines will be selected from + this list. + descriptions (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets for descriptions. When + the ad serves the descriptions will be selected + from this list. + images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + List of image assets that may be displayed + with the ad. + youtube_videos (MutableSequence[google.ads.googleads.v24.common.types.AdVideoAsset]): + List of YouTube video assets that may be + displayed with the ad. + html5_media_bundles (MutableSequence[google.ads.googleads.v24.common.types.AdMediaBundleAsset]): + List of media bundle assets that may be used + with the ad. + app_deep_link (google.ads.googleads.v24.common.types.AdAppDeepLinkAsset): + An app deep link asset that may be used with + the ad. + """ + + mandatory_ad_text: ad_asset.AdTextAsset = proto.Field( + proto.MESSAGE, + number=1, + message=ad_asset.AdTextAsset, + ) + headlines: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=ad_asset.AdTextAsset, + ) + descriptions: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=ad_asset.AdTextAsset, + ) + images: MutableSequence[ad_asset.AdImageAsset] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=ad_asset.AdImageAsset, + ) + youtube_videos: MutableSequence[ad_asset.AdVideoAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=5, + message=ad_asset.AdVideoAsset, + ) + ) + html5_media_bundles: MutableSequence[ad_asset.AdMediaBundleAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=6, + message=ad_asset.AdMediaBundleAsset, + ) + ) + app_deep_link: ad_asset.AdAppDeepLinkAsset = proto.Field( + proto.MESSAGE, + number=7, + message=ad_asset.AdAppDeepLinkAsset, + ) + + +class AppEngagementAdInfo(proto.Message): + r"""App engagement ads allow you to write text encouraging a + specific action in the app, like checking in, making a purchase, + or booking a flight. They allow you to send users to a specific + part of your app where they can find what they're looking for + easier and faster. + + Attributes: + headlines (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets for headlines. When the + ad serves the headlines will be selected from + this list. + descriptions (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets for descriptions. When + the ad serves the descriptions will be selected + from this list. + images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + List of image assets that may be displayed + with the ad. + videos (MutableSequence[google.ads.googleads.v24.common.types.AdVideoAsset]): + List of video assets that may be displayed + with the ad. + """ + + headlines: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=ad_asset.AdTextAsset, + ) + descriptions: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=ad_asset.AdTextAsset, + ) + images: MutableSequence[ad_asset.AdImageAsset] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=ad_asset.AdImageAsset, + ) + videos: MutableSequence[ad_asset.AdVideoAsset] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=ad_asset.AdVideoAsset, + ) + + +class AppPreRegistrationAdInfo(proto.Message): + r"""App pre-registration ads link to your app or game listing on + Google Play, and can run on Google Play, on YouTube (in-stream + only), and within other apps and mobile websites on the Display + Network. It will help capture people's interest in your app or + game and generate an early install base for your app or game + before a launch. + + Attributes: + headlines (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets for headlines. When the + ad serves the headlines will be selected from + this list. + descriptions (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets for descriptions. When + the ad serves the descriptions will be selected + from this list. + images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + List of image asset IDs whose images may be + displayed with the ad. + youtube_videos (MutableSequence[google.ads.googleads.v24.common.types.AdVideoAsset]): + List of YouTube video asset IDs whose videos + may be displayed with the ad. + """ + + headlines: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=ad_asset.AdTextAsset, + ) + descriptions: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=ad_asset.AdTextAsset, + ) + images: MutableSequence[ad_asset.AdImageAsset] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=ad_asset.AdImageAsset, + ) + youtube_videos: MutableSequence[ad_asset.AdVideoAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=4, + message=ad_asset.AdVideoAsset, + ) + ) + + +class LegacyAppInstallAdInfo(proto.Message): + r"""A legacy app install ad that only can be used by a few select + customers. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + app_id (str): + The ID of the mobile app. + + This field is a member of `oneof`_ ``_app_id``. + app_store (google.ads.googleads.v24.enums.types.LegacyAppInstallAdAppStoreEnum.LegacyAppInstallAdAppStore): + The app store the mobile app is available in. + headline (str): + The headline of the ad. + + This field is a member of `oneof`_ ``_headline``. + description1 (str): + The first description line of the ad. + + This field is a member of `oneof`_ ``_description1``. + description2 (str): + The second description line of the ad. + + This field is a member of `oneof`_ ``_description2``. + """ + + app_id: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + app_store: ( + legacy_app_install_ad_app_store.LegacyAppInstallAdAppStoreEnum.LegacyAppInstallAdAppStore + ) = proto.Field( + proto.ENUM, + number=2, + enum=legacy_app_install_ad_app_store.LegacyAppInstallAdAppStoreEnum.LegacyAppInstallAdAppStore, + ) + headline: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + description1: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + description2: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + + +class ResponsiveDisplayAdInfo(proto.Message): + r"""A responsive display ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + marketing_images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + Marketing images to be used in the ad. Valid image types are + GIF, JPEG, and PNG. The minimum size is 600x314 and the + aspect ratio must be 1.91:1 (+-1%). At least one + ``marketing_image`` is required. Combined with + ``square_marketing_images``, the maximum is 15. + square_marketing_images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + Square marketing images to be used in the ad. Valid image + types are GIF, JPEG, and PNG. The minimum size is 300x300 + and the aspect ratio must be 1:1 (+-1%). At least one square + ``marketing_image`` is required. Combined with + ``marketing_images``, the maximum is 15. + logo_images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + Logo images to be used in the ad. Valid image types are GIF, + JPEG, and PNG. The minimum size is 512x128 and the aspect + ratio must be 4:1 (+-1%). Combined with + ``square_logo_images``, the maximum is 5. + square_logo_images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + Square logo images to be used in the ad. Valid image types + are GIF, JPEG, and PNG. The minimum size is 128x128 and the + aspect ratio must be 1:1 (+-1%). Combined with + ``logo_images``, the maximum is 5. + headlines (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + Short format headlines for the ad. The + maximum length is 30 characters. At least 1 and + max 5 headlines can be specified. + long_headline (google.ads.googleads.v24.common.types.AdTextAsset): + A required long format headline. The maximum + length is 90 characters. + descriptions (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + Descriptive texts for the ad. The maximum + length is 90 characters. At least 1 and max 5 + headlines can be specified. + youtube_videos (MutableSequence[google.ads.googleads.v24.common.types.AdVideoAsset]): + Optional YouTube videos for the ad. A maximum + of 5 videos can be specified. + business_name (str): + The advertiser/brand name. Maximum display + width is 25. + + This field is a member of `oneof`_ ``_business_name``. + main_color (str): + The main color of the ad in hexadecimal, for example, + #ffffff for white. If one of ``main_color`` and + ``accent_color`` is set, the other is required as well. + + This field is a member of `oneof`_ ``_main_color``. + accent_color (str): + The accent color of the ad in hexadecimal, for example, + #ffffff for white. If one of ``main_color`` and + ``accent_color`` is set, the other is required as well. + + This field is a member of `oneof`_ ``_accent_color``. + allow_flexible_color (bool): + Advertiser's consent to allow flexible color. When true, the + ad may be served with different color if necessary. When + false, the ad will be served with the specified colors or a + neutral color. The default value is ``true``. Must be true + if ``main_color`` and ``accent_color`` are not set. + + This field is a member of `oneof`_ ``_allow_flexible_color``. + call_to_action_text (str): + The call-to-action text for the ad. Maximum + display width is 30. + + This field is a member of `oneof`_ ``_call_to_action_text``. + price_prefix (str): + Prefix before price. For example, 'as low + as'. + + This field is a member of `oneof`_ ``_price_prefix``. + promo_text (str): + Promotion text used for dynamic formats of + responsive ads. For example 'Free two-day + shipping'. + + This field is a member of `oneof`_ ``_promo_text``. + format_setting (google.ads.googleads.v24.enums.types.DisplayAdFormatSettingEnum.DisplayAdFormatSetting): + Specifies which format the ad will be served in. Default is + ALL_FORMATS. + control_spec (google.ads.googleads.v24.common.types.ResponsiveDisplayAdControlSpec): + Specification for various creative controls. + """ + + marketing_images: MutableSequence[ad_asset.AdImageAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=ad_asset.AdImageAsset, + ) + ) + square_marketing_images: MutableSequence[ad_asset.AdImageAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message=ad_asset.AdImageAsset, + ) + ) + logo_images: MutableSequence[ad_asset.AdImageAsset] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=ad_asset.AdImageAsset, + ) + square_logo_images: MutableSequence[ad_asset.AdImageAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=4, + message=ad_asset.AdImageAsset, + ) + ) + headlines: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message=ad_asset.AdTextAsset, + ) + long_headline: ad_asset.AdTextAsset = proto.Field( + proto.MESSAGE, + number=6, + message=ad_asset.AdTextAsset, + ) + descriptions: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=7, + message=ad_asset.AdTextAsset, + ) + youtube_videos: MutableSequence[ad_asset.AdVideoAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=8, + message=ad_asset.AdVideoAsset, + ) + ) + business_name: str = proto.Field( + proto.STRING, + number=17, + optional=True, + ) + main_color: str = proto.Field( + proto.STRING, + number=18, + optional=True, + ) + accent_color: str = proto.Field( + proto.STRING, + number=19, + optional=True, + ) + allow_flexible_color: bool = proto.Field( + proto.BOOL, + number=20, + optional=True, + ) + call_to_action_text: str = proto.Field( + proto.STRING, + number=21, + optional=True, + ) + price_prefix: str = proto.Field( + proto.STRING, + number=22, + optional=True, + ) + promo_text: str = proto.Field( + proto.STRING, + number=23, + optional=True, + ) + format_setting: ( + display_ad_format_setting.DisplayAdFormatSettingEnum.DisplayAdFormatSetting + ) = proto.Field( + proto.ENUM, + number=16, + enum=display_ad_format_setting.DisplayAdFormatSettingEnum.DisplayAdFormatSetting, + ) + control_spec: "ResponsiveDisplayAdControlSpec" = proto.Field( + proto.MESSAGE, + number=24, + message="ResponsiveDisplayAdControlSpec", + ) + + +class LocalAdInfo(proto.Message): + r"""A local ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + headlines (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets for headlines. When the + ad serves the headlines will be selected from + this list. At least 1 and at most 5 headlines + must be specified. + descriptions (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets for descriptions. When + the ad serves the descriptions will be selected + from this list. At least 1 and at most 5 + descriptions must be specified. + call_to_actions (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets for call-to-actions. When + the ad serves the call-to-actions will be + selected from this list. At least 1 and at most + 5 call-to-actions must be specified. + marketing_images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + List of marketing image assets that may be + displayed with the ad. The images must be + 314x600 pixels or 320x320 pixels. At least 1 and + at most 20 image assets must be specified. + logo_images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + List of logo image assets that may be + displayed with the ad. The images must be + 128x128 pixels and not larger than 120KB. At + least 1 and at most 5 image assets must be + specified. + videos (MutableSequence[google.ads.googleads.v24.common.types.AdVideoAsset]): + List of YouTube video assets that may be + displayed with the ad. At least 1 and at most 20 + video assets must be specified. + path1 (str): + First part of optional text that can be + appended to the URL in the ad. + + This field is a member of `oneof`_ ``_path1``. + path2 (str): + Second part of optional text that can be appended to the URL + in the ad. This field can only be set when ``path1`` is also + set. + + This field is a member of `oneof`_ ``_path2``. + """ + + headlines: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=ad_asset.AdTextAsset, + ) + descriptions: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=ad_asset.AdTextAsset, + ) + call_to_actions: MutableSequence[ad_asset.AdTextAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=3, + message=ad_asset.AdTextAsset, + ) + ) + marketing_images: MutableSequence[ad_asset.AdImageAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=4, + message=ad_asset.AdImageAsset, + ) + ) + logo_images: MutableSequence[ad_asset.AdImageAsset] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message=ad_asset.AdImageAsset, + ) + videos: MutableSequence[ad_asset.AdVideoAsset] = proto.RepeatedField( + proto.MESSAGE, + number=6, + message=ad_asset.AdVideoAsset, + ) + path1: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + path2: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + + +class DisplayUploadAdInfo(proto.Message): + r"""A generic type of display ad. The exact ad format is controlled by + the ``display_upload_product_type`` field, which determines what + kinds of data need to be included with the ad. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + display_upload_product_type (google.ads.googleads.v24.enums.types.DisplayUploadProductTypeEnum.DisplayUploadProductType): + The product type of this ad. See comments on + the enum for details. + media_bundle (google.ads.googleads.v24.common.types.AdMediaBundleAsset): + A media bundle asset to be used in the ad. For information + about the media bundle for HTML5_UPLOAD_AD, see + https://support.google.com/google-ads/answer/1722096 Media + bundles that are part of dynamic product types use a special + format that needs to be created through the Google Web + Designer. See + https://support.google.com/webdesigner/answer/7543898 for + more information. + + This field is a member of `oneof`_ ``media_asset``. + """ + + display_upload_product_type: ( + gage_display_upload_product_type.DisplayUploadProductTypeEnum.DisplayUploadProductType + ) = proto.Field( + proto.ENUM, + number=1, + enum=gage_display_upload_product_type.DisplayUploadProductTypeEnum.DisplayUploadProductType, + ) + media_bundle: ad_asset.AdMediaBundleAsset = proto.Field( + proto.MESSAGE, + number=2, + oneof="media_asset", + message=ad_asset.AdMediaBundleAsset, + ) + + +class ResponsiveDisplayAdControlSpec(proto.Message): + r"""Specification for various creative controls for a responsive + display ad. + + Attributes: + enable_asset_enhancements (bool): + Whether the advertiser has opted into the + asset enhancements feature. + enable_autogen_video (bool): + Whether the advertiser has opted into + auto-gen video feature. + """ + + enable_asset_enhancements: bool = proto.Field( + proto.BOOL, + number=1, + ) + enable_autogen_video: bool = proto.Field( + proto.BOOL, + number=2, + ) + + +class SmartCampaignAdInfo(proto.Message): + r"""A Smart campaign ad. + + Attributes: + headlines (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets, each of which + corresponds to a headline when the ad serves. + This list consists of a minimum of 3 and up to + 15 text assets. + descriptions (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets, each of which + corresponds to a description when the ad serves. + This list consists of a minimum of 2 and up to 4 + text assets. + """ + + headlines: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=ad_asset.AdTextAsset, + ) + descriptions: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=ad_asset.AdTextAsset, + ) + + +class DemandGenMultiAssetAdInfo(proto.Message): + r"""A Demand Gen multi asset ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + marketing_images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + Marketing image assets to be used in the ad. Valid image + types are GIF, JPEG, and PNG. The minimum size is 600x314 + and the aspect ratio must be 1.91:1 (+-1%). Required if + square_marketing_images is not present. Combined with + ``square_marketing_images``, ``portrait_marketing_images``, + and ``tall_portrait_marketing_images`` the maximum is 20. + square_marketing_images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + Square marketing image assets to be used in the ad. Valid + image types are GIF, JPEG, and PNG. The minimum size is + 300x300 and the aspect ratio must be 1:1 (+-1%). Required if + marketing_images is not present. Combined with + ``marketing_images``, ``portrait_marketing_images``, and + ``tall_portrait_marketing_images`` the maximum is 20. + portrait_marketing_images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + Portrait marketing image assets to be used in the ad. Valid + image types are GIF, JPEG, and PNG. The minimum size is + 480x600 and the aspect ratio must be 4:5 (+-1%). Combined + with ``marketing_images``, ``square_marketing_images``, and + ``tall_portrait_marketing_images`` the maximum is 20. + tall_portrait_marketing_images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + Tall portrait marketing image assets to be used in the ad. + Valid image types are GIF, JPEG, and PNG. The minimum size + is 600x1067 and the aspect ratio must be 9:16 (+-1%). + Combined with ``marketing_images``, + ``square_marketing_images``, and + ``portrait_marketing_images``, the maximum is 20. + logo_images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + Logo image assets to be used in the ad. Valid + image types are GIF, JPEG, and PNG. The minimum + size is 128x128 and the aspect ratio must be 1:1 + (+-1%). At least 1 and max 5 logo images can be + specified. + headlines (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + Headline text asset of the ad. Maximum + display width is 30. At least 1 and max 5 + headlines can be specified. + descriptions (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + The descriptive text of the ad. Maximum + display width is 90. At least 1 and max 5 + descriptions can be specified. + business_name (str): + The Advertiser/brand name. Maximum display + width is 25. Required. + + This field is a member of `oneof`_ ``_business_name``. + call_to_action_text (str): + Call to action text. + + This field is a member of `oneof`_ ``_call_to_action_text``. + """ + + marketing_images: MutableSequence[ad_asset.AdImageAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=ad_asset.AdImageAsset, + ) + ) + square_marketing_images: MutableSequence[ad_asset.AdImageAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message=ad_asset.AdImageAsset, + ) + ) + portrait_marketing_images: MutableSequence[ad_asset.AdImageAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=3, + message=ad_asset.AdImageAsset, + ) + ) + tall_portrait_marketing_images: MutableSequence[ad_asset.AdImageAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=10, + message=ad_asset.AdImageAsset, + ) + ) + logo_images: MutableSequence[ad_asset.AdImageAsset] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=ad_asset.AdImageAsset, + ) + headlines: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message=ad_asset.AdTextAsset, + ) + descriptions: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=6, + message=ad_asset.AdTextAsset, + ) + business_name: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + call_to_action_text: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + + +class DemandGenCarouselAdInfo(proto.Message): + r"""A Demand Gen carousel ad. + + Attributes: + business_name (str): + Required. The Advertiser/brand name. + logo_image (google.ads.googleads.v24.common.types.AdImageAsset): + Required. Logo image to be used in the ad. + The minimum size is 128x128 and the aspect ratio + must be 1:1 (+-1%). + headline (google.ads.googleads.v24.common.types.AdTextAsset): + Required. Headline of the ad. + description (google.ads.googleads.v24.common.types.AdTextAsset): + Required. The descriptive text of the ad. + call_to_action_text (str): + Call to action text. + carousel_cards (MutableSequence[google.ads.googleads.v24.common.types.AdDemandGenCarouselCardAsset]): + Required. Carousel cards that will display + with the ad. Min 2 max 10. + """ + + business_name: str = proto.Field( + proto.STRING, + number=1, + ) + logo_image: ad_asset.AdImageAsset = proto.Field( + proto.MESSAGE, + number=2, + message=ad_asset.AdImageAsset, + ) + headline: ad_asset.AdTextAsset = proto.Field( + proto.MESSAGE, + number=3, + message=ad_asset.AdTextAsset, + ) + description: ad_asset.AdTextAsset = proto.Field( + proto.MESSAGE, + number=4, + message=ad_asset.AdTextAsset, + ) + call_to_action_text: str = proto.Field( + proto.STRING, + number=5, + ) + carousel_cards: MutableSequence[ad_asset.AdDemandGenCarouselCardAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=6, + message=ad_asset.AdDemandGenCarouselCardAsset, + ) + ) + + +class DemandGenVideoResponsiveAdInfo(proto.Message): + r"""A Demand Gen video responsive ad. + + Attributes: + headlines (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets used for the short + headline. + long_headlines (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets used for the long + headline. + descriptions (MutableSequence[google.ads.googleads.v24.common.types.AdTextAsset]): + List of text assets used for the description. + videos (MutableSequence[google.ads.googleads.v24.common.types.AdVideoAsset]): + Required. List of YouTube video assets used + for the ad. + logo_images (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + Required. Logo image to be used in the ad. + Valid image types are GIF, JPEG, and PNG. The + minimum size is 128x128 and the aspect ratio + must be 1:1 (+-1%). + companion_banners (MutableSequence[google.ads.googleads.v24.common.types.AdImageAsset]): + List of image assets used for the companion + banner. Currently, only a single value for the + companion banner asset is supported. + breadcrumb1 (str): + First part of text that appears in the ad + with the displayed URL. + breadcrumb2 (str): + Second part of text that appears in the ad + with the displayed URL. + business_name (google.ads.googleads.v24.common.types.AdTextAsset): + Required. The advertiser/brand name. + call_to_actions (MutableSequence[google.ads.googleads.v24.common.types.AdCallToActionAsset]): + Assets of type CallToActionAsset used for the + "Call To Action" button. + """ + + headlines: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=ad_asset.AdTextAsset, + ) + long_headlines: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=ad_asset.AdTextAsset, + ) + descriptions: MutableSequence[ad_asset.AdTextAsset] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=ad_asset.AdTextAsset, + ) + videos: MutableSequence[ad_asset.AdVideoAsset] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=ad_asset.AdVideoAsset, + ) + logo_images: MutableSequence[ad_asset.AdImageAsset] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message=ad_asset.AdImageAsset, + ) + companion_banners: MutableSequence[ad_asset.AdImageAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=10, + message=ad_asset.AdImageAsset, + ) + ) + breadcrumb1: str = proto.Field( + proto.STRING, + number=6, + ) + breadcrumb2: str = proto.Field( + proto.STRING, + number=7, + ) + business_name: ad_asset.AdTextAsset = proto.Field( + proto.MESSAGE, + number=8, + message=ad_asset.AdTextAsset, + ) + call_to_actions: MutableSequence[ad_asset.AdCallToActionAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=9, + message=ad_asset.AdCallToActionAsset, + ) + ) + + +class DemandGenProductAdInfo(proto.Message): + r"""A Demand Gen product ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + headline (google.ads.googleads.v24.common.types.AdTextAsset): + Required. Text asset used for the short + headline. + + This field is a member of `oneof`_ ``_headline``. + description (google.ads.googleads.v24.common.types.AdTextAsset): + Required. Text asset used for the + description. + + This field is a member of `oneof`_ ``_description``. + logo_image (google.ads.googleads.v24.common.types.AdImageAsset): + Required. Logo image to be used in the ad. + Valid image types are GIF, JPEG, and PNG. The + minimum size is 128x128 and the aspect ratio + must be 1:1 (+-1%). + + This field is a member of `oneof`_ ``_logo_image``. + breadcrumb1 (str): + First part of text that appears in the ad + with the displayed URL. + breadcrumb2 (str): + Second part of text that appears in the ad + with the displayed URL. + business_name (google.ads.googleads.v24.common.types.AdTextAsset): + Required. The advertiser/brand name. + call_to_action (google.ads.googleads.v24.common.types.AdCallToActionAsset): + Asset of type CallToActionAsset used for the + "Call To Action" button. + + This field is a member of `oneof`_ ``_call_to_action``. + """ + + headline: ad_asset.AdTextAsset = proto.Field( + proto.MESSAGE, + number=1, + optional=True, + message=ad_asset.AdTextAsset, + ) + description: ad_asset.AdTextAsset = proto.Field( + proto.MESSAGE, + number=2, + optional=True, + message=ad_asset.AdTextAsset, + ) + logo_image: ad_asset.AdImageAsset = proto.Field( + proto.MESSAGE, + number=3, + optional=True, + message=ad_asset.AdImageAsset, + ) + breadcrumb1: str = proto.Field( + proto.STRING, + number=4, + ) + breadcrumb2: str = proto.Field( + proto.STRING, + number=5, + ) + business_name: ad_asset.AdTextAsset = proto.Field( + proto.MESSAGE, + number=6, + message=ad_asset.AdTextAsset, + ) + call_to_action: ad_asset.AdCallToActionAsset = proto.Field( + proto.MESSAGE, + number=7, + optional=True, + message=ad_asset.AdCallToActionAsset, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/additional_application_info.py b/google/ads/googleads/v24/common/types/additional_application_info.py new file mode 100644 index 000000000..b58f12771 --- /dev/null +++ b/google/ads/googleads/v24/common/types/additional_application_info.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + application_instance as gage_application_instance, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "AdditionalApplicationInfo", + }, +) + + +class AdditionalApplicationInfo(proto.Message): + r"""Additional information about the application/tool issuing the + request. This field is only used by + [ContentCreatorInsightsService][google.ads.googleads.v24.services.ContentCreatorInsightsService], + [AudienceInsightsService][google.ads.googleads.v24.services.AudienceInsightsService], + and + [ReachPlanService][google.ads.googleads.v24.services.ReachPlanService] + APIs. + + Attributes: + application_id (str): + The unique identifier of the agency proprietary application. + This identifier is generated by Google. Reach out to your + Google representative to request an application_id for each + new application being integrated. + application_instance (google.ads.googleads.v24.enums.types.ApplicationInstanceEnum.ApplicationInstance): + The instance type of the application sending + the request. + """ + + application_id: str = proto.Field( + proto.STRING, + number=1, + ) + application_instance: ( + gage_application_instance.ApplicationInstanceEnum.ApplicationInstance + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_application_instance.ApplicationInstanceEnum.ApplicationInstance, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/asset_policy.py b/google/ads/googleads/v24/common/types/asset_policy.py new file mode 100644 index 000000000..cfc5f9c33 --- /dev/null +++ b/google/ads/googleads/v24/common/types/asset_policy.py @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import policy +from google.ads.googleads.v24.enums.types import asset_link_primary_status +from google.ads.googleads.v24.enums.types import ( + asset_link_primary_status_reason, +) +from google.ads.googleads.v24.enums.types import ( + asset_offline_evaluation_error_reasons, +) +from google.ads.googleads.v24.enums.types import policy_approval_status +from google.ads.googleads.v24.enums.types import policy_review_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "AdAssetPolicySummary", + "AssetLinkPrimaryStatusDetails", + "AssetDisapproved", + }, +) + + +class AdAssetPolicySummary(proto.Message): + r"""Contains policy information for an asset inside an ad. + + Attributes: + policy_topic_entries (MutableSequence[google.ads.googleads.v24.common.types.PolicyTopicEntry]): + The list of policy findings for this asset. + review_status (google.ads.googleads.v24.enums.types.PolicyReviewStatusEnum.PolicyReviewStatus): + Where in the review process this asset. + approval_status (google.ads.googleads.v24.enums.types.PolicyApprovalStatusEnum.PolicyApprovalStatus): + The overall approval status of this asset, + which is calculated based on the status of its + individual policy topic entries. + """ + + policy_topic_entries: MutableSequence[policy.PolicyTopicEntry] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=policy.PolicyTopicEntry, + ) + ) + review_status: ( + policy_review_status.PolicyReviewStatusEnum.PolicyReviewStatus + ) = proto.Field( + proto.ENUM, + number=2, + enum=policy_review_status.PolicyReviewStatusEnum.PolicyReviewStatus, + ) + approval_status: ( + policy_approval_status.PolicyApprovalStatusEnum.PolicyApprovalStatus + ) = proto.Field( + proto.ENUM, + number=3, + enum=policy_approval_status.PolicyApprovalStatusEnum.PolicyApprovalStatus, + ) + + +class AssetLinkPrimaryStatusDetails(proto.Message): + r"""Provides the detail of a PrimaryStatus. Each asset link has a + PrimaryStatus value (e.g. NOT_ELIGIBLE, meaning not serving), and + list of corroborating PrimaryStatusReasons (e.g. + [ASSET_DISAPPROVED]). Each reason may have some additional details + annotated with it. For instance, when the reason is + ASSET_DISAPPROVED, the details field will contain additional + information about the offline evaluation errors which led to the + asset being disapproved. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + reason (google.ads.googleads.v24.enums.types.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason): + Provides the reason of this PrimaryStatus. + + This field is a member of `oneof`_ ``_reason``. + status (google.ads.googleads.v24.enums.types.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus): + Provides the PrimaryStatus of this status + detail. + + This field is a member of `oneof`_ ``_status``. + asset_disapproved (google.ads.googleads.v24.common.types.AssetDisapproved): + Provides the details for + AssetLinkPrimaryStatusReason.ASSET_DISAPPROVED + + This field is a member of `oneof`_ ``details``. + """ + + reason: ( + asset_link_primary_status_reason.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason + ) = proto.Field( + proto.ENUM, + number=1, + optional=True, + enum=asset_link_primary_status_reason.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason, + ) + status: ( + asset_link_primary_status.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus + ) = proto.Field( + proto.ENUM, + number=2, + optional=True, + enum=asset_link_primary_status.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus, + ) + asset_disapproved: "AssetDisapproved" = proto.Field( + proto.MESSAGE, + number=3, + oneof="details", + message="AssetDisapproved", + ) + + +class AssetDisapproved(proto.Message): + r"""Details related to AssetLinkPrimaryStatusReasonPB.ASSET_DISAPPROVED + + Attributes: + offline_evaluation_error_reasons (MutableSequence[google.ads.googleads.v24.enums.types.AssetOfflineEvaluationErrorReasonsEnum.AssetOfflineEvaluationErrorReasons]): + Provides the quality evaluation disapproval + reason of an asset. + """ + + offline_evaluation_error_reasons: MutableSequence[ + asset_offline_evaluation_error_reasons.AssetOfflineEvaluationErrorReasonsEnum.AssetOfflineEvaluationErrorReasons + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum=asset_offline_evaluation_error_reasons.AssetOfflineEvaluationErrorReasonsEnum.AssetOfflineEvaluationErrorReasons, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/asset_set_types.py b/google/ads/googleads/v24/common/types/asset_set_types.py new file mode 100644 index 000000000..4a68796d4 --- /dev/null +++ b/google/ads/googleads/v24/common/types/asset_set_types.py @@ -0,0 +1,366 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import chain_relationship_type +from google.ads.googleads.v24.enums.types import ( + location_ownership_type as gage_location_ownership_type, +) +from google.ads.googleads.v24.enums.types import location_string_filter_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "LocationSet", + "BusinessProfileLocationSet", + "ChainSet", + "ChainFilter", + "MapsLocationSet", + "MapsLocationInfo", + "BusinessProfileLocationGroup", + "DynamicBusinessProfileLocationGroupFilter", + "BusinessProfileBusinessNameFilter", + "ChainLocationGroup", + }, +) + + +class LocationSet(proto.Message): + r"""Data related to location set. One of the Google Business + Profile (previously known as Google My Business) data, Chain + data, and map location data need to be specified. + + 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: + location_ownership_type (google.ads.googleads.v24.enums.types.LocationOwnershipTypeEnum.LocationOwnershipType): + Required. Immutable. Location Ownership Type + (owned location or affiliate location). + business_profile_location_set (google.ads.googleads.v24.common.types.BusinessProfileLocationSet): + Data used to configure a location set + populated from Google Business Profile + locations. + + This field is a member of `oneof`_ ``source``. + chain_location_set (google.ads.googleads.v24.common.types.ChainSet): + Data used to configure a location on chain + set populated with the specified chains. + + This field is a member of `oneof`_ ``source``. + maps_location_set (google.ads.googleads.v24.common.types.MapsLocationSet): + Only set if locations are synced based on + selected maps locations + + This field is a member of `oneof`_ ``source``. + """ + + location_ownership_type: ( + gage_location_ownership_type.LocationOwnershipTypeEnum.LocationOwnershipType + ) = proto.Field( + proto.ENUM, + number=3, + enum=gage_location_ownership_type.LocationOwnershipTypeEnum.LocationOwnershipType, + ) + business_profile_location_set: "BusinessProfileLocationSet" = proto.Field( + proto.MESSAGE, + number=1, + oneof="source", + message="BusinessProfileLocationSet", + ) + chain_location_set: "ChainSet" = proto.Field( + proto.MESSAGE, + number=2, + oneof="source", + message="ChainSet", + ) + maps_location_set: "MapsLocationSet" = proto.Field( + proto.MESSAGE, + number=5, + oneof="source", + message="MapsLocationSet", + ) + + +class BusinessProfileLocationSet(proto.Message): + r"""Data used to configure a location set populated from Google + Business Profile locations. + Different types of filters are AND'ed together, if they are + specified. + + Attributes: + http_authorization_token (str): + Required. Immutable. The HTTP authorization + token used to obtain authorization. + email_address (str): + Required. Immutable. Email address of a + Google Business Profile account or email address + of a manager of the Google Business Profile + account. + business_name_filter (str): + Used to filter Google Business Profile + listings by business name. If businessNameFilter + is set, only listings with a matching business + name are candidates to be sync'd into Assets. + label_filters (MutableSequence[str]): + Used to filter Google Business Profile + listings by labels. If entries exist in + labelFilters, only listings that have any of the + labels set are candidates to be synchronized + into Assets. If no entries exist in + labelFilters, then all listings are candidates + for syncing. Label filters are OR'ed together. + listing_id_filters (MutableSequence[int]): + Used to filter Google Business Profile + listings by listing id. If entries exist in + listingIdFilters, only listings specified by the + filters are candidates to be synchronized into + Assets. If no entries exist in listingIdFilters, + then all listings are candidates for syncing. + Listing ID filters are OR'ed together. + business_account_id (str): + Immutable. The account ID of the managed + business whose locations are to be used. If this + field is not set, then all businesses accessible + by the user (specified by the emailAddress) are + used. + """ + + http_authorization_token: str = proto.Field( + proto.STRING, + number=1, + ) + email_address: str = proto.Field( + proto.STRING, + number=2, + ) + business_name_filter: str = proto.Field( + proto.STRING, + number=3, + ) + label_filters: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=4, + ) + listing_id_filters: MutableSequence[int] = proto.RepeatedField( + proto.INT64, + number=5, + ) + business_account_id: str = proto.Field( + proto.STRING, + number=6, + ) + + +class ChainSet(proto.Message): + r"""Data used to configure a location set populated with the + specified chains. + + Attributes: + relationship_type (google.ads.googleads.v24.enums.types.ChainRelationshipTypeEnum.ChainRelationshipType): + Required. Immutable. Relationship type the + specified chains have with this advertiser. + chains (MutableSequence[google.ads.googleads.v24.common.types.ChainFilter]): + Required. A list of chain level filters, all + filters are OR'ed together. + """ + + relationship_type: ( + chain_relationship_type.ChainRelationshipTypeEnum.ChainRelationshipType + ) = proto.Field( + proto.ENUM, + number=1, + enum=chain_relationship_type.ChainRelationshipTypeEnum.ChainRelationshipType, + ) + chains: MutableSequence["ChainFilter"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ChainFilter", + ) + + +class ChainFilter(proto.Message): + r"""One chain level filter on location in a feed item set. + The filtering logic among all the fields is AND. + + Attributes: + chain_id (int): + Required. Used to filter chain locations by + chain id. Only chain locations that belong to + the specified chain will be in the asset set. + location_attributes (MutableSequence[str]): + Used to filter chain locations by location + attributes. Only chain locations that belong to + all of the specified attribute(s) will be in the + asset set. If this field is empty, it means no + filtering on this field. + """ + + chain_id: int = proto.Field( + proto.INT64, + number=1, + ) + location_attributes: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + + +class MapsLocationSet(proto.Message): + r"""Wrapper for multiple maps location sync data + + Attributes: + maps_locations (MutableSequence[google.ads.googleads.v24.common.types.MapsLocationInfo]): + Required. A list of maps location info that + user manually synced in. + """ + + maps_locations: MutableSequence["MapsLocationInfo"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MapsLocationInfo", + ) + + +class MapsLocationInfo(proto.Message): + r"""Wrapper for place ids + + Attributes: + place_id (str): + Place ID of the Maps location. + """ + + place_id: str = proto.Field( + proto.STRING, + number=1, + ) + + +class BusinessProfileLocationGroup(proto.Message): + r"""Information about a Business Profile dynamic location group. Only + applicable if the sync level AssetSet's type is LOCATION_SYNC and + sync source is Business Profile. + + Attributes: + dynamic_business_profile_location_group_filter (google.ads.googleads.v24.common.types.DynamicBusinessProfileLocationGroupFilter): + Filter for dynamic Business Profile location + sets. + """ + + dynamic_business_profile_location_group_filter: ( + "DynamicBusinessProfileLocationGroupFilter" + ) = proto.Field( + proto.MESSAGE, + number=1, + message="DynamicBusinessProfileLocationGroupFilter", + ) + + +class DynamicBusinessProfileLocationGroupFilter(proto.Message): + r"""Represents a filter on Business Profile locations in an asset + set. If multiple filters are provided, they are AND'ed together. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + label_filters (MutableSequence[str]): + Used to filter Business Profile locations by + label. Only locations that have any of the + listed labels will be in the asset set. Label + filters are OR'ed together. + business_name_filter (google.ads.googleads.v24.common.types.BusinessProfileBusinessNameFilter): + Used to filter Business Profile locations by + business name. + + This field is a member of `oneof`_ ``_business_name_filter``. + listing_id_filters (MutableSequence[int]): + Used to filter Business Profile locations by + listing ids. + """ + + label_filters: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + business_name_filter: "BusinessProfileBusinessNameFilter" = proto.Field( + proto.MESSAGE, + number=2, + optional=True, + message="BusinessProfileBusinessNameFilter", + ) + listing_id_filters: MutableSequence[int] = proto.RepeatedField( + proto.INT64, + number=3, + ) + + +class BusinessProfileBusinessNameFilter(proto.Message): + r"""Business Profile location group business name filter. + + Attributes: + business_name (str): + Business name string to use for filtering. + filter_type (google.ads.googleads.v24.enums.types.LocationStringFilterTypeEnum.LocationStringFilterType): + The type of string matching to use when filtering with + business_name. + """ + + business_name: str = proto.Field( + proto.STRING, + number=1, + ) + filter_type: ( + location_string_filter_type.LocationStringFilterTypeEnum.LocationStringFilterType + ) = proto.Field( + proto.ENUM, + number=2, + enum=location_string_filter_type.LocationStringFilterTypeEnum.LocationStringFilterType, + ) + + +class ChainLocationGroup(proto.Message): + r"""Represents information about a Chain dynamic location group. Only + applicable if the sync level AssetSet's type is LOCATION_SYNC and + sync source is chain. + + Attributes: + dynamic_chain_location_group_filters (MutableSequence[google.ads.googleads.v24.common.types.ChainFilter]): + Used to filter chain locations by chain ids. + Only Locations that belong to the specified + chain(s) will be in the asset set. + """ + + dynamic_chain_location_group_filters: MutableSequence["ChainFilter"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ChainFilter", + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/asset_types.py b/google/ads/googleads/v24/common/types/asset_types.py new file mode 100644 index 000000000..22fb93096 --- /dev/null +++ b/google/ads/googleads/v24/common/types/asset_types.py @@ -0,0 +1,2601 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import ad_asset +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.common.types import feed_common +from google.ads.googleads.v24.enums.types import ( + business_message_call_to_action_type, +) +from google.ads.googleads.v24.enums.types import business_message_provider +from google.ads.googleads.v24.enums.types import ( + call_conversion_reporting_state as gage_call_conversion_reporting_state, +) +from google.ads.googleads.v24.enums.types import ( + call_to_action_type as gage_call_to_action_type, +) +from google.ads.googleads.v24.enums.types import lead_form_call_to_action_type +from google.ads.googleads.v24.enums.types import lead_form_desired_intent +from google.ads.googleads.v24.enums.types import lead_form_field_user_input_type +from google.ads.googleads.v24.enums.types import ( + lead_form_post_submit_call_to_action_type, +) +from google.ads.googleads.v24.enums.types import ( + location_ownership_type as gage_location_ownership_type, +) +from google.ads.googleads.v24.enums.types import mime_type as gage_mime_type +from google.ads.googleads.v24.enums.types import mobile_app_vendor +from google.ads.googleads.v24.enums.types import price_extension_price_qualifier +from google.ads.googleads.v24.enums.types import price_extension_price_unit +from google.ads.googleads.v24.enums.types import price_extension_type +from google.ads.googleads.v24.enums.types import promotion_barcode_type +from google.ads.googleads.v24.enums.types import ( + promotion_extension_discount_modifier, +) +from google.ads.googleads.v24.enums.types import promotion_extension_occasion + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "YoutubeVideoAsset", + "MediaBundleAsset", + "ImageAsset", + "ImageDimension", + "TextAsset", + "LeadFormAsset", + "LeadFormField", + "LeadFormCustomQuestionField", + "LeadFormSingleChoiceAnswers", + "LeadFormDeliveryMethod", + "WebhookDelivery", + "BookOnGoogleAsset", + "PromotionAsset", + "PromotionBarcodeInfo", + "PromotionQrCodeInfo", + "CalloutAsset", + "StructuredSnippetAsset", + "SitelinkAsset", + "PageFeedAsset", + "DynamicEducationAsset", + "MobileAppAsset", + "HotelCalloutAsset", + "CallAsset", + "PriceAsset", + "PriceOffering", + "CallToActionAsset", + "DynamicRealEstateAsset", + "DynamicCustomAsset", + "DynamicHotelsAndRentalsAsset", + "DynamicFlightsAsset", + "DemandGenCarouselCardAsset", + "DynamicTravelAsset", + "DynamicLocalAsset", + "DynamicJobsAsset", + "LocationAsset", + "BusinessProfileLocation", + "HotelPropertyAsset", + "BusinessMessageAsset", + "WhatsappBusinessMessageInfo", + "FacebookMessengerBusinessMessageInfo", + "ZaloBusinessMessageInfo", + "BusinessMessageCallToActionInfo", + "AppDeepLinkAsset", + "YouTubeVideoListAsset", + }, +) + + +class YoutubeVideoAsset(proto.Message): + r"""A YouTube asset. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + youtube_video_id (str): + YouTube video id. This is the 11 character + string value used in the YouTube video URL. + + This field is a member of `oneof`_ ``_youtube_video_id``. + youtube_video_title (str): + YouTube video title. + """ + + youtube_video_id: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + youtube_video_title: str = proto.Field( + proto.STRING, + number=3, + ) + + +class MediaBundleAsset(proto.Message): + r"""A MediaBundle asset. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + data (bytes): + Media bundle (ZIP file) asset data. The + format of the uploaded ZIP file depends on the + ad field where it will be used. For more + information on the format, see the documentation + of the ad field where you plan on using the + MediaBundleAsset. This field is mutate only. + + This field is a member of `oneof`_ ``_data``. + """ + + data: bytes = proto.Field( + proto.BYTES, + number=2, + optional=True, + ) + + +class ImageAsset(proto.Message): + r"""An Image asset. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + data (bytes): + The raw bytes data of an image. This field is + mutate only. + + This field is a member of `oneof`_ ``_data``. + file_size (int): + File size of the image asset in bytes. + + This field is a member of `oneof`_ ``_file_size``. + mime_type (google.ads.googleads.v24.enums.types.MimeTypeEnum.MimeType): + MIME type of the image asset. + full_size (google.ads.googleads.v24.common.types.ImageDimension): + Metadata for this image at its original size. + """ + + data: bytes = proto.Field( + proto.BYTES, + number=5, + optional=True, + ) + file_size: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + mime_type: gage_mime_type.MimeTypeEnum.MimeType = proto.Field( + proto.ENUM, + number=3, + enum=gage_mime_type.MimeTypeEnum.MimeType, + ) + full_size: "ImageDimension" = proto.Field( + proto.MESSAGE, + number=4, + message="ImageDimension", + ) + + +class ImageDimension(proto.Message): + r"""Metadata for an image at a certain size, either original or + resized. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + height_pixels (int): + Height of the image. + + This field is a member of `oneof`_ ``_height_pixels``. + width_pixels (int): + Width of the image. + + This field is a member of `oneof`_ ``_width_pixels``. + url (str): + A URL that returns the image with this height + and width. + + This field is a member of `oneof`_ ``_url``. + """ + + height_pixels: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + width_pixels: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + url: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + + +class TextAsset(proto.Message): + r"""A Text asset. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + text (str): + Text content of the text asset. + + This field is a member of `oneof`_ ``_text``. + """ + + text: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class LeadFormAsset(proto.Message): + r"""A Lead Form asset. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + business_name (str): + Required. The name of the business being + advertised. + call_to_action_type (google.ads.googleads.v24.enums.types.LeadFormCallToActionTypeEnum.LeadFormCallToActionType): + Required. Pre-defined display text that + encourages user to expand the form. + call_to_action_description (str): + Required. Text giving a clear value + proposition of what users expect once they + expand the form. + headline (str): + Required. Headline of the expanded form to + describe what the form is asking for or + facilitating. + description (str): + Required. Detailed description of the + expanded form to describe what the form is + asking for or facilitating. + privacy_policy_url (str): + Required. Link to a page describing the + policy on how the collected data is handled by + the advertiser/business. + post_submit_headline (str): + Headline of text shown after form submission + that describes how the advertiser will follow up + with the user. + + This field is a member of `oneof`_ ``_post_submit_headline``. + post_submit_description (str): + Detailed description shown after form + submission that describes how the advertiser + will follow up with the user. + + This field is a member of `oneof`_ ``_post_submit_description``. + fields (MutableSequence[google.ads.googleads.v24.common.types.LeadFormField]): + Ordered list of input fields. This field can + be updated by reordering questions, but not by + adding or removing questions. + custom_question_fields (MutableSequence[google.ads.googleads.v24.common.types.LeadFormCustomQuestionField]): + Ordered list of custom question fields. This + field is subject to a limit of 5 qualifying + questions per form. + delivery_methods (MutableSequence[google.ads.googleads.v24.common.types.LeadFormDeliveryMethod]): + Configured methods for collected lead data to + be delivered to advertiser. Only one method + typed as WebhookDelivery can be configured. + post_submit_call_to_action_type (google.ads.googleads.v24.enums.types.LeadFormPostSubmitCallToActionTypeEnum.LeadFormPostSubmitCallToActionType): + Pre-defined display text that encourages user + action after the form is submitted. + background_image_asset (str): + Asset resource name of the background image. + The image dimensions must be exactly 1200x628. + + This field is a member of `oneof`_ ``_background_image_asset``. + desired_intent (google.ads.googleads.v24.enums.types.LeadFormDesiredIntentEnum.LeadFormDesiredIntent): + Chosen intent for the lead form, for example, + more volume or more qualified. + custom_disclosure (str): + Custom disclosure shown along with Google + disclaimer on the lead form. Accessible to + allowed customers only. + + This field is a member of `oneof`_ ``_custom_disclosure``. + """ + + business_name: str = proto.Field( + proto.STRING, + number=10, + ) + call_to_action_type: ( + lead_form_call_to_action_type.LeadFormCallToActionTypeEnum.LeadFormCallToActionType + ) = proto.Field( + proto.ENUM, + number=17, + enum=lead_form_call_to_action_type.LeadFormCallToActionTypeEnum.LeadFormCallToActionType, + ) + call_to_action_description: str = proto.Field( + proto.STRING, + number=18, + ) + headline: str = proto.Field( + proto.STRING, + number=12, + ) + description: str = proto.Field( + proto.STRING, + number=13, + ) + privacy_policy_url: str = proto.Field( + proto.STRING, + number=14, + ) + post_submit_headline: str = proto.Field( + proto.STRING, + number=15, + optional=True, + ) + post_submit_description: str = proto.Field( + proto.STRING, + number=16, + optional=True, + ) + fields: MutableSequence["LeadFormField"] = proto.RepeatedField( + proto.MESSAGE, + number=8, + message="LeadFormField", + ) + custom_question_fields: MutableSequence["LeadFormCustomQuestionField"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=23, + message="LeadFormCustomQuestionField", + ) + ) + delivery_methods: MutableSequence["LeadFormDeliveryMethod"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=9, + message="LeadFormDeliveryMethod", + ) + ) + post_submit_call_to_action_type: ( + lead_form_post_submit_call_to_action_type.LeadFormPostSubmitCallToActionTypeEnum.LeadFormPostSubmitCallToActionType + ) = proto.Field( + proto.ENUM, + number=19, + enum=lead_form_post_submit_call_to_action_type.LeadFormPostSubmitCallToActionTypeEnum.LeadFormPostSubmitCallToActionType, + ) + background_image_asset: str = proto.Field( + proto.STRING, + number=20, + optional=True, + ) + desired_intent: ( + lead_form_desired_intent.LeadFormDesiredIntentEnum.LeadFormDesiredIntent + ) = proto.Field( + proto.ENUM, + number=21, + enum=lead_form_desired_intent.LeadFormDesiredIntentEnum.LeadFormDesiredIntent, + ) + custom_disclosure: str = proto.Field( + proto.STRING, + number=22, + optional=True, + ) + + +class LeadFormField(proto.Message): + r"""One input field instance within a form. + + 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: + input_type (google.ads.googleads.v24.enums.types.LeadFormFieldUserInputTypeEnum.LeadFormFieldUserInputType): + Describes the input type, which may be a + predefined type such as "full name" or a + pre-vetted question like "What kind of vehicle + do you have?". + single_choice_answers (google.ads.googleads.v24.common.types.LeadFormSingleChoiceAnswers): + Answer configuration for a single choice + question. Can be set only for pre-vetted + question fields. Minimum of 2 answers required + and maximum of 12 allowed. + + This field is a member of `oneof`_ ``answers``. + has_location_answer (bool): + Answer configuration for location question. If true, + campaign/account level location data (state, city, business + name etc) will be rendered on the Lead Form. Starting V13.1, + has_location_answer can only be set for "What is your + preferred dealership?" question, for advertisers with + Location Assets setup at campaign/account level. + + This field is a member of `oneof`_ ``answers``. + """ + + input_type: ( + lead_form_field_user_input_type.LeadFormFieldUserInputTypeEnum.LeadFormFieldUserInputType + ) = proto.Field( + proto.ENUM, + number=1, + enum=lead_form_field_user_input_type.LeadFormFieldUserInputTypeEnum.LeadFormFieldUserInputType, + ) + single_choice_answers: "LeadFormSingleChoiceAnswers" = proto.Field( + proto.MESSAGE, + number=2, + oneof="answers", + message="LeadFormSingleChoiceAnswers", + ) + has_location_answer: bool = proto.Field( + proto.BOOL, + number=3, + oneof="answers", + ) + + +class LeadFormCustomQuestionField(proto.Message): + r"""One custom question input field instance within a form. + + 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: + custom_question_text (str): + The exact custom question field text (for + example, "What kind of vehicle do you have?"). + single_choice_answers (google.ads.googleads.v24.common.types.LeadFormSingleChoiceAnswers): + Answer configuration for a single choice + question. Minimum of 2 answers and maximum of 12 + allowed. + + This field is a member of `oneof`_ ``answers``. + has_location_answer (bool): + Answer configuration for location question. If true, + campaign/account level location data (state, city, business + name etc) will be rendered on the Lead Form. Starting V13.1, + has_location_answer can only be set for "What is your + preferred dealership?" question, for advertisers with + Location Assets setup at campaign/account level. + + This field is a member of `oneof`_ ``answers``. + """ + + custom_question_text: str = proto.Field( + proto.STRING, + number=1, + ) + single_choice_answers: "LeadFormSingleChoiceAnswers" = proto.Field( + proto.MESSAGE, + number=2, + oneof="answers", + message="LeadFormSingleChoiceAnswers", + ) + has_location_answer: bool = proto.Field( + proto.BOOL, + number=3, + oneof="answers", + ) + + +class LeadFormSingleChoiceAnswers(proto.Message): + r"""Defines possible answers for a single choice question, + usually presented as a single-choice drop-down list. + + Attributes: + answers (MutableSequence[str]): + List of choices for a single question field. + The order of entries defines UI order. Minimum + of 2 answers required and maximum of 12 allowed. + """ + + answers: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + + +class LeadFormDeliveryMethod(proto.Message): + r"""A configuration of how leads are delivered to the advertiser. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + webhook (google.ads.googleads.v24.common.types.WebhookDelivery): + Webhook method of delivery. + + This field is a member of `oneof`_ ``delivery_details``. + """ + + webhook: "WebhookDelivery" = proto.Field( + proto.MESSAGE, + number=1, + oneof="delivery_details", + message="WebhookDelivery", + ) + + +class WebhookDelivery(proto.Message): + r"""Google notifies the advertiser of leads by making HTTP calls + to an endpoint they specify. The requests contain JSON matching + a schema that Google publishes as part of form ads + documentation. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + advertiser_webhook_url (str): + Webhook url specified by advertiser to send + the lead. + + This field is a member of `oneof`_ ``_advertiser_webhook_url``. + google_secret (str): + Anti-spoofing secret set by the advertiser as + part of the webhook payload. + + This field is a member of `oneof`_ ``_google_secret``. + payload_schema_version (int): + The schema version that this delivery + instance will use. + + This field is a member of `oneof`_ ``_payload_schema_version``. + """ + + advertiser_webhook_url: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + google_secret: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + payload_schema_version: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + + +class BookOnGoogleAsset(proto.Message): + r"""A Book on Google asset. Used to redirect user to book through + Google. Book on Google will change the redirect url to book + directly through Google. + + """ + + +class PromotionAsset(proto.Message): + r"""A Promotion asset. + + 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: + promotion_target (str): + Required. A freeform description of what the + promotion is targeting. + discount_modifier (google.ads.googleads.v24.enums.types.PromotionExtensionDiscountModifierEnum.PromotionExtensionDiscountModifier): + A modifier for qualification of the discount. + redemption_start_date (str): + Start date of when the promotion is eligible + to be redeemed, in yyyy-MM-dd format. + redemption_end_date (str): + Last date of when the promotion is eligible + to be redeemed, in yyyy-MM-dd format. + occasion (google.ads.googleads.v24.enums.types.PromotionExtensionOccasionEnum.PromotionExtensionOccasion): + The occasion the promotion was intended for. + If an occasion is set, the redemption window + will need to fall within the date range + associated with the occasion. + language_code (str): + The language of the promotion. + Represented as BCP 47 language tag. + start_date (str): + Start date of when this asset is effective + and can begin serving, in yyyy-MM-dd format. + end_date (str): + Last date of when this asset is effective and + still serving, in yyyy-MM-dd format. + ad_schedule_targets (MutableSequence[google.ads.googleads.v24.common.types.AdScheduleInfo]): + List of non-overlapping schedules specifying + all time intervals for which the asset may + serve. There can be a maximum of 6 schedules per + day, 42 in total. + terms_and_conditions_text (str): + Terms and conditions of the promotion. + terms_and_conditions_uri (str): + URI to the terms and conditions of the + promotion. + percent_off (int): + Percentage off discount in the promotion. 1,000,000 = 100%. + Either this or money_amount_off is required. + + This field is a member of `oneof`_ ``discount_type``. + money_amount_off (google.ads.googleads.v24.common.types.Money): + Money amount off for discount in the promotion. Either this + or percent_off is required. + + This field is a member of `oneof`_ ``discount_type``. + promotion_code (str): + A code the user should use in order to be + eligible for the promotion. + + This field is a member of `oneof`_ ``promotion_trigger``. + orders_over_amount (google.ads.googleads.v24.common.types.Money): + The amount the total order needs to be for + the user to be eligible for the promotion. + + This field is a member of `oneof`_ ``promotion_trigger``. + promotion_barcode_info (google.ads.googleads.v24.common.types.PromotionBarcodeInfo): + Barcode info used to generate promotion + barcode for user to be eligible for the + promotion. + + This field is a member of `oneof`_ ``promotion_trigger``. + promotion_qr_code_info (google.ads.googleads.v24.common.types.PromotionQrCodeInfo): + QR code info used to generate promotion QR + code for user to be eligible for the promotion. + + This field is a member of `oneof`_ ``promotion_trigger``. + """ + + promotion_target: str = proto.Field( + proto.STRING, + number=1, + ) + discount_modifier: ( + promotion_extension_discount_modifier.PromotionExtensionDiscountModifierEnum.PromotionExtensionDiscountModifier + ) = proto.Field( + proto.ENUM, + number=2, + enum=promotion_extension_discount_modifier.PromotionExtensionDiscountModifierEnum.PromotionExtensionDiscountModifier, + ) + redemption_start_date: str = proto.Field( + proto.STRING, + number=7, + ) + redemption_end_date: str = proto.Field( + proto.STRING, + number=8, + ) + occasion: ( + promotion_extension_occasion.PromotionExtensionOccasionEnum.PromotionExtensionOccasion + ) = proto.Field( + proto.ENUM, + number=9, + enum=promotion_extension_occasion.PromotionExtensionOccasionEnum.PromotionExtensionOccasion, + ) + language_code: str = proto.Field( + proto.STRING, + number=10, + ) + start_date: str = proto.Field( + proto.STRING, + number=11, + ) + end_date: str = proto.Field( + proto.STRING, + number=12, + ) + ad_schedule_targets: MutableSequence[criteria.AdScheduleInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=13, + message=criteria.AdScheduleInfo, + ) + ) + terms_and_conditions_text: str = proto.Field( + proto.STRING, + number=14, + ) + terms_and_conditions_uri: str = proto.Field( + proto.STRING, + number=15, + ) + percent_off: int = proto.Field( + proto.INT64, + number=3, + oneof="discount_type", + ) + money_amount_off: feed_common.Money = proto.Field( + proto.MESSAGE, + number=4, + oneof="discount_type", + message=feed_common.Money, + ) + promotion_code: str = proto.Field( + proto.STRING, + number=5, + oneof="promotion_trigger", + ) + orders_over_amount: feed_common.Money = proto.Field( + proto.MESSAGE, + number=6, + oneof="promotion_trigger", + message=feed_common.Money, + ) + promotion_barcode_info: "PromotionBarcodeInfo" = proto.Field( + proto.MESSAGE, + number=16, + oneof="promotion_trigger", + message="PromotionBarcodeInfo", + ) + promotion_qr_code_info: "PromotionQrCodeInfo" = proto.Field( + proto.MESSAGE, + number=17, + oneof="promotion_trigger", + message="PromotionQrCodeInfo", + ) + + +class PromotionBarcodeInfo(proto.Message): + r"""Barcode info to generate promotion barcode. + + Attributes: + type_ (google.ads.googleads.v24.enums.types.PromotionBarcodeTypeEnum.PromotionBarcodeType): + Barcode type used to generate barcode with + the correct format. + barcode_content (str): + Promotion message to be encoded in the + barcode. + """ + + type_: ( + promotion_barcode_type.PromotionBarcodeTypeEnum.PromotionBarcodeType + ) = proto.Field( + proto.ENUM, + number=1, + enum=promotion_barcode_type.PromotionBarcodeTypeEnum.PromotionBarcodeType, + ) + barcode_content: str = proto.Field( + proto.STRING, + number=2, + ) + + +class PromotionQrCodeInfo(proto.Message): + r"""QR code info to generate promotion QR code. + + Attributes: + qr_code_content (str): + Promotion message to be encoded in the QR + code. + """ + + qr_code_content: str = proto.Field( + proto.STRING, + number=1, + ) + + +class CalloutAsset(proto.Message): + r"""A Callout asset. + + Attributes: + callout_text (str): + Required. The callout text. + The length of this string should be between 1 + and 25, inclusive. + start_date (str): + Start date of when this asset is effective + and can begin serving, in yyyy-MM-dd format. + end_date (str): + Last date of when this asset is effective and + still serving, in yyyy-MM-dd format. + ad_schedule_targets (MutableSequence[google.ads.googleads.v24.common.types.AdScheduleInfo]): + List of non-overlapping schedules specifying + all time intervals for which the asset may + serve. There can be a maximum of 6 schedules per + day, 42 in total. + """ + + callout_text: str = proto.Field( + proto.STRING, + number=1, + ) + start_date: str = proto.Field( + proto.STRING, + number=2, + ) + end_date: str = proto.Field( + proto.STRING, + number=3, + ) + ad_schedule_targets: MutableSequence[criteria.AdScheduleInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=4, + message=criteria.AdScheduleInfo, + ) + ) + + +class StructuredSnippetAsset(proto.Message): + r"""A Structured Snippet asset. + + Attributes: + header (str): + Required. The header of the snippet. + This string should be one of the predefined + values at + https://developers.google.com/google-ads/api/reference/data/structured-snippet-headers + values (MutableSequence[str]): + Required. The values in the snippet. + The size of this collection should be between 3 + and 10, inclusive. The length of each value + should be between 1 and 25 characters, + inclusive. + """ + + header: str = proto.Field( + proto.STRING, + number=1, + ) + values: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + + +class SitelinkAsset(proto.Message): + r"""A Sitelink asset. + + Attributes: + link_text (str): + Required. URL display text for the sitelink. + The length of this string should be between 1 + and 25, inclusive. + description1 (str): + First line of the description for the + sitelink. If set, the length should be between 1 + and 35, inclusive, and description2 must also be + set. + description2 (str): + Second line of the description for the + sitelink. If set, the length should be between 1 + and 35, inclusive, and description1 must also be + set. + start_date (str): + Start date of when this asset is effective + and can begin serving, in yyyy-MM-dd format. + end_date (str): + Last date of when this asset is effective and + still serving, in yyyy-MM-dd format. + ad_schedule_targets (MutableSequence[google.ads.googleads.v24.common.types.AdScheduleInfo]): + List of non-overlapping schedules specifying + all time intervals for which the asset may + serve. There can be a maximum of 6 schedules per + day, 42 in total. + """ + + link_text: str = proto.Field( + proto.STRING, + number=1, + ) + description1: str = proto.Field( + proto.STRING, + number=2, + ) + description2: str = proto.Field( + proto.STRING, + number=3, + ) + start_date: str = proto.Field( + proto.STRING, + number=4, + ) + end_date: str = proto.Field( + proto.STRING, + number=5, + ) + ad_schedule_targets: MutableSequence[criteria.AdScheduleInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=6, + message=criteria.AdScheduleInfo, + ) + ) + + +class PageFeedAsset(proto.Message): + r"""A Page Feed asset. + + Attributes: + page_url (str): + Required. The webpage that advertisers want + to target. + labels (MutableSequence[str]): + Labels used to group the page urls. + """ + + page_url: str = proto.Field( + proto.STRING, + number=1, + ) + labels: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + + +class DynamicEducationAsset(proto.Message): + r"""A Dynamic Education asset. + + Attributes: + program_id (str): + Required. Program ID which can be any + sequence of letters and digits, and must be + unique and match the values of remarketing tag. + Required. + location_id (str): + Location ID which can be any sequence of + letters and digits and must be unique. + program_name (str): + Required. Program name, for example, Nursing. + Required. + subject (str): + Subject of study, for example, Health. + program_description (str): + Program description, for example, Nursing + Certification. + school_name (str): + School name, for example, Mountain View + School of Nursing. + address (str): + School address which can be specified in one + of the following formats. (1) City, state, code, + country, for example, Mountain View, CA, USA. + (2) Full address, for example, 123 Boulevard St, + Mountain View, CA 94043. (3) Latitude-longitude + in the DDD format, for example, 41.40338, + 2.17403 + contextual_keywords (MutableSequence[str]): + Contextual keywords, for example, Nursing + certification, Health, Mountain View. + android_app_link (str): + Android deep link, for example, + android-app://com.example.android/http/example.com/gizmos?1234. + similar_program_ids (MutableSequence[str]): + Similar program IDs. + ios_app_link (str): + iOS deep link, for example, + exampleApp://content/page. + ios_app_store_id (int): + iOS app store ID. This is used to check if the user has the + app installed on their device before deep linking. If this + field is set, then the ios_app_link field must also be + present. + thumbnail_image_url (str): + Thumbnail image url, for example, + http://www.example.com/thumbnail.png. The + thumbnail image will not be uploaded as image + asset. + image_url (str): + Image url, for example, + http://www.example.com/image.png. The image will + not be uploaded as image asset. + """ + + program_id: str = proto.Field( + proto.STRING, + number=1, + ) + location_id: str = proto.Field( + proto.STRING, + number=2, + ) + program_name: str = proto.Field( + proto.STRING, + number=3, + ) + subject: str = proto.Field( + proto.STRING, + number=4, + ) + program_description: str = proto.Field( + proto.STRING, + number=5, + ) + school_name: str = proto.Field( + proto.STRING, + number=6, + ) + address: str = proto.Field( + proto.STRING, + number=7, + ) + contextual_keywords: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=8, + ) + android_app_link: str = proto.Field( + proto.STRING, + number=9, + ) + similar_program_ids: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=10, + ) + ios_app_link: str = proto.Field( + proto.STRING, + number=11, + ) + ios_app_store_id: int = proto.Field( + proto.INT64, + number=12, + ) + thumbnail_image_url: str = proto.Field( + proto.STRING, + number=13, + ) + image_url: str = proto.Field( + proto.STRING, + number=14, + ) + + +class MobileAppAsset(proto.Message): + r"""An asset representing a mobile app. + + Attributes: + app_id (str): + Required. A string that uniquely identifies a + mobile application. It should just contain the + platform native id, like "com.android.ebay" for + Android or "12345689" for iOS. + app_store (google.ads.googleads.v24.enums.types.MobileAppVendorEnum.MobileAppVendor): + Required. The application store that + distributes this specific app. + link_text (str): + Required. The visible text displayed when the + link is rendered in an ad. The length of this + string should be between 1 and 25, inclusive. + start_date (str): + Start date of when this asset is effective + and can begin serving, in yyyy-MM-dd format. + end_date (str): + Last date of when this asset is effective and + still serving, in yyyy-MM-dd format. + """ + + app_id: str = proto.Field( + proto.STRING, + number=1, + ) + app_store: mobile_app_vendor.MobileAppVendorEnum.MobileAppVendor = ( + proto.Field( + proto.ENUM, + number=2, + enum=mobile_app_vendor.MobileAppVendorEnum.MobileAppVendor, + ) + ) + link_text: str = proto.Field( + proto.STRING, + number=3, + ) + start_date: str = proto.Field( + proto.STRING, + number=4, + ) + end_date: str = proto.Field( + proto.STRING, + number=5, + ) + + +class HotelCalloutAsset(proto.Message): + r"""An asset representing a hotel callout. + + Attributes: + text (str): + Required. The text of the hotel callout + asset. The length of this string should be + between 1 and 25, inclusive. + language_code (str): + Required. The language of the hotel callout. + Represented as BCP 47 language tag. + """ + + text: str = proto.Field( + proto.STRING, + number=1, + ) + language_code: str = proto.Field( + proto.STRING, + number=2, + ) + + +class CallAsset(proto.Message): + r"""A Call asset. + + Attributes: + country_code (str): + Required. Two-letter country code of the + phone number. Examples: 'US', 'us'. + phone_number (str): + Required. The advertiser's raw phone number. + Examples: '1234567890', '(123)456-7890' + call_conversion_reporting_state (google.ads.googleads.v24.enums.types.CallConversionReportingStateEnum.CallConversionReportingState): + Indicates whether this CallAsset should use + its own call conversion setting, follow the + account level setting, or disable call + conversion. + call_conversion_action (str): + The conversion action to attribute a call conversion to. If + not set, the default conversion action is used. This field + only has effect if call_conversion_reporting_state is set to + USE_RESOURCE_LEVEL_CALL_CONVERSION_ACTION. + ad_schedule_targets (MutableSequence[google.ads.googleads.v24.common.types.AdScheduleInfo]): + List of non-overlapping schedules specifying + all time intervals for which the asset may + serve. There can be a maximum of 6 schedules per + day, 42 in total. + """ + + country_code: str = proto.Field( + proto.STRING, + number=1, + ) + phone_number: str = proto.Field( + proto.STRING, + number=2, + ) + call_conversion_reporting_state: ( + gage_call_conversion_reporting_state.CallConversionReportingStateEnum.CallConversionReportingState + ) = proto.Field( + proto.ENUM, + number=3, + enum=gage_call_conversion_reporting_state.CallConversionReportingStateEnum.CallConversionReportingState, + ) + call_conversion_action: str = proto.Field( + proto.STRING, + number=4, + ) + ad_schedule_targets: MutableSequence[criteria.AdScheduleInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=5, + message=criteria.AdScheduleInfo, + ) + ) + + +class PriceAsset(proto.Message): + r"""An asset representing a list of price offers. + + Attributes: + type_ (google.ads.googleads.v24.enums.types.PriceExtensionTypeEnum.PriceExtensionType): + Required. The type of the price asset. + price_qualifier (google.ads.googleads.v24.enums.types.PriceExtensionPriceQualifierEnum.PriceExtensionPriceQualifier): + The price qualifier of the price asset. + language_code (str): + Required. The language of the price asset. + Represented as BCP 47 language tag. + price_offerings (MutableSequence[google.ads.googleads.v24.common.types.PriceOffering]): + The price offerings of the price asset. + The size of this collection should be between 3 + and 8, inclusive. + """ + + type_: price_extension_type.PriceExtensionTypeEnum.PriceExtensionType = ( + proto.Field( + proto.ENUM, + number=1, + enum=price_extension_type.PriceExtensionTypeEnum.PriceExtensionType, + ) + ) + price_qualifier: ( + price_extension_price_qualifier.PriceExtensionPriceQualifierEnum.PriceExtensionPriceQualifier + ) = proto.Field( + proto.ENUM, + number=2, + enum=price_extension_price_qualifier.PriceExtensionPriceQualifierEnum.PriceExtensionPriceQualifier, + ) + language_code: str = proto.Field( + proto.STRING, + number=3, + ) + price_offerings: MutableSequence["PriceOffering"] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="PriceOffering", + ) + + +class PriceOffering(proto.Message): + r"""A single price offering within a PriceAsset. + + Attributes: + header (str): + Required. The header of the price offering. + The length of this string should be between 1 + and 25, inclusive. + description (str): + Required. The description of the price + offering. The length of this string should be + between 1 and 25, inclusive. + price (google.ads.googleads.v24.common.types.Money): + Required. The price value of the price + offering. + unit (google.ads.googleads.v24.enums.types.PriceExtensionPriceUnitEnum.PriceExtensionPriceUnit): + The price unit of the price offering. + final_url (str): + Required. The final URL after all cross + domain redirects. + final_mobile_url (str): + The final mobile URL after all cross domain + redirects. + """ + + header: str = proto.Field( + proto.STRING, + number=1, + ) + description: str = proto.Field( + proto.STRING, + number=2, + ) + price: feed_common.Money = proto.Field( + proto.MESSAGE, + number=3, + message=feed_common.Money, + ) + unit: ( + price_extension_price_unit.PriceExtensionPriceUnitEnum.PriceExtensionPriceUnit + ) = proto.Field( + proto.ENUM, + number=4, + enum=price_extension_price_unit.PriceExtensionPriceUnitEnum.PriceExtensionPriceUnit, + ) + final_url: str = proto.Field( + proto.STRING, + number=5, + ) + final_mobile_url: str = proto.Field( + proto.STRING, + number=6, + ) + + +class CallToActionAsset(proto.Message): + r"""A call to action asset. + + Attributes: + call_to_action (google.ads.googleads.v24.enums.types.CallToActionTypeEnum.CallToActionType): + Call to action. + """ + + call_to_action: ( + gage_call_to_action_type.CallToActionTypeEnum.CallToActionType + ) = proto.Field( + proto.ENUM, + number=1, + enum=gage_call_to_action_type.CallToActionTypeEnum.CallToActionType, + ) + + +class DynamicRealEstateAsset(proto.Message): + r"""A dynamic real estate asset. + + Attributes: + listing_id (str): + Required. Listing ID which can be any + sequence of letters and digits, and must be + unique and match the values of remarketing tag. + Required. + listing_name (str): + Required. Listing name, for example, + Boulevard Bungalow. Required. + city_name (str): + City name, for example, Mountain View, + California. + description (str): + Description, for example, 3 beds, 2 baths, + 1568 sq. ft. + address (str): + Address which can be specified in one of the + following formats. (1) City, state, code, + country, for example, Mountain View, CA, USA. + (2) Full address, for example, 123 Boulevard St, + Mountain View, CA 94043. (3) Latitude-longitude + in the DDD format, for example, 41.40338, + 2.17403 + price (str): + Price which can be number followed by the + alphabetic currency code, ISO 4217 standard. Use + '.' as the decimal mark, for example, 200,000.00 + USD. + image_url (str): + Image URL, for example, + http://www.example.com/image.png. The image will + not be uploaded as image asset. + property_type (str): + Property type, for example, House. + listing_type (str): + Listing type, for example, For sale. + contextual_keywords (MutableSequence[str]): + Contextual keywords, for example, For sale; + Houses for sale. + formatted_price (str): + Formatted price which can be any characters. + If set, this attribute will be used instead of + 'price', for example, Starting at $200,000.00. + android_app_link (str): + Android deep link, for example, + android-app://com.example.android/http/example.com/gizmos?1234. + ios_app_link (str): + iOS deep link, for example, + exampleApp://content/page. + ios_app_store_id (int): + iOS app store ID. This is used to check if the user has the + app installed on their device before deep linking. If this + field is set, then the ios_app_link field must also be + present. + similar_listing_ids (MutableSequence[str]): + Similar listing IDs. + """ + + listing_id: str = proto.Field( + proto.STRING, + number=1, + ) + listing_name: str = proto.Field( + proto.STRING, + number=2, + ) + city_name: str = proto.Field( + proto.STRING, + number=3, + ) + description: str = proto.Field( + proto.STRING, + number=4, + ) + address: str = proto.Field( + proto.STRING, + number=5, + ) + price: str = proto.Field( + proto.STRING, + number=6, + ) + image_url: str = proto.Field( + proto.STRING, + number=7, + ) + property_type: str = proto.Field( + proto.STRING, + number=8, + ) + listing_type: str = proto.Field( + proto.STRING, + number=9, + ) + contextual_keywords: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=10, + ) + formatted_price: str = proto.Field( + proto.STRING, + number=11, + ) + android_app_link: str = proto.Field( + proto.STRING, + number=12, + ) + ios_app_link: str = proto.Field( + proto.STRING, + number=13, + ) + ios_app_store_id: int = proto.Field( + proto.INT64, + number=14, + ) + similar_listing_ids: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=15, + ) + + +class DynamicCustomAsset(proto.Message): + r"""A dynamic custom asset. + + Attributes: + id (str): + Required. ID which can be any sequence of + letters and digits, and must be unique and match + the values of remarketing tag, for example, + sedan. Required. + id2 (str): + ID2 which can be any sequence of letters and + digits, for example, red. ID sequence (ID + ID2) + must be unique. + item_title (str): + Required. Item title, for example, Mid-size + sedan. Required. + item_subtitle (str): + Item subtitle, for example, At your Mountain + View dealership. + item_description (str): + Item description, for example, Best selling + mid-size car. + item_address (str): + Item address which can be specified in one of + the following formats. (1) City, state, code, + country, for example, Mountain View, CA, USA. + (2) Full address, for example, 123 Boulevard St, + Mountain View, CA 94043. (3) Latitude-longitude + in the DDD format, for example, 41.40338, + 2.17403 + item_category (str): + Item category, for example, Sedans. + price (str): + Price which can be number followed by the + alphabetic currency code, ISO 4217 standard. Use + '.' as the decimal mark, for example, 20,000.00 + USD. + sale_price (str): + Sale price which can be number followed by + the alphabetic currency code, ISO 4217 standard. + Use '.' as the decimal mark, for example, + 15,000.00 USD. Must be less than the 'price' + field. + formatted_price (str): + Formatted price which can be any characters. + If set, this attribute will be used instead of + 'price', for example, Starting at $20,000.00. + formatted_sale_price (str): + Formatted sale price which can be any + characters. If set, this attribute will be used + instead of 'sale price', for example, On sale + for $15,000.00. + image_url (str): + Image URL, for example, + http://www.example.com/image.png. The image will + not be uploaded as image asset. + contextual_keywords (MutableSequence[str]): + Contextual keywords, for example, Sedans, 4 + door sedans. + android_app_link (str): + Android deep link, for example, + android-app://com.example.android/http/example.com/gizmos?1234. + ios_app_link (str): + iOS deep link, for example, + exampleApp://content/page. + ios_app_store_id (int): + iOS app store ID. This is used to check if the user has the + app installed on their device before deep linking. If this + field is set, then the ios_app_link field must also be + present. + similar_ids (MutableSequence[str]): + Similar IDs. + """ + + id: str = proto.Field( + proto.STRING, + number=1, + ) + id2: str = proto.Field( + proto.STRING, + number=2, + ) + item_title: str = proto.Field( + proto.STRING, + number=3, + ) + item_subtitle: str = proto.Field( + proto.STRING, + number=4, + ) + item_description: str = proto.Field( + proto.STRING, + number=5, + ) + item_address: str = proto.Field( + proto.STRING, + number=6, + ) + item_category: str = proto.Field( + proto.STRING, + number=7, + ) + price: str = proto.Field( + proto.STRING, + number=8, + ) + sale_price: str = proto.Field( + proto.STRING, + number=9, + ) + formatted_price: str = proto.Field( + proto.STRING, + number=10, + ) + formatted_sale_price: str = proto.Field( + proto.STRING, + number=11, + ) + image_url: str = proto.Field( + proto.STRING, + number=12, + ) + contextual_keywords: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=13, + ) + android_app_link: str = proto.Field( + proto.STRING, + number=14, + ) + ios_app_link: str = proto.Field( + proto.STRING, + number=16, + ) + ios_app_store_id: int = proto.Field( + proto.INT64, + number=17, + ) + similar_ids: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=15, + ) + + +class DynamicHotelsAndRentalsAsset(proto.Message): + r"""A dynamic hotels and rentals asset. + + Attributes: + property_id (str): + Required. Property ID which can be any + sequence of letters and digits, and must be + unique and match the values of remarketing tag. + Required. + property_name (str): + Required. Property name, for example, + Mountain View Hotel. Required. + image_url (str): + Image URL, for example, + http://www.example.com/image.png. The image will + not be uploaded as image asset. + destination_name (str): + Destination name, for example, Downtown + Mountain View. + description (str): + Description, for example, Close to SJC + Airport. + price (str): + Price which can be number followed by the + alphabetic currency code, ISO 4217 standard. Use + '.' as the decimal mark, for example, 100.00 + USD. + sale_price (str): + ISO 4217 standard. Use '.' as the decimal + mark, for example, 80.00 USD. Must be less than + the 'price' field. + star_rating (int): + Star rating. Must be a number between 1 to 5, + inclusive. + category (str): + Category, for example, Hotel suite. + contextual_keywords (MutableSequence[str]): + Contextual keywords, for example, Mountain + View "Hotels", South Bay hotels. + address (str): + Address which can be specified in one of the + following formats. (1) City, state, code, + country, for example, Mountain View, CA, USA. + (2) Full address, for example, 123 Boulevard St, + Mountain View, CA 94043. (3) Latitude-longitude + in the DDD format, for example, 41.40338, + 2.17403 + android_app_link (str): + Android deep link, for example, + android-app://com.example.android/http/example.com/gizmos?1234. + ios_app_link (str): + iOS deep link, for example, + exampleApp://content/page. + ios_app_store_id (int): + iOS app store ID. This is used to check if the user has the + app installed on their device before deep linking. If this + field is set, then the ios_app_link field must also be + present. + formatted_price (str): + Formatted price which can be any characters. + If set, this attribute will be used instead of + 'price', for example, Starting at $100.00. + formatted_sale_price (str): + Formatted sale price which can be any + characters. If set, this attribute will be used + instead of 'sale price', for example, On sale + for $80.00. + similar_property_ids (MutableSequence[str]): + Similar property IDs. + """ + + property_id: str = proto.Field( + proto.STRING, + number=1, + ) + property_name: str = proto.Field( + proto.STRING, + number=2, + ) + image_url: str = proto.Field( + proto.STRING, + number=3, + ) + destination_name: str = proto.Field( + proto.STRING, + number=4, + ) + description: str = proto.Field( + proto.STRING, + number=5, + ) + price: str = proto.Field( + proto.STRING, + number=6, + ) + sale_price: str = proto.Field( + proto.STRING, + number=7, + ) + star_rating: int = proto.Field( + proto.INT64, + number=8, + ) + category: str = proto.Field( + proto.STRING, + number=9, + ) + contextual_keywords: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=10, + ) + address: str = proto.Field( + proto.STRING, + number=11, + ) + android_app_link: str = proto.Field( + proto.STRING, + number=12, + ) + ios_app_link: str = proto.Field( + proto.STRING, + number=13, + ) + ios_app_store_id: int = proto.Field( + proto.INT64, + number=14, + ) + formatted_price: str = proto.Field( + proto.STRING, + number=15, + ) + formatted_sale_price: str = proto.Field( + proto.STRING, + number=16, + ) + similar_property_ids: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=17, + ) + + +class DynamicFlightsAsset(proto.Message): + r"""A dynamic flights asset. + + Attributes: + destination_id (str): + Required. Destination ID which can be any + sequence of letters and digits, and must be + unique and match the values of remarketing tag. + Required. + origin_id (str): + Origin ID which can be any sequence of + letters and digits. The ID sequence (destination + ID + origin ID) must be unique. + flight_description (str): + Required. Flight description, for example, + Book your ticket. Required. + image_url (str): + Image URL, for example, + http://www.example.com/image.png. The image will + not be uploaded as image asset. + destination_name (str): + Destination name, for example, Paris. + origin_name (str): + Origin name, for example, London. + flight_price (str): + Flight price which can be number followed by + the alphabetic currency code, ISO 4217 standard. + Use '.' as the decimal mark, for example, 100.00 + USD. + flight_sale_price (str): + Flight sale price which can be number followed by the + alphabetic currency code, ISO 4217 standard. Use '.' as the + decimal mark, for example, 80.00 USD. Must be less than the + 'flight_price' field. + formatted_price (str): + Formatted price which can be any characters. + If set, this attribute will be used instead of + 'price', for example, Starting at $100.00. + formatted_sale_price (str): + Formatted sale price which can be any + characters. If set, this attribute will be used + instead of 'sale price', for example, On sale + for $80.00. + android_app_link (str): + Android deep link, for example, + android-app://com.example.android/http/example.com/gizmos?1234. + ios_app_link (str): + iOS deep link, for example, + exampleApp://content/page. + ios_app_store_id (int): + iOS app store ID. This is used to check if the user has the + app installed on their device before deep linking. If this + field is set, then the ios_app_link field must also be + present. + similar_destination_ids (MutableSequence[str]): + Similar destination IDs, for example, + PAR,LON. + custom_mapping (str): + A custom field which can be multiple key to values mapping + separated by delimiters (",", "\|" and ":"), in the forms of + ": , , ... , \| : + , ... , \| ... \| : , ... + ," for example, wifi: most \| aircraft: 320, 77W \| + flights: 42 \| legroom: 32". + """ + + destination_id: str = proto.Field( + proto.STRING, + number=1, + ) + origin_id: str = proto.Field( + proto.STRING, + number=2, + ) + flight_description: str = proto.Field( + proto.STRING, + number=3, + ) + image_url: str = proto.Field( + proto.STRING, + number=4, + ) + destination_name: str = proto.Field( + proto.STRING, + number=5, + ) + origin_name: str = proto.Field( + proto.STRING, + number=6, + ) + flight_price: str = proto.Field( + proto.STRING, + number=7, + ) + flight_sale_price: str = proto.Field( + proto.STRING, + number=8, + ) + formatted_price: str = proto.Field( + proto.STRING, + number=9, + ) + formatted_sale_price: str = proto.Field( + proto.STRING, + number=10, + ) + android_app_link: str = proto.Field( + proto.STRING, + number=11, + ) + ios_app_link: str = proto.Field( + proto.STRING, + number=12, + ) + ios_app_store_id: int = proto.Field( + proto.INT64, + number=13, + ) + similar_destination_ids: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=14, + ) + custom_mapping: str = proto.Field( + proto.STRING, + number=15, + ) + + +class DemandGenCarouselCardAsset(proto.Message): + r"""A Demand Gen Carousel Card asset. + + Attributes: + marketing_image_asset (str): + Asset resource name of the associated 1.91:1 + marketing image. This and/or square marketing + image asset is required. + square_marketing_image_asset (str): + Asset resource name of the associated square + marketing image. This and/or a marketing image + asset is required. + portrait_marketing_image_asset (str): + Asset resource name of the associated 4:5 + portrait marketing image. + headline (str): + Required. Headline of the carousel card. + call_to_action_text (str): + Call to action text. + """ + + marketing_image_asset: str = proto.Field( + proto.STRING, + number=1, + ) + square_marketing_image_asset: str = proto.Field( + proto.STRING, + number=2, + ) + portrait_marketing_image_asset: str = proto.Field( + proto.STRING, + number=3, + ) + headline: str = proto.Field( + proto.STRING, + number=4, + ) + call_to_action_text: str = proto.Field( + proto.STRING, + number=5, + ) + + +class DynamicTravelAsset(proto.Message): + r"""A dynamic travel asset. + + Attributes: + destination_id (str): + Required. Destination ID which can be any + sequence of letters and digits, and must be + unique and match the values of remarketing tag. + Required. + origin_id (str): + Origin ID which can be any sequence of + letters and digits. The ID sequence (destination + ID + origin ID) must be unique. + title (str): + Required. Title, for example, Book your train + ticket. Required. + destination_name (str): + Destination name, for example, Paris. + destination_address (str): + Destination address which can be specified in + one of the following formats. (1) City, state, + code, country, for example, Mountain View, CA, + USA. (2) Full address, for example, 123 + Boulevard St, Mountain View, CA 94043. (3) + Latitude-longitude in the DDD format, for + example, 41.40338, 2.17403. + origin_name (str): + Origin name, for example, London. + price (str): + Price which can be a number followed by the + alphabetic currency code, ISO 4217 standard. Use + '.' as the decimal mark, for example, 100.00 + USD. + sale_price (str): + Sale price which can be a number followed by + the alphabetic currency code, ISO 4217 standard. + Use '.' as the decimal mark, for example, 80.00 + USD. Must be less than the 'price' field. + formatted_price (str): + Formatted price which can be any characters. + If set, this attribute will be used instead of + 'price', for example, Starting at $100.00. + formatted_sale_price (str): + Formatted sale price which can be any + characters. If set, this attribute will be used + instead of 'sale price', for example, On sale + for $80.00. + category (str): + Category, for example, Express. + contextual_keywords (MutableSequence[str]): + Contextual keywords, for example, Paris + trains. + similar_destination_ids (MutableSequence[str]): + Similar destination IDs, for example, NYC. + image_url (str): + Image URL, for example, + http://www.example.com/image.png. The image will + not be uploaded as image asset. + android_app_link (str): + Android deep link, for example, + android-app://com.example.android/http/example.com/gizmos?1234. + ios_app_link (str): + iOS deep link, for example, + exampleApp://content/page. + ios_app_store_id (int): + iOS app store ID. This is used to check if the user has the + app installed on their device before deep linking. If this + field is set, then the ios_app_link field must also be + present. + """ + + destination_id: str = proto.Field( + proto.STRING, + number=1, + ) + origin_id: str = proto.Field( + proto.STRING, + number=2, + ) + title: str = proto.Field( + proto.STRING, + number=3, + ) + destination_name: str = proto.Field( + proto.STRING, + number=4, + ) + destination_address: str = proto.Field( + proto.STRING, + number=5, + ) + origin_name: str = proto.Field( + proto.STRING, + number=6, + ) + price: str = proto.Field( + proto.STRING, + number=7, + ) + sale_price: str = proto.Field( + proto.STRING, + number=8, + ) + formatted_price: str = proto.Field( + proto.STRING, + number=9, + ) + formatted_sale_price: str = proto.Field( + proto.STRING, + number=10, + ) + category: str = proto.Field( + proto.STRING, + number=11, + ) + contextual_keywords: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=12, + ) + similar_destination_ids: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=13, + ) + image_url: str = proto.Field( + proto.STRING, + number=14, + ) + android_app_link: str = proto.Field( + proto.STRING, + number=15, + ) + ios_app_link: str = proto.Field( + proto.STRING, + number=16, + ) + ios_app_store_id: int = proto.Field( + proto.INT64, + number=17, + ) + + +class DynamicLocalAsset(proto.Message): + r"""A dynamic local asset. + + Attributes: + deal_id (str): + Required. Deal ID which can be any sequence + of letters and digits, and must be unique and + match the values of remarketing tag. Required. + deal_name (str): + Required. Deal name, for example, 50% off at + Mountain View Grocers. Required. + subtitle (str): + Subtitle, for example, Groceries. + description (str): + Description, for example, Save on your weekly + bill. + price (str): + Price which can be a number followed by the + alphabetic currency code, ISO 4217 standard. Use + '.' as the decimal mark, for example, 100.00 + USD. + sale_price (str): + Sale price which can be number followed by + the alphabetic currency code, ISO 4217 standard. + Use '.' as the decimal mark, for example, 80.00 + USD. Must be less than the 'price' field. + image_url (str): + Image URL, for example, + http://www.example.com/image.png. The image will + not be uploaded as image asset. + address (str): + Address which can be specified in one of the + following formats. (1) City, state, code, + country, for example, Mountain View, CA, USA. + (2) Full address, for example, 123 Boulevard St, + Mountain View, CA 94043. (3) Latitude-longitude + in the DDD format, for example, 41.40338, + 2.17403. + category (str): + Category, for example, Food. + contextual_keywords (MutableSequence[str]): + Contextual keywords, for example, Save + groceries coupons. + formatted_price (str): + Formatted price which can be any characters. + If set, this attribute will be used instead of + 'price', for example, Starting at $100.00. + formatted_sale_price (str): + Formatted sale price which can be any + characters. If set, this attribute will be used + instead of 'sale price', for example, On sale + for $80.00. + android_app_link (str): + Android deep link, for example, + android-app://com.example.android/http/example.com/gizmos?1234. + similar_deal_ids (MutableSequence[str]): + Similar deal IDs, for example, 1275. + ios_app_link (str): + iOS deep link, for example, + exampleApp://content/page. + ios_app_store_id (int): + iOS app store ID. This is used to check if the user has the + app installed on their device before deep linking. If this + field is set, then the ios_app_link field must also be + present. + """ + + deal_id: str = proto.Field( + proto.STRING, + number=1, + ) + deal_name: str = proto.Field( + proto.STRING, + number=2, + ) + subtitle: str = proto.Field( + proto.STRING, + number=3, + ) + description: str = proto.Field( + proto.STRING, + number=4, + ) + price: str = proto.Field( + proto.STRING, + number=5, + ) + sale_price: str = proto.Field( + proto.STRING, + number=6, + ) + image_url: str = proto.Field( + proto.STRING, + number=7, + ) + address: str = proto.Field( + proto.STRING, + number=8, + ) + category: str = proto.Field( + proto.STRING, + number=9, + ) + contextual_keywords: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=10, + ) + formatted_price: str = proto.Field( + proto.STRING, + number=11, + ) + formatted_sale_price: str = proto.Field( + proto.STRING, + number=12, + ) + android_app_link: str = proto.Field( + proto.STRING, + number=13, + ) + similar_deal_ids: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=14, + ) + ios_app_link: str = proto.Field( + proto.STRING, + number=15, + ) + ios_app_store_id: int = proto.Field( + proto.INT64, + number=16, + ) + + +class DynamicJobsAsset(proto.Message): + r"""A dynamic jobs asset. + + Attributes: + job_id (str): + Required. Job ID which can be any sequence of + letters and digits, and must be unique and match + the values of remarketing tag. Required. + location_id (str): + Location ID which can be any sequence of + letters and digits. The ID sequence (job ID + + location ID) must be unique. + job_title (str): + Required. Job title, for example, Software + engineer. Required. + job_subtitle (str): + Job subtitle, for example, Level II. + description (str): + Description, for example, Apply your + technical skills. + image_url (str): + Image URL, for example, + http://www.example.com/image.png. The image will + not be uploaded as image asset. + job_category (str): + Job category, for example, Technical. + contextual_keywords (MutableSequence[str]): + Contextual keywords, for example, Software + engineering job. + address (str): + Address which can be specified in one of the + following formats. (1) City, state, code, + country, for example, Mountain View, CA, USA. + (2) Full address, for example, 123 Boulevard St, + Mountain View, CA 94043. (3) Latitude-longitude + in the DDD format, for example, 41.40338, + 2.17403. + salary (str): + Salary, for example, $100,000. + android_app_link (str): + Android deep link, for example, + android-app://com.example.android/http/example.com/gizmos?1234. + similar_job_ids (MutableSequence[str]): + Similar job IDs, for example, 1275. + ios_app_link (str): + iOS deep link, for example, + exampleApp://content/page. + ios_app_store_id (int): + iOS app store ID. This is used to check if the user has the + app installed on their device before deep linking. If this + field is set, then the ios_app_link field must also be + present. + """ + + job_id: str = proto.Field( + proto.STRING, + number=1, + ) + location_id: str = proto.Field( + proto.STRING, + number=2, + ) + job_title: str = proto.Field( + proto.STRING, + number=3, + ) + job_subtitle: str = proto.Field( + proto.STRING, + number=4, + ) + description: str = proto.Field( + proto.STRING, + number=5, + ) + image_url: str = proto.Field( + proto.STRING, + number=6, + ) + job_category: str = proto.Field( + proto.STRING, + number=7, + ) + contextual_keywords: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=8, + ) + address: str = proto.Field( + proto.STRING, + number=9, + ) + salary: str = proto.Field( + proto.STRING, + number=10, + ) + android_app_link: str = proto.Field( + proto.STRING, + number=11, + ) + similar_job_ids: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=12, + ) + ios_app_link: str = proto.Field( + proto.STRING, + number=13, + ) + ios_app_store_id: int = proto.Field( + proto.INT64, + number=14, + ) + + +class LocationAsset(proto.Message): + r"""A location asset. + + Attributes: + place_id (str): + Place IDs uniquely identify a place in the + Google Places database and on Google Maps. + This field is unique for a given customer ID and + asset type. See + https://developers.google.com/places/web-service/place-id + to learn more about Place ID. + business_profile_locations (MutableSequence[google.ads.googleads.v24.common.types.BusinessProfileLocation]): + The list of business locations for the + customer. This will only be returned if the + Location Asset is syncing from the Business + Profile account. It is possible to have multiple + Business Profile listings under the same account + that point to the same Place ID. + location_ownership_type (google.ads.googleads.v24.enums.types.LocationOwnershipTypeEnum.LocationOwnershipType): + The type of location ownership. If the type is + BUSINESS_OWNER, it will be served as a location extension. + If the type is AFFILIATE, it will be served as an affiliate + location. + """ + + place_id: str = proto.Field( + proto.STRING, + number=1, + ) + business_profile_locations: MutableSequence["BusinessProfileLocation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="BusinessProfileLocation", + ) + ) + location_ownership_type: ( + gage_location_ownership_type.LocationOwnershipTypeEnum.LocationOwnershipType + ) = proto.Field( + proto.ENUM, + number=3, + enum=gage_location_ownership_type.LocationOwnershipTypeEnum.LocationOwnershipType, + ) + + +class BusinessProfileLocation(proto.Message): + r"""Business Profile location data synced from the linked + Business Profile account. + + Attributes: + labels (MutableSequence[str]): + Advertiser specified label for the location + on the Business Profile account. This is synced + from the Business Profile account. + store_code (str): + Business Profile store code of this location. + This is synced from the Business Profile + account. + listing_id (int): + Listing ID of this Business Profile location. + This is synced from the linked Business Profile + account. + """ + + labels: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + store_code: str = proto.Field( + proto.STRING, + number=2, + ) + listing_id: int = proto.Field( + proto.INT64, + number=3, + ) + + +class HotelPropertyAsset(proto.Message): + r"""A hotel property asset. + + Attributes: + place_id (str): + Place IDs uniquely identify a place in the + Google Places database and on Google Maps. See + https://developers.google.com/places/web-service/place-id + to learn more. + hotel_address (str): + Address of the hotel. Read-only. + hotel_name (str): + Name of the hotel. Read-only. + """ + + place_id: str = proto.Field( + proto.STRING, + number=1, + ) + hotel_address: str = proto.Field( + proto.STRING, + number=2, + ) + hotel_name: str = proto.Field( + proto.STRING, + number=3, + ) + + +class BusinessMessageAsset(proto.Message): + r"""A business message asset. + + 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: + message_provider (google.ads.googleads.v24.enums.types.BusinessMessageProviderEnum.BusinessMessageProvider): + Required. Message provider of the business + message asset. + starter_message (str): + Required. A welcome message to prompt the + user to initiate a conversation. + call_to_action (google.ads.googleads.v24.common.types.BusinessMessageCallToActionInfo): + A call to action for the business message + asset. + + This field is a member of `oneof`_ ``_call_to_action``. + whatsapp_info (google.ads.googleads.v24.common.types.WhatsappBusinessMessageInfo): + Whatsapp. + + This field is a member of `oneof`_ ``message_provider_data``. + facebook_messenger_info (google.ads.googleads.v24.common.types.FacebookMessengerBusinessMessageInfo): + Facebook Messenger. + + This field is a member of `oneof`_ ``message_provider_data``. + zalo_info (google.ads.googleads.v24.common.types.ZaloBusinessMessageInfo): + Zalo. + + This field is a member of `oneof`_ ``message_provider_data``. + """ + + message_provider: ( + business_message_provider.BusinessMessageProviderEnum.BusinessMessageProvider + ) = proto.Field( + proto.ENUM, + number=1, + enum=business_message_provider.BusinessMessageProviderEnum.BusinessMessageProvider, + ) + starter_message: str = proto.Field( + proto.STRING, + number=2, + ) + call_to_action: "BusinessMessageCallToActionInfo" = proto.Field( + proto.MESSAGE, + number=3, + optional=True, + message="BusinessMessageCallToActionInfo", + ) + whatsapp_info: "WhatsappBusinessMessageInfo" = proto.Field( + proto.MESSAGE, + number=5, + oneof="message_provider_data", + message="WhatsappBusinessMessageInfo", + ) + facebook_messenger_info: "FacebookMessengerBusinessMessageInfo" = ( + proto.Field( + proto.MESSAGE, + number=6, + oneof="message_provider_data", + message="FacebookMessengerBusinessMessageInfo", + ) + ) + zalo_info: "ZaloBusinessMessageInfo" = proto.Field( + proto.MESSAGE, + number=7, + oneof="message_provider_data", + message="ZaloBusinessMessageInfo", + ) + + +class WhatsappBusinessMessageInfo(proto.Message): + r"""Whatsapp information to use for messaging. + + Attributes: + country_code (str): + Required. Two-letter country code of the + phone number. Examples: 'US', 'us'. + phone_number (str): + Required. Whatsapp phone number of the + business. Examples: '1234567890', + '(123)456-7890'. + """ + + country_code: str = proto.Field( + proto.STRING, + number=1, + ) + phone_number: str = proto.Field( + proto.STRING, + number=2, + ) + + +class FacebookMessengerBusinessMessageInfo(proto.Message): + r"""Facebook Messenger information to use for messaging. + + Attributes: + page_name (str): + Required. Facebook page name used for + starting a chat on Facebook Messenger. + """ + + page_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class ZaloBusinessMessageInfo(proto.Message): + r"""Zalo information to use for messaging. + + 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: + oa_id (int): + Zalo Official Account ID of the advertiser. + + This field is a member of `oneof`_ ``zalo_id``. + custom_name (str): + Custom name generated by the advertiser for + their Zalo Account. These names will usually be + registered brands or trademarks. + + This field is a member of `oneof`_ ``zalo_id``. + """ + + oa_id: int = proto.Field( + proto.INT64, + number=1, + oneof="zalo_id", + ) + custom_name: str = proto.Field( + proto.STRING, + number=2, + oneof="zalo_id", + ) + + +class BusinessMessageCallToActionInfo(proto.Message): + r"""Display information that encourages the user to take action. + + Attributes: + call_to_action_selection (google.ads.googleads.v24.enums.types.BusinessMessageCallToActionTypeEnum.BusinessMessageCallToActionType): + Required. Pre-defined call to action text. + call_to_action_description (str): + Required. Text providing a clear value + proposition of what users expect once they take + the action. Examples: 'Message us for a quote', + 'Ask our expert team'. + """ + + call_to_action_selection: ( + business_message_call_to_action_type.BusinessMessageCallToActionTypeEnum.BusinessMessageCallToActionType + ) = proto.Field( + proto.ENUM, + number=1, + enum=business_message_call_to_action_type.BusinessMessageCallToActionTypeEnum.BusinessMessageCallToActionType, + ) + call_to_action_description: str = proto.Field( + proto.STRING, + number=2, + ) + + +class AppDeepLinkAsset(proto.Message): + r"""An app deep link asset + + Attributes: + app_deep_link_uri (str): + The uri for the app deep link, The uri can be + either a custom scheme uri (e.g. + mystore://shoes) or universal uri (e.g. + http://www.mystore.com/shoes). + """ + + app_deep_link_uri: str = proto.Field( + proto.STRING, + number=1, + ) + + +class YouTubeVideoListAsset(proto.Message): + r"""A YouTube video list asset. + + Attributes: + youtube_videos (MutableSequence[google.ads.googleads.v24.common.types.AdVideoAsset]): + List of videos. Each is a reference to a + YouTube video asset. Minimum of 2 videos + required and maximum of 5 allowed. + """ + + youtube_videos: MutableSequence[ad_asset.AdVideoAsset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=ad_asset.AdVideoAsset, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/asset_usage.py b/google/ads/googleads/v24/common/types/asset_usage.py new file mode 100644 index 000000000..9081a8557 --- /dev/null +++ b/google/ads/googleads/v24/common/types/asset_usage.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + served_asset_field_type as gage_served_asset_field_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "AssetUsage", + }, +) + + +class AssetUsage(proto.Message): + r"""Contains the usage information of the asset. + + Attributes: + asset (str): + Resource name of the asset. + served_asset_field_type (google.ads.googleads.v24.enums.types.ServedAssetFieldTypeEnum.ServedAssetFieldType): + The served field type of the asset. + """ + + asset: str = proto.Field( + proto.STRING, + number=1, + ) + served_asset_field_type: ( + gage_served_asset_field_type.ServedAssetFieldTypeEnum.ServedAssetFieldType + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_served_asset_field_type.ServedAssetFieldTypeEnum.ServedAssetFieldType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/audience_insights_attribute.py b/google/ads/googleads/v24/common/types/audience_insights_attribute.py new file mode 100644 index 000000000..2285c665f --- /dev/null +++ b/google/ads/googleads/v24/common/types/audience_insights_attribute.py @@ -0,0 +1,676 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.enums.types import audience_insights_dimension +from google.ads.googleads.v24.enums.types import ( + insights_knowledge_graph_entity_capabilities, +) +from google.ads.googleads.v24.enums.types import ( + user_list_type as gage_user_list_type, +) +from google.ads.googleads.v24.enums.types import youtube_video_property + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "AudienceInsightsAttributeMetadata", + "AudienceInsightsAttribute", + "AudienceInsightsEntity", + "AudienceInsightsCategory", + "AudienceInsightsLineup", + "YouTubeChannelAttributeMetadata", + "YouTubeVideoAttributeMetadata", + "LineupAttributeMetadata", + "LocationAttributeMetadata", + "UserInterestAttributeMetadata", + "KnowledgeGraphAttributeMetadata", + "UserListAttributeMetadata", + "AudienceInsightsAttributeMetadataGroup", + "InsightsAudienceAttributeGroup", + }, +) + + +class AudienceInsightsAttributeMetadata(proto.Message): + r"""An audience attribute, with metadata about it, returned in + response to a search. + + 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: + dimension (google.ads.googleads.v24.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension): + The type of the attribute. + attribute (google.ads.googleads.v24.common.types.AudienceInsightsAttribute): + The attribute itself. + display_name (str): + The human-readable name of the attribute. + display_info (str): + A string that supplements the display_name to identify the + attribute. If the dimension is TOPIC, this is a brief + description of the Knowledge Graph entity, such as "American + singer-songwriter". If the dimension is CATEGORY, this is + the complete path to the category in The Product & Service + taxonomy, for example "/Apparel/Clothing/Outerwear". + potential_youtube_reach (int): + An estimate of the number of reachable + YouTube users matching this attribute in the + requested location, or zero if that information + is not available for this attribute. This field + is not populated in every response. + subscriber_share (float): + The share of subscribers within this + attribute, between and including 0 and + 1. This field is not populated in every + response. + viewer_share (float): + The share of viewers within this attribute, + between and including 0 and + 1. This field is not populated in every + response. + youtube_channel_metadata (google.ads.googleads.v24.common.types.YouTubeChannelAttributeMetadata): + Special metadata for a YouTube channel. + + This field is a member of `oneof`_ ``dimension_metadata``. + youtube_video_metadata (google.ads.googleads.v24.common.types.YouTubeVideoAttributeMetadata): + Special metadata for a YouTube video. + + This field is a member of `oneof`_ ``dimension_metadata``. + lineup_attribute_metadata (google.ads.googleads.v24.common.types.LineupAttributeMetadata): + Special metadata for a YouTube Lineup. + + This field is a member of `oneof`_ ``dimension_metadata``. + location_attribute_metadata (google.ads.googleads.v24.common.types.LocationAttributeMetadata): + Special metadata for a Location. + + This field is a member of `oneof`_ ``dimension_metadata``. + user_interest_attribute_metadata (google.ads.googleads.v24.common.types.UserInterestAttributeMetadata): + Special metadata for a User Interest. + + This field is a member of `oneof`_ ``dimension_metadata``. + knowledge_graph_attribute_metadata (google.ads.googleads.v24.common.types.KnowledgeGraphAttributeMetadata): + Special metadata for a Knowledge Graph + Entity. + + This field is a member of `oneof`_ ``dimension_metadata``. + user_list_attribute_metadata (google.ads.googleads.v24.common.types.UserListAttributeMetadata): + Special metadata for a User List. + + This field is a member of `oneof`_ ``dimension_metadata``. + """ + + dimension: ( + audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension + ) = proto.Field( + proto.ENUM, + number=1, + enum=audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension, + ) + attribute: "AudienceInsightsAttribute" = proto.Field( + proto.MESSAGE, + number=2, + message="AudienceInsightsAttribute", + ) + display_name: str = proto.Field( + proto.STRING, + number=3, + ) + display_info: str = proto.Field( + proto.STRING, + number=4, + ) + potential_youtube_reach: int = proto.Field( + proto.INT64, + number=8, + ) + subscriber_share: float = proto.Field( + proto.DOUBLE, + number=9, + ) + viewer_share: float = proto.Field( + proto.DOUBLE, + number=13, + ) + youtube_channel_metadata: "YouTubeChannelAttributeMetadata" = proto.Field( + proto.MESSAGE, + number=5, + oneof="dimension_metadata", + message="YouTubeChannelAttributeMetadata", + ) + youtube_video_metadata: "YouTubeVideoAttributeMetadata" = proto.Field( + proto.MESSAGE, + number=10, + oneof="dimension_metadata", + message="YouTubeVideoAttributeMetadata", + ) + lineup_attribute_metadata: "LineupAttributeMetadata" = proto.Field( + proto.MESSAGE, + number=14, + oneof="dimension_metadata", + message="LineupAttributeMetadata", + ) + location_attribute_metadata: "LocationAttributeMetadata" = proto.Field( + proto.MESSAGE, + number=7, + oneof="dimension_metadata", + message="LocationAttributeMetadata", + ) + user_interest_attribute_metadata: "UserInterestAttributeMetadata" = ( + proto.Field( + proto.MESSAGE, + number=11, + oneof="dimension_metadata", + message="UserInterestAttributeMetadata", + ) + ) + knowledge_graph_attribute_metadata: "KnowledgeGraphAttributeMetadata" = ( + proto.Field( + proto.MESSAGE, + number=12, + oneof="dimension_metadata", + message="KnowledgeGraphAttributeMetadata", + ) + ) + user_list_attribute_metadata: "UserListAttributeMetadata" = proto.Field( + proto.MESSAGE, + number=15, + oneof="dimension_metadata", + message="UserListAttributeMetadata", + ) + + +class AudienceInsightsAttribute(proto.Message): + r"""An audience attribute that can be used to request insights about the + audience. Valid inputs for these fields are available from + [AudienceInsightsService.ListAudienceInsightsAttributes][google.ads.googleads.v24.services.AudienceInsightsService.ListAudienceInsightsAttributes]. + + 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: + age_range (google.ads.googleads.v24.common.types.AgeRangeInfo): + An audience attribute defined by an age + range. + + This field is a member of `oneof`_ ``attribute``. + gender (google.ads.googleads.v24.common.types.GenderInfo): + An audience attribute defined by a gender. + + This field is a member of `oneof`_ ``attribute``. + location (google.ads.googleads.v24.common.types.LocationInfo): + An audience attribute defined by a geographic + location. + + This field is a member of `oneof`_ ``attribute``. + user_interest (google.ads.googleads.v24.common.types.UserInterestInfo): + An Affinity or In-Market audience. + + This field is a member of `oneof`_ ``attribute``. + entity (google.ads.googleads.v24.common.types.AudienceInsightsEntity): + An audience attribute defined by interest in + a topic represented by a Knowledge Graph entity. + + This field is a member of `oneof`_ ``attribute``. + category (google.ads.googleads.v24.common.types.AudienceInsightsCategory): + An audience attribute defined by interest in + a Product & Service category. + + This field is a member of `oneof`_ ``attribute``. + lineup (google.ads.googleads.v24.common.types.AudienceInsightsLineup): + A YouTube Lineup. + + This field is a member of `oneof`_ ``attribute``. + parental_status (google.ads.googleads.v24.common.types.ParentalStatusInfo): + A Parental Status value (parent, or not a + parent). + + This field is a member of `oneof`_ ``attribute``. + income_range (google.ads.googleads.v24.common.types.IncomeRangeInfo): + A household income percentile range. + + This field is a member of `oneof`_ ``attribute``. + youtube_channel (google.ads.googleads.v24.common.types.YouTubeChannelInfo): + A YouTube channel. + + This field is a member of `oneof`_ ``attribute``. + youtube_video (google.ads.googleads.v24.common.types.YouTubeVideoInfo): + A YouTube video. + + This field is a member of `oneof`_ ``attribute``. + device (google.ads.googleads.v24.common.types.DeviceInfo): + A device type. (Mobile, Desktop, Tablet) + + This field is a member of `oneof`_ ``attribute``. + user_list (google.ads.googleads.v24.common.types.UserListInfo): + A User List. + + This field is a member of `oneof`_ ``attribute``. + """ + + age_range: criteria.AgeRangeInfo = proto.Field( + proto.MESSAGE, + number=1, + oneof="attribute", + message=criteria.AgeRangeInfo, + ) + gender: criteria.GenderInfo = proto.Field( + proto.MESSAGE, + number=2, + oneof="attribute", + message=criteria.GenderInfo, + ) + location: criteria.LocationInfo = proto.Field( + proto.MESSAGE, + number=3, + oneof="attribute", + message=criteria.LocationInfo, + ) + user_interest: criteria.UserInterestInfo = proto.Field( + proto.MESSAGE, + number=4, + oneof="attribute", + message=criteria.UserInterestInfo, + ) + entity: "AudienceInsightsEntity" = proto.Field( + proto.MESSAGE, + number=5, + oneof="attribute", + message="AudienceInsightsEntity", + ) + category: "AudienceInsightsCategory" = proto.Field( + proto.MESSAGE, + number=6, + oneof="attribute", + message="AudienceInsightsCategory", + ) + lineup: "AudienceInsightsLineup" = proto.Field( + proto.MESSAGE, + number=13, + oneof="attribute", + message="AudienceInsightsLineup", + ) + parental_status: criteria.ParentalStatusInfo = proto.Field( + proto.MESSAGE, + number=8, + oneof="attribute", + message=criteria.ParentalStatusInfo, + ) + income_range: criteria.IncomeRangeInfo = proto.Field( + proto.MESSAGE, + number=9, + oneof="attribute", + message=criteria.IncomeRangeInfo, + ) + youtube_channel: criteria.YouTubeChannelInfo = proto.Field( + proto.MESSAGE, + number=10, + oneof="attribute", + message=criteria.YouTubeChannelInfo, + ) + youtube_video: criteria.YouTubeVideoInfo = proto.Field( + proto.MESSAGE, + number=11, + oneof="attribute", + message=criteria.YouTubeVideoInfo, + ) + device: criteria.DeviceInfo = proto.Field( + proto.MESSAGE, + number=12, + oneof="attribute", + message=criteria.DeviceInfo, + ) + user_list: criteria.UserListInfo = proto.Field( + proto.MESSAGE, + number=14, + oneof="attribute", + message=criteria.UserListInfo, + ) + + +class AudienceInsightsEntity(proto.Message): + r"""A Knowledge Graph entity, represented by its machine id. + + Attributes: + knowledge_graph_machine_id (str): + Required. The machine ID (mid) of the + Knowledge Graph entity. + """ + + knowledge_graph_machine_id: str = proto.Field( + proto.STRING, + number=1, + ) + + +class AudienceInsightsCategory(proto.Message): + r"""A Product and Service category. + + Attributes: + category_id (str): + Required. The criterion ID of the category. + """ + + category_id: str = proto.Field( + proto.STRING, + number=1, + ) + + +class AudienceInsightsLineup(proto.Message): + r"""A YouTube Lineup. + + Attributes: + lineup_id (str): + Required. The numeric ID of the lineup. + """ + + lineup_id: str = proto.Field( + proto.STRING, + number=1, + ) + + +class YouTubeChannelAttributeMetadata(proto.Message): + r"""Metadata associated with a YouTube channel attribute. + + Attributes: + subscriber_count (int): + The approximate number of subscribers to the + YouTube channel. + """ + + subscriber_count: int = proto.Field( + proto.INT64, + number=1, + ) + + +class YouTubeVideoAttributeMetadata(proto.Message): + r"""Metadata for a YouTube video attribute. + + Attributes: + thumbnail_url (str): + The URL of the video thumbnail, prefixed by + "https://img.youtube.com/". + video_url (str): + The URL of the video, prefixed by + "https://www.youtube.com/". + views_count (int): + The total number of views. + likes_count (int): + The total number of likes. + comments_count (int): + The total number of comments. + video_properties (MutableSequence[google.ads.googleads.v24.enums.types.YouTubeVideoPropertyEnum.YouTubeVideoProperty]): + The properties of this video (such as shorts, + live stream). + publish_date (str): + The date that the video was created. + Formatted as "yyyy-mm-dd". + """ + + thumbnail_url: str = proto.Field( + proto.STRING, + number=1, + ) + video_url: str = proto.Field( + proto.STRING, + number=2, + ) + views_count: int = proto.Field( + proto.INT64, + number=3, + ) + likes_count: int = proto.Field( + proto.INT64, + number=4, + ) + comments_count: int = proto.Field( + proto.INT64, + number=5, + ) + video_properties: MutableSequence[ + youtube_video_property.YouTubeVideoPropertyEnum.YouTubeVideoProperty + ] = proto.RepeatedField( + proto.ENUM, + number=6, + enum=youtube_video_property.YouTubeVideoPropertyEnum.YouTubeVideoProperty, + ) + publish_date: str = proto.Field( + proto.STRING, + number=7, + ) + + +class LineupAttributeMetadata(proto.Message): + r"""Metadata associated with a Lineup attribute. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + inventory_country (google.ads.googleads.v24.common.types.LocationInfo): + The national market associated with the + lineup. + median_monthly_inventory (int): + The median number of impressions per month on + this lineup. + + This field is a member of `oneof`_ ``_median_monthly_inventory``. + channel_count_lower_bound (int): + The lower end of a range containing the + number of channels in the lineup. + + This field is a member of `oneof`_ ``_channel_count_lower_bound``. + channel_count_upper_bound (int): + The upper end of a range containing the + number of channels in the lineup. + + This field is a member of `oneof`_ ``_channel_count_upper_bound``. + sample_channels (MutableSequence[google.ads.googleads.v24.common.types.LineupAttributeMetadata.SampleChannel]): + Examples of channels that are included in the + lineup. + """ + + class SampleChannel(proto.Message): + r"""A YouTube channel returned as an example of the content in a + lineup. + + Attributes: + youtube_channel (google.ads.googleads.v24.common.types.YouTubeChannelInfo): + A YouTube channel. + display_name (str): + The name of the sample channel. + youtube_channel_metadata (google.ads.googleads.v24.common.types.YouTubeChannelAttributeMetadata): + Metadata for the sample channel. + """ + + youtube_channel: criteria.YouTubeChannelInfo = proto.Field( + proto.MESSAGE, + number=1, + message=criteria.YouTubeChannelInfo, + ) + display_name: str = proto.Field( + proto.STRING, + number=2, + ) + youtube_channel_metadata: "YouTubeChannelAttributeMetadata" = ( + proto.Field( + proto.MESSAGE, + number=3, + message="YouTubeChannelAttributeMetadata", + ) + ) + + inventory_country: criteria.LocationInfo = proto.Field( + proto.MESSAGE, + number=1, + message=criteria.LocationInfo, + ) + median_monthly_inventory: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + channel_count_lower_bound: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + channel_count_upper_bound: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + sample_channels: MutableSequence[SampleChannel] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message=SampleChannel, + ) + + +class LocationAttributeMetadata(proto.Message): + r"""Metadata associated with a Location attribute. + + Attributes: + country_location (google.ads.googleads.v24.common.types.LocationInfo): + The country location that this attribute’s + sub country location is located in. + """ + + country_location: criteria.LocationInfo = proto.Field( + proto.MESSAGE, + number=1, + message=criteria.LocationInfo, + ) + + +class UserInterestAttributeMetadata(proto.Message): + r"""Metadata associated with a User Interest attribute. + + Attributes: + user_interest_description (str): + English language text description of the user + interest category (200 characters max). + """ + + user_interest_description: str = proto.Field( + proto.STRING, + number=1, + ) + + +class KnowledgeGraphAttributeMetadata(proto.Message): + r"""Metadata associated with a Knowledge Graph Entity attribute. + + Attributes: + entity_capabilities (MutableSequence[google.ads.googleads.v24.enums.types.InsightsKnowledgeGraphEntityCapabilitiesEnum.InsightsKnowledgeGraphEntityCapabilities]): + The capabilities of the entity used in + [ContentCreatorInsightsService][google.ads.googleads.v24.services.ContentCreatorInsightsService]. + related_categories (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadata]): + A list of CATEGORY attributes related to this + entity. + """ + + entity_capabilities: MutableSequence[ + insights_knowledge_graph_entity_capabilities.InsightsKnowledgeGraphEntityCapabilitiesEnum.InsightsKnowledgeGraphEntityCapabilities + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum=insights_knowledge_graph_entity_capabilities.InsightsKnowledgeGraphEntityCapabilitiesEnum.InsightsKnowledgeGraphEntityCapabilities, + ) + related_categories: MutableSequence["AudienceInsightsAttributeMetadata"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AudienceInsightsAttributeMetadata", + ) + ) + + +class UserListAttributeMetadata(proto.Message): + r"""Metadata associated with a User List attribute. + + Attributes: + user_list_type (google.ads.googleads.v24.enums.types.UserListTypeEnum.UserListType): + The user list type. + """ + + user_list_type: gage_user_list_type.UserListTypeEnum.UserListType = ( + proto.Field( + proto.ENUM, + number=1, + enum=gage_user_list_type.UserListTypeEnum.UserListType, + ) + ) + + +class AudienceInsightsAttributeMetadataGroup(proto.Message): + r"""A group of audience attributes with metadata, returned in + response to a search. + + Attributes: + attributes (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadata]): + Attributes with metadata returned in response + to a search. + """ + + attributes: MutableSequence["AudienceInsightsAttributeMetadata"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="AudienceInsightsAttributeMetadata", + ) + ) + + +class InsightsAudienceAttributeGroup(proto.Message): + r"""A list of AudienceInsightsAttributes. + + Attributes: + attributes (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttribute]): + Required. A collection of audience attributes + combined with logical OR. Attributes need not + all be the same dimension. Only Knowledge Graph + entities, Product & Service Categories, and user + interests are supported in this context. + """ + + attributes: MutableSequence["AudienceInsightsAttribute"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="AudienceInsightsAttribute", + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/audiences.py b/google/ads/googleads/v24/common/types/audiences.py new file mode 100644 index 000000000..e2a7de4d4 --- /dev/null +++ b/google/ads/googleads/v24/common/types/audiences.py @@ -0,0 +1,478 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import gender_type +from google.ads.googleads.v24.enums.types import income_range_type +from google.ads.googleads.v24.enums.types import parental_status_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "AudienceDimension", + "AudienceExclusionDimension", + "ExclusionSegment", + "AgeDimension", + "AgeSegment", + "GenderDimension", + "HouseholdIncomeDimension", + "ParentalStatusDimension", + "AudienceSegmentDimension", + "AudienceSegment", + "UserListSegment", + "UserInterestSegment", + "LifeEventSegment", + "DetailedDemographicSegment", + "CustomAudienceSegment", + }, +) + + +class AudienceDimension(proto.Message): + r"""Positive dimension specifying user's audience. + + 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: + age (google.ads.googleads.v24.common.types.AgeDimension): + Dimension specifying users by their age. + + This field is a member of `oneof`_ ``dimension``. + gender (google.ads.googleads.v24.common.types.GenderDimension): + Dimension specifying users by their gender. + + This field is a member of `oneof`_ ``dimension``. + household_income (google.ads.googleads.v24.common.types.HouseholdIncomeDimension): + Dimension specifying users by their household + income. + + This field is a member of `oneof`_ ``dimension``. + parental_status (google.ads.googleads.v24.common.types.ParentalStatusDimension): + Dimension specifying users by their parental + status. + + This field is a member of `oneof`_ ``dimension``. + audience_segments (google.ads.googleads.v24.common.types.AudienceSegmentDimension): + Dimension specifying users by their + membership in other audience segments. + + This field is a member of `oneof`_ ``dimension``. + """ + + age: "AgeDimension" = proto.Field( + proto.MESSAGE, + number=1, + oneof="dimension", + message="AgeDimension", + ) + gender: "GenderDimension" = proto.Field( + proto.MESSAGE, + number=2, + oneof="dimension", + message="GenderDimension", + ) + household_income: "HouseholdIncomeDimension" = proto.Field( + proto.MESSAGE, + number=3, + oneof="dimension", + message="HouseholdIncomeDimension", + ) + parental_status: "ParentalStatusDimension" = proto.Field( + proto.MESSAGE, + number=4, + oneof="dimension", + message="ParentalStatusDimension", + ) + audience_segments: "AudienceSegmentDimension" = proto.Field( + proto.MESSAGE, + number=5, + oneof="dimension", + message="AudienceSegmentDimension", + ) + + +class AudienceExclusionDimension(proto.Message): + r"""Negative dimension specifying users to exclude from the + audience. + + Attributes: + exclusions (MutableSequence[google.ads.googleads.v24.common.types.ExclusionSegment]): + Audience segment to be excluded. + """ + + exclusions: MutableSequence["ExclusionSegment"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ExclusionSegment", + ) + + +class ExclusionSegment(proto.Message): + r"""An audience segment to be excluded from an audience. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + user_list (google.ads.googleads.v24.common.types.UserListSegment): + User list segment to be excluded. + + This field is a member of `oneof`_ ``segment``. + """ + + user_list: "UserListSegment" = proto.Field( + proto.MESSAGE, + number=1, + oneof="segment", + message="UserListSegment", + ) + + +class AgeDimension(proto.Message): + r"""Dimension specifying users by their age. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + age_ranges (MutableSequence[google.ads.googleads.v24.common.types.AgeSegment]): + Contiguous age range to be included in the + dimension. + include_undetermined (bool): + Include users whose age is not determined. + + This field is a member of `oneof`_ ``_include_undetermined``. + """ + + age_ranges: MutableSequence["AgeSegment"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="AgeSegment", + ) + include_undetermined: bool = proto.Field( + proto.BOOL, + number=2, + optional=True, + ) + + +class AgeSegment(proto.Message): + r"""Contiguous age range. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + min_age (int): + Minimum age to include. A minimum age must be + specified and must be at least 18. Allowed + values are 18, 25, 35, 45, 55, and 65. + + This field is a member of `oneof`_ ``_min_age``. + max_age (int): + Maximum age to include. A maximum age need not be specified. + If specified, max_age must be greater than min_age, and + allowed values are 24, 34, 44, 54, and 64. + + This field is a member of `oneof`_ ``_max_age``. + """ + + min_age: int = proto.Field( + proto.INT32, + number=1, + optional=True, + ) + max_age: int = proto.Field( + proto.INT32, + number=2, + optional=True, + ) + + +class GenderDimension(proto.Message): + r"""Dimension specifying users by their gender. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + genders (MutableSequence[google.ads.googleads.v24.enums.types.GenderTypeEnum.GenderType]): + Included gender demographic segments. + include_undetermined (bool): + Include users whose gender is not determined. + + This field is a member of `oneof`_ ``_include_undetermined``. + """ + + genders: MutableSequence[gender_type.GenderTypeEnum.GenderType] = ( + proto.RepeatedField( + proto.ENUM, + number=1, + enum=gender_type.GenderTypeEnum.GenderType, + ) + ) + include_undetermined: bool = proto.Field( + proto.BOOL, + number=2, + optional=True, + ) + + +class HouseholdIncomeDimension(proto.Message): + r"""Dimension specifying users by their household income. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + income_ranges (MutableSequence[google.ads.googleads.v24.enums.types.IncomeRangeTypeEnum.IncomeRangeType]): + Included household income demographic + segments. + include_undetermined (bool): + Include users whose household income is not + determined. + + This field is a member of `oneof`_ ``_include_undetermined``. + """ + + income_ranges: MutableSequence[ + income_range_type.IncomeRangeTypeEnum.IncomeRangeType + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum=income_range_type.IncomeRangeTypeEnum.IncomeRangeType, + ) + include_undetermined: bool = proto.Field( + proto.BOOL, + number=2, + optional=True, + ) + + +class ParentalStatusDimension(proto.Message): + r"""Dimension specifying users by their parental status. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + parental_statuses (MutableSequence[google.ads.googleads.v24.enums.types.ParentalStatusTypeEnum.ParentalStatusType]): + Included parental status demographic + segments. + include_undetermined (bool): + Include users whose parental status is + undetermined. + + This field is a member of `oneof`_ ``_include_undetermined``. + """ + + parental_statuses: MutableSequence[ + parental_status_type.ParentalStatusTypeEnum.ParentalStatusType + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum=parental_status_type.ParentalStatusTypeEnum.ParentalStatusType, + ) + include_undetermined: bool = proto.Field( + proto.BOOL, + number=2, + optional=True, + ) + + +class AudienceSegmentDimension(proto.Message): + r"""Dimension specifying users by their membership in other + audience segments. + + Attributes: + segments (MutableSequence[google.ads.googleads.v24.common.types.AudienceSegment]): + Included audience segments. Users are + included if they belong to at least one segment. + """ + + segments: MutableSequence["AudienceSegment"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="AudienceSegment", + ) + + +class AudienceSegment(proto.Message): + r"""Positive audience segment. + + 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: + user_list (google.ads.googleads.v24.common.types.UserListSegment): + User list segment. + + This field is a member of `oneof`_ ``segment``. + user_interest (google.ads.googleads.v24.common.types.UserInterestSegment): + Affinity or In-market segment. + + This field is a member of `oneof`_ ``segment``. + life_event (google.ads.googleads.v24.common.types.LifeEventSegment): + Live-event audience segment. + + This field is a member of `oneof`_ ``segment``. + detailed_demographic (google.ads.googleads.v24.common.types.DetailedDemographicSegment): + Detailed demographic segment. + + This field is a member of `oneof`_ ``segment``. + custom_audience (google.ads.googleads.v24.common.types.CustomAudienceSegment): + Custom audience segment. + + This field is a member of `oneof`_ ``segment``. + """ + + user_list: "UserListSegment" = proto.Field( + proto.MESSAGE, + number=1, + oneof="segment", + message="UserListSegment", + ) + user_interest: "UserInterestSegment" = proto.Field( + proto.MESSAGE, + number=2, + oneof="segment", + message="UserInterestSegment", + ) + life_event: "LifeEventSegment" = proto.Field( + proto.MESSAGE, + number=3, + oneof="segment", + message="LifeEventSegment", + ) + detailed_demographic: "DetailedDemographicSegment" = proto.Field( + proto.MESSAGE, + number=4, + oneof="segment", + message="DetailedDemographicSegment", + ) + custom_audience: "CustomAudienceSegment" = proto.Field( + proto.MESSAGE, + number=5, + oneof="segment", + message="CustomAudienceSegment", + ) + + +class UserListSegment(proto.Message): + r"""User list segment. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + user_list (str): + The user list resource. + + This field is a member of `oneof`_ ``_user_list``. + """ + + user_list: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class UserInterestSegment(proto.Message): + r"""User interest segment. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + user_interest_category (str): + The user interest resource. + + This field is a member of `oneof`_ ``_user_interest_category``. + """ + + user_interest_category: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class LifeEventSegment(proto.Message): + r"""Live event segment. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + life_event (str): + The life event resource. + + This field is a member of `oneof`_ ``_life_event``. + """ + + life_event: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class DetailedDemographicSegment(proto.Message): + r"""Detailed demographic segment. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + detailed_demographic (str): + The detailed demographic resource. + + This field is a member of `oneof`_ ``_detailed_demographic``. + """ + + detailed_demographic: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class CustomAudienceSegment(proto.Message): + r"""Custom audience segment. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + custom_audience (str): + The custom audience resource. + + This field is a member of `oneof`_ ``_custom_audience``. + """ + + custom_audience: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/bidding.py b/google/ads/googleads/v24/common/types/bidding.py new file mode 100644 index 000000000..219f0d5a0 --- /dev/null +++ b/google/ads/googleads/v24/common/types/bidding.py @@ -0,0 +1,599 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import fixed_cpm_goal +from google.ads.googleads.v24.enums.types import ( + fixed_cpm_target_frequency_time_unit, +) +from google.ads.googleads.v24.enums.types import target_frequency_time_unit +from google.ads.googleads.v24.enums.types import ( + target_impression_share_location, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "Commission", + "EnhancedCpc", + "ManualCpa", + "ManualCpc", + "ManualCpm", + "ManualCpv", + "MaximizeConversions", + "MaximizeConversionValue", + "TargetCpa", + "TargetCpm", + "TargetCpmTargetFrequencyGoal", + "TargetImpressionShare", + "TargetRoas", + "TargetSpend", + "PercentCpc", + "FixedCpm", + "FixedCpmTargetFrequencyGoalInfo", + "TargetCpv", + "TargetCpc", + }, +) + + +class Commission(proto.Message): + r"""Commission is an automatic bidding strategy in which the + advertiser pays a certain portion of the conversion value. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + commission_rate_micros (int): + Commission rate defines the portion of the conversion value + that the advertiser will be billed. A commission rate of x + should be passed into this field as (x \* 1,000,000). For + example, 106,000 represents a commission rate of 0.106 + (10.6%). + + This field is a member of `oneof`_ ``_commission_rate_micros``. + """ + + commission_rate_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + +class EnhancedCpc(proto.Message): + r"""An automated bidding strategy that raises bids for clicks that seem + more likely to lead to a conversion and lowers them for clicks where + they seem less likely. + + This bidding strategy is deprecated and cannot be created anymore. + Use ManualCpc with enhanced_cpc_enabled set to true for equivalent + functionality. + + """ + + +class ManualCpa(proto.Message): + r"""Manual bidding strategy that allows advertiser to set the bid + per advertiser-specified action. + + """ + + +class ManualCpc(proto.Message): + r"""Manual click-based bidding where user pays per click. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + enhanced_cpc_enabled (bool): + Whether bids are to be enhanced based on + conversion optimizer data. + + This field is a member of `oneof`_ ``_enhanced_cpc_enabled``. + """ + + enhanced_cpc_enabled: bool = proto.Field( + proto.BOOL, + number=2, + optional=True, + ) + + +class ManualCpm(proto.Message): + r"""Manual impression-based bidding where user pays per thousand + impressions. + + """ + + +class ManualCpv(proto.Message): + r"""View based bidding where user pays per video view.""" + + +class MaximizeConversions(proto.Message): + r"""An automated bidding strategy to help get the most + conversions for your campaigns while spending your budget. + + Attributes: + cpc_bid_ceiling_micros (int): + Maximum bid limit that can be set by the bid + strategy. The limit applies to all keywords + managed by the strategy. Mutable for portfolio + bidding strategies only. + cpc_bid_floor_micros (int): + Minimum bid limit that can be set by the bid + strategy. The limit applies to all keywords + managed by the strategy. Mutable for portfolio + bidding strategies only. + target_cpa_micros (int): + The target cost-per-action (CPA) option. This + is the average amount that you would like to + spend per conversion action specified in micro + units of the bidding strategy's currency. If + set, the bid strategy will get as many + conversions as possible at or below the target + cost-per-action. If the target CPA is not set, + the bid strategy will aim to achieve the lowest + possible CPA given the budget. + """ + + cpc_bid_ceiling_micros: int = proto.Field( + proto.INT64, + number=2, + ) + cpc_bid_floor_micros: int = proto.Field( + proto.INT64, + number=3, + ) + target_cpa_micros: int = proto.Field( + proto.INT64, + number=4, + ) + + +class MaximizeConversionValue(proto.Message): + r"""An automated bidding strategy to help get the most conversion + value for your campaigns while spending your budget. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_roas (float): + The target return on ad spend (ROAS) option. + If set, the bid strategy will maximize revenue + while averaging the target return on ad spend. + If the target ROAS is high, the bid strategy may + not be able to spend the full budget. If the + target ROAS is not set, the bid strategy will + aim to achieve the highest possible ROAS for the + budget. + cpc_bid_ceiling_micros (int): + Maximum bid limit that can be set by the bid + strategy. The limit applies to all keywords + managed by the strategy. Mutable for portfolio + bidding strategies only. + cpc_bid_floor_micros (int): + Minimum bid limit that can be set by the bid + strategy. The limit applies to all keywords + managed by the strategy. Mutable for portfolio + bidding strategies only. + target_roas_tolerance_percent_millis (int): + The percent of ROAS(return on advertising + spend) degradation tolerance allowed to increase + traffic diversity and conversion volume, + specified in millis (for example, 10,000 = 10%). + A value of 10,000 means that the advertiser can + expect ROAS degradation of up to 10% of the + specified target ROAS. + + This field is a member of `oneof`_ ``_target_roas_tolerance_percent_millis``. + """ + + target_roas: float = proto.Field( + proto.DOUBLE, + number=2, + ) + cpc_bid_ceiling_micros: int = proto.Field( + proto.INT64, + number=3, + ) + cpc_bid_floor_micros: int = proto.Field( + proto.INT64, + number=4, + ) + target_roas_tolerance_percent_millis: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + + +class TargetCpa(proto.Message): + r"""An automated bid strategy that sets bids to help get as many + conversions as possible at the target cost-per-acquisition (CPA) + you set. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_cpa_micros (int): + Average CPA target. + This target should be greater than or equal to + minimum billable unit based on the currency for + the account. + + This field is a member of `oneof`_ ``_target_cpa_micros``. + cpc_bid_ceiling_micros (int): + Maximum bid limit that can be set by the bid + strategy. The limit applies to all keywords + managed by the strategy. This should only be set + for portfolio bid strategies. + + This field is a member of `oneof`_ ``_cpc_bid_ceiling_micros``. + cpc_bid_floor_micros (int): + Minimum bid limit that can be set by the bid + strategy. The limit applies to all keywords + managed by the strategy. This should only be set + for portfolio bid strategies. + + This field is a member of `oneof`_ ``_cpc_bid_floor_micros``. + """ + + target_cpa_micros: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + cpc_bid_ceiling_micros: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + cpc_bid_floor_micros: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + + +class TargetCpm(proto.Message): + r"""Target CPM (cost per thousand impressions) is an automated + bidding strategy that sets bids to optimize performance given + the target CPM you set. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_frequency_goal (google.ads.googleads.v24.common.types.TargetCpmTargetFrequencyGoal): + Target Frequency bidding goal details. + + This field is a member of `oneof`_ ``goal``. + """ + + target_frequency_goal: "TargetCpmTargetFrequencyGoal" = proto.Field( + proto.MESSAGE, + number=1, + oneof="goal", + message="TargetCpmTargetFrequencyGoal", + ) + + +class TargetCpmTargetFrequencyGoal(proto.Message): + r"""Target Frequency bidding goal details. + + Attributes: + target_count (int): + Target Frequency count representing how many + times you want to reach a single user. + time_unit (google.ads.googleads.v24.enums.types.TargetFrequencyTimeUnitEnum.TargetFrequencyTimeUnit): + Time window expressing the period over which you want to + reach the specified target_count. + """ + + target_count: int = proto.Field( + proto.INT64, + number=1, + ) + time_unit: ( + target_frequency_time_unit.TargetFrequencyTimeUnitEnum.TargetFrequencyTimeUnit + ) = proto.Field( + proto.ENUM, + number=2, + enum=target_frequency_time_unit.TargetFrequencyTimeUnitEnum.TargetFrequencyTimeUnit, + ) + + +class TargetImpressionShare(proto.Message): + r"""An automated bidding strategy that sets bids so that a + certain percentage of search ads are shown at the top of the + first page (or other targeted location). + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + location (google.ads.googleads.v24.enums.types.TargetImpressionShareLocationEnum.TargetImpressionShareLocation): + The targeted location on the search results + page. + location_fraction_micros (int): + The chosen fraction of ads to be shown in the + targeted location in micros. For example, 1% + equals 10,000. + + This field is a member of `oneof`_ ``_location_fraction_micros``. + cpc_bid_ceiling_micros (int): + The highest CPC bid the automated bidding + system is permitted to specify. This is a + required field entered by the advertiser that + sets the ceiling and specified in local micros. + + This field is a member of `oneof`_ ``_cpc_bid_ceiling_micros``. + """ + + location: ( + target_impression_share_location.TargetImpressionShareLocationEnum.TargetImpressionShareLocation + ) = proto.Field( + proto.ENUM, + number=1, + enum=target_impression_share_location.TargetImpressionShareLocationEnum.TargetImpressionShareLocation, + ) + location_fraction_micros: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + cpc_bid_ceiling_micros: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + + +class TargetRoas(proto.Message): + r"""An automated bidding strategy that helps you maximize revenue + while averaging a specific target return on ad spend (ROAS). + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_roas (float): + Required. The chosen revenue (based on + conversion data) per unit of spend. Value must + be between 0.01 and 1000.0, inclusive. + + This field is a member of `oneof`_ ``_target_roas``. + cpc_bid_ceiling_micros (int): + Maximum bid limit that can be set by the bid + strategy. The limit applies to all keywords + managed by the strategy. This should only be set + for portfolio bid strategies. + + This field is a member of `oneof`_ ``_cpc_bid_ceiling_micros``. + cpc_bid_floor_micros (int): + Minimum bid limit that can be set by the bid + strategy. The limit applies to all keywords + managed by the strategy. This should only be set + for portfolio bid strategies. + + This field is a member of `oneof`_ ``_cpc_bid_floor_micros``. + target_roas_tolerance_percent_millis (int): + The percent of ROAS(return on advertising + spend) degradation tolerance allowed to increase + traffic diversity and conversion volume, + specified in millis (for example, 10,000 = 10%). + A value of 10,000 means that the advertiser can + expect ROAS degradation of up to 10% of the + specified target ROAS. This field is only + mutable for portfolio bidding strategies. + + This field is a member of `oneof`_ ``_target_roas_tolerance_percent_millis``. + """ + + target_roas: float = proto.Field( + proto.DOUBLE, + number=4, + optional=True, + ) + cpc_bid_ceiling_micros: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + cpc_bid_floor_micros: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + target_roas_tolerance_percent_millis: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + + +class TargetSpend(proto.Message): + r"""An automated bid strategy that sets your bids to help get as + many clicks as possible within your budget. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_spend_micros (int): + Deprecated: The spend target under which to + maximize clicks. A TargetSpend bidder will + attempt to spend the smaller of this value or + the natural throttling spend amount. + If not specified, the budget is used as the + spend target. This field is deprecated and + should no longer be used. See + https://ads-developers.googleblog.com/2020/05/reminder-about-sunset-creation-of.html + for details. + + This field is a member of `oneof`_ ``_target_spend_micros``. + cpc_bid_ceiling_micros (int): + Maximum bid limit that can be set by the bid + strategy. The limit applies to all keywords + managed by the strategy. + + This field is a member of `oneof`_ ``_cpc_bid_ceiling_micros``. + """ + + target_spend_micros: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + cpc_bid_ceiling_micros: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + + +class PercentCpc(proto.Message): + r"""A bidding strategy where bids are a fraction of the + advertised price for some good or service. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + cpc_bid_ceiling_micros (int): + Maximum bid limit that can be set by the bid strategy. This + is an optional field entered by the advertiser and specified + in local micros. Note: A zero value is interpreted in the + same way as having bid_ceiling undefined. + + This field is a member of `oneof`_ ``_cpc_bid_ceiling_micros``. + enhanced_cpc_enabled (bool): + Adjusts the bid for each auction upward or downward, + depending on the likelihood of a conversion. Individual bids + may exceed cpc_bid_ceiling_micros, but the average bid + amount for a campaign should not. + + This field is a member of `oneof`_ ``_enhanced_cpc_enabled``. + """ + + cpc_bid_ceiling_micros: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + enhanced_cpc_enabled: bool = proto.Field( + proto.BOOL, + number=4, + optional=True, + ) + + +class FixedCpm(proto.Message): + r"""Fixed CPM (cost per thousand impression) bidding strategy. A + manual bidding strategy with a fixed CPM. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + goal (google.ads.googleads.v24.enums.types.FixedCpmGoalEnum.FixedCpmGoal): + Fixed CPM bidding goal. Determines the exact + bidding optimization parameters. + target_frequency_info (google.ads.googleads.v24.common.types.FixedCpmTargetFrequencyGoalInfo): + Target frequency bidding goal details. + + This field is a member of `oneof`_ ``goal_info``. + """ + + goal: fixed_cpm_goal.FixedCpmGoalEnum.FixedCpmGoal = proto.Field( + proto.ENUM, + number=1, + enum=fixed_cpm_goal.FixedCpmGoalEnum.FixedCpmGoal, + ) + target_frequency_info: "FixedCpmTargetFrequencyGoalInfo" = proto.Field( + proto.MESSAGE, + number=2, + oneof="goal_info", + message="FixedCpmTargetFrequencyGoalInfo", + ) + + +class FixedCpmTargetFrequencyGoalInfo(proto.Message): + r"""Target frequency bidding goal details for Fixed CPM bidding + strategy. Only relevant if the goal of the bidding strategy is + ``TARGET_FREQUENCY``. + + Attributes: + target_count (int): + Target frequency count represents the number + of times an advertiser wants to show the ad to + target a single user. + time_unit (google.ads.googleads.v24.enums.types.FixedCpmTargetFrequencyTimeUnitEnum.FixedCpmTargetFrequencyTimeUnit): + Time window expressing the period over which you want to + reach the specified target_count. + """ + + target_count: int = proto.Field( + proto.INT64, + number=1, + ) + time_unit: ( + fixed_cpm_target_frequency_time_unit.FixedCpmTargetFrequencyTimeUnitEnum.FixedCpmTargetFrequencyTimeUnit + ) = proto.Field( + proto.ENUM, + number=2, + enum=fixed_cpm_target_frequency_time_unit.FixedCpmTargetFrequencyTimeUnitEnum.FixedCpmTargetFrequencyTimeUnit, + ) + + +class TargetCpv(proto.Message): + r"""Target CPV (cost per view) bidding strategy. An automated + bidding strategy that sets bids to optimize performance given + the target CPV you set. + + """ + + +class TargetCpc(proto.Message): + r"""An automated bidding strategy that sets bids to help get as + many clicks as possible at the target cost-per-click (CPC) you + set. + + Attributes: + target_cpc_micros (int): + Average CPC target. + This target should be greater than or equal to + minimum billable unit based on the currency for + the account. + """ + + target_cpc_micros: int = proto.Field( + proto.INT64, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/campaign_goal_settings.py b/google/ads/googleads/v24/common/types/campaign_goal_settings.py new file mode 100644 index 000000000..fe07cc56a --- /dev/null +++ b/google/ads/googleads/v24/common/types/campaign_goal_settings.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import goal_common +from google.ads.googleads.v24.enums.types import ( + customer_lifecycle_optimization_mode, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignGoalSettings", + }, +) + + +class CampaignGoalSettings(proto.Message): + r"""Campaign Goal settings.""" + + class CampaignRetentionGoalSettings(proto.Message): + r"""Retention campaign goal settings. + + Attributes: + value_settings_override (google.ads.googleads.v24.common.types.CustomerLifecycleOptimizationValueSettings): + Retention goal campaign specific value + settings. + target_option (google.ads.googleads.v24.enums.types.CustomerLifecycleOptimizationModeEnum.CustomerLifecycleOptimizationMode): + Retention goal optimization mode for this campaign. + + Defaults to TARGET_ALL. Only customers on the allowlist can + set target_option. + """ + + value_settings_override: ( + goal_common.CustomerLifecycleOptimizationValueSettings + ) = proto.Field( + proto.MESSAGE, + number=1, + message=goal_common.CustomerLifecycleOptimizationValueSettings, + ) + target_option: ( + customer_lifecycle_optimization_mode.CustomerLifecycleOptimizationModeEnum.CustomerLifecycleOptimizationMode + ) = proto.Field( + proto.ENUM, + number=2, + enum=customer_lifecycle_optimization_mode.CustomerLifecycleOptimizationModeEnum.CustomerLifecycleOptimizationMode, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/campaign_reservation_quote.py b/google/ads/googleads/v24/common/types/campaign_reservation_quote.py new file mode 100644 index 000000000..368a3918a --- /dev/null +++ b/google/ads/googleads/v24/common/types/campaign_reservation_quote.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignReservationQuote", + }, +) + + +class CampaignReservationQuote(proto.Message): + r"""The campaign reservation quote. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + campaign (str): + The campaign resource name, as it was specified in the + request. It could contain a temp ID. Format: + customers/{customer_id}/campaigns/{campaign_id} + max_budget_micros (int): + Maximum budget to get all available + impressions at the current CPM. Capped at 10M + USD. Specified in micros of the advertiser + currency. + possible_hold_duration_seconds (int): + The possible duration of the hold, in + seconds. + suggested_cpm_micros (int): + The CPM that would be accepted for the + campaign calculated at the proposed budget. + Specified in micros of the advertiser currency. + + This field is a member of `oneof`_ ``suggested_quote``. + """ + + campaign: str = proto.Field( + proto.STRING, + number=1, + ) + max_budget_micros: int = proto.Field( + proto.INT64, + number=3, + ) + possible_hold_duration_seconds: int = proto.Field( + proto.INT64, + number=4, + ) + suggested_cpm_micros: int = proto.Field( + proto.INT64, + number=2, + oneof="suggested_quote", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/click_location.py b/google/ads/googleads/v24/common/types/click_location.py new file mode 100644 index 000000000..facdd50a7 --- /dev/null +++ b/google/ads/googleads/v24/common/types/click_location.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "ClickLocation", + }, +) + + +class ClickLocation(proto.Message): + r"""Location criteria associated with a click. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + city (str): + The city location criterion associated with + the impression. + + This field is a member of `oneof`_ ``_city``. + country (str): + The country location criterion associated + with the impression. + + This field is a member of `oneof`_ ``_country``. + metro (str): + The metro location criterion associated with + the impression. + + This field is a member of `oneof`_ ``_metro``. + most_specific (str): + The most specific location criterion + associated with the impression. + + This field is a member of `oneof`_ ``_most_specific``. + region (str): + The region location criterion associated with + the impression. + + This field is a member of `oneof`_ ``_region``. + """ + + city: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + country: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + metro: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + most_specific: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + region: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/consent.py b/google/ads/googleads/v24/common/types/consent.py new file mode 100644 index 000000000..1cbcf8182 --- /dev/null +++ b/google/ads/googleads/v24/common/types/consent.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import consent_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "Consent", + }, +) + + +class Consent(proto.Message): + r"""Consent + + Attributes: + ad_user_data (google.ads.googleads.v24.enums.types.ConsentStatusEnum.ConsentStatus): + This represents consent for ad user data. + ad_personalization (google.ads.googleads.v24.enums.types.ConsentStatusEnum.ConsentStatus): + This represents consent for ad + personalization. This can only be set for + OfflineUserDataJobService and UserDataService. + """ + + ad_user_data: consent_status.ConsentStatusEnum.ConsentStatus = proto.Field( + proto.ENUM, + number=1, + enum=consent_status.ConsentStatusEnum.ConsentStatus, + ) + ad_personalization: consent_status.ConsentStatusEnum.ConsentStatus = ( + proto.Field( + proto.ENUM, + number=2, + enum=consent_status.ConsentStatusEnum.ConsentStatus, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/criteria.py b/google/ads/googleads/v24/common/types/criteria.py new file mode 100644 index 000000000..1ecab6b32 --- /dev/null +++ b/google/ads/googleads/v24/common/types/criteria.py @@ -0,0 +1,2556 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import age_range_type +from google.ads.googleads.v24.enums.types import app_payment_model_type +from google.ads.googleads.v24.enums.types import brand_request_rejection_reason +from google.ads.googleads.v24.enums.types import brand_state +from google.ads.googleads.v24.enums.types import content_label_type +from google.ads.googleads.v24.enums.types import day_of_week as gage_day_of_week +from google.ads.googleads.v24.enums.types import device +from google.ads.googleads.v24.enums.types import gender_type +from google.ads.googleads.v24.enums.types import hotel_date_selection_type +from google.ads.googleads.v24.enums.types import income_range_type +from google.ads.googleads.v24.enums.types import interaction_type +from google.ads.googleads.v24.enums.types import keyword_match_type +from google.ads.googleads.v24.enums.types import listing_group_type +from google.ads.googleads.v24.enums.types import location_group_radius_units +from google.ads.googleads.v24.enums.types import minute_of_hour +from google.ads.googleads.v24.enums.types import parental_status_type +from google.ads.googleads.v24.enums.types import product_category_level +from google.ads.googleads.v24.enums.types import ( + product_channel as gage_product_channel, +) +from google.ads.googleads.v24.enums.types import ( + product_channel_exclusivity as gage_product_channel_exclusivity, +) +from google.ads.googleads.v24.enums.types import ( + product_condition as gage_product_condition, +) +from google.ads.googleads.v24.enums.types import product_custom_attribute_index +from google.ads.googleads.v24.enums.types import product_type_level +from google.ads.googleads.v24.enums.types import proximity_radius_units +from google.ads.googleads.v24.enums.types import webpage_condition_operand +from google.ads.googleads.v24.enums.types import webpage_condition_operator + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordInfo", + "PlacementInfo", + "NegativeKeywordListInfo", + "MobileAppCategoryInfo", + "MobileApplicationInfo", + "LocationInfo", + "DeviceInfo", + "ListingGroupInfo", + "ListingDimensionPath", + "ListingScopeInfo", + "ListingDimensionInfo", + "HotelIdInfo", + "HotelClassInfo", + "HotelCountryRegionInfo", + "HotelStateInfo", + "HotelCityInfo", + "ProductCategoryInfo", + "ProductBrandInfo", + "ProductChannelInfo", + "ProductChannelExclusivityInfo", + "ProductConditionInfo", + "ProductCustomAttributeInfo", + "ProductItemIdInfo", + "ProductTypeInfo", + "ProductGroupingInfo", + "ProductLabelsInfo", + "ProductLegacyConditionInfo", + "ProductTypeFullInfo", + "UnknownListingDimensionInfo", + "HotelDateSelectionTypeInfo", + "HotelAdvanceBookingWindowInfo", + "HotelLengthOfStayInfo", + "HotelCheckInDateRangeInfo", + "HotelCheckInDayInfo", + "ActivityIdInfo", + "ActivityRatingInfo", + "ActivityCountryInfo", + "ActivityStateInfo", + "ActivityCityInfo", + "InteractionTypeInfo", + "AdScheduleInfo", + "AgeRangeInfo", + "GenderInfo", + "IncomeRangeInfo", + "ParentalStatusInfo", + "YouTubeVideoInfo", + "YouTubeChannelInfo", + "UserListInfo", + "ProximityInfo", + "GeoPointInfo", + "AddressInfo", + "TopicInfo", + "LanguageInfo", + "IpBlockInfo", + "ContentLabelInfo", + "CarrierInfo", + "UserInterestInfo", + "WebpageInfo", + "WebpageConditionInfo", + "WebpageListInfo", + "WebpageSampleInfo", + "OperatingSystemVersionInfo", + "AppPaymentModelInfo", + "MobileDeviceInfo", + "CustomAffinityInfo", + "CustomIntentInfo", + "LocationGroupInfo", + "CustomAudienceInfo", + "CombinedAudienceInfo", + "AudienceInfo", + "KeywordThemeInfo", + "LocalServiceIdInfo", + "SearchThemeInfo", + "BrandInfo", + "BrandListInfo", + "LifeEventInfo", + "ExtendedDemographicInfo", + "VideoLineupInfo", + "PlacementListInfo", + "VerticalAdsItemGroupRuleListInfo", + "VerticalAdsItemGroupRuleInfo", + "RetailFilterBundle", + "RetailFilter", + "RetailFilterExpression", + "RetailTag", + }, +) + + +class KeywordInfo(proto.Message): + r"""A keyword criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + text (str): + The text of the keyword (at most 80 + characters and 10 words). + + This field is a member of `oneof`_ ``_text``. + match_type (google.ads.googleads.v24.enums.types.KeywordMatchTypeEnum.KeywordMatchType): + The match type of the keyword. + """ + + text: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + match_type: keyword_match_type.KeywordMatchTypeEnum.KeywordMatchType = ( + proto.Field( + proto.ENUM, + number=2, + enum=keyword_match_type.KeywordMatchTypeEnum.KeywordMatchType, + ) + ) + + +class PlacementInfo(proto.Message): + r"""A placement criterion. This can be used to modify bids for + sites when targeting the content network. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + url (str): + URL of the placement. + + For example, "http://www.domain.com". + + This field is a member of `oneof`_ ``_url``. + """ + + url: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class NegativeKeywordListInfo(proto.Message): + r"""A Negative Keyword List criterion. Represents a shared set + of negative keywords that can be excluded at the account-level. + Only one negative keyword list criterion can be attached per + account. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + shared_set (str): + The NegativeKeywordListInfo shared set + resource name. + + This field is a member of `oneof`_ ``_shared_set``. + """ + + shared_set: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class MobileAppCategoryInfo(proto.Message): + r"""A mobile app category criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + mobile_app_category_constant (str): + The mobile app category constant resource + name. + + This field is a member of `oneof`_ ``_mobile_app_category_constant``. + """ + + mobile_app_category_constant: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class MobileApplicationInfo(proto.Message): + r"""A mobile application criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + app_id (str): + A string that uniquely identifies a mobile application to + Google Ads API. The format of this string is + "{platform}-{platform_native_id}", where platform is "1" for + iOS apps and "2" for Android apps, and where + platform_native_id is the mobile application identifier + native to the corresponding platform. For iOS, this native + identifier is the 9 digit string that appears at the end of + an App Store URL (for example, "476943146" for "Flood-It! 2" + whose App Store link is + "http://itunes.apple.com/us/app/flood-it!-2/id476943146"). + For Android, this native identifier is the application's + package name (for example, "com.labpixies.colordrips" for + "Color Drips" given Google Play link + "https://play.google.com/store/apps/details?id=com.labpixies.colordrips"). + A well formed app id for Google Ads API would thus be + "1-476943146" for iOS and "2-com.labpixies.colordrips" for + Android. This field is required and must be set in CREATE + operations. + + This field is a member of `oneof`_ ``_app_id``. + name (str): + Name of this mobile application. + + This field is a member of `oneof`_ ``_name``. + """ + + app_id: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + + +class LocationInfo(proto.Message): + r"""A location criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + geo_target_constant (str): + The geo target constant resource name. + + This field is a member of `oneof`_ ``_geo_target_constant``. + """ + + geo_target_constant: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class DeviceInfo(proto.Message): + r"""A device criterion. + + Attributes: + type_ (google.ads.googleads.v24.enums.types.DeviceEnum.Device): + Type of the device. + """ + + type_: device.DeviceEnum.Device = proto.Field( + proto.ENUM, + number=1, + enum=device.DeviceEnum.Device, + ) + + +class ListingGroupInfo(proto.Message): + r"""A listing group criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + type_ (google.ads.googleads.v24.enums.types.ListingGroupTypeEnum.ListingGroupType): + Type of the listing group. + case_value (google.ads.googleads.v24.common.types.ListingDimensionInfo): + Dimension value with which this listing group + is refining its parent. Undefined for the root + group. + parent_ad_group_criterion (str): + Resource name of ad group criterion which is + the parent listing group subdivision. Null for + the root group. + + This field is a member of `oneof`_ ``_parent_ad_group_criterion``. + path (google.ads.googleads.v24.common.types.ListingDimensionPath): + The path of dimensions defining this listing + group. + + This field is a member of `oneof`_ ``_path``. + """ + + type_: listing_group_type.ListingGroupTypeEnum.ListingGroupType = ( + proto.Field( + proto.ENUM, + number=1, + enum=listing_group_type.ListingGroupTypeEnum.ListingGroupType, + ) + ) + case_value: "ListingDimensionInfo" = proto.Field( + proto.MESSAGE, + number=2, + message="ListingDimensionInfo", + ) + parent_ad_group_criterion: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + path: "ListingDimensionPath" = proto.Field( + proto.MESSAGE, + number=5, + optional=True, + message="ListingDimensionPath", + ) + + +class ListingDimensionPath(proto.Message): + r"""The path of dimensions defining a listing group. + + Attributes: + dimensions (MutableSequence[google.ads.googleads.v24.common.types.ListingDimensionInfo]): + The complete path of dimensions through the + listing group hierarchy, from the root + (excluding the root itself) to this listing + group. + """ + + dimensions: MutableSequence["ListingDimensionInfo"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ListingDimensionInfo", + ) + + +class ListingScopeInfo(proto.Message): + r"""A listing scope criterion. + + Attributes: + dimensions (MutableSequence[google.ads.googleads.v24.common.types.ListingDimensionInfo]): + Scope of the campaign criterion. + """ + + dimensions: MutableSequence["ListingDimensionInfo"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ListingDimensionInfo", + ) + + +class ListingDimensionInfo(proto.Message): + r"""Listing dimensions for listing group criterion. + + 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: + hotel_id (google.ads.googleads.v24.common.types.HotelIdInfo): + Advertiser-specific hotel ID. + + This field is a member of `oneof`_ ``dimension``. + hotel_class (google.ads.googleads.v24.common.types.HotelClassInfo): + Class of the hotel as a number of stars 1 to + 5. + + This field is a member of `oneof`_ ``dimension``. + hotel_country_region (google.ads.googleads.v24.common.types.HotelCountryRegionInfo): + Country or Region the hotel is located in. + + This field is a member of `oneof`_ ``dimension``. + hotel_state (google.ads.googleads.v24.common.types.HotelStateInfo): + State the hotel is located in. + + This field is a member of `oneof`_ ``dimension``. + hotel_city (google.ads.googleads.v24.common.types.HotelCityInfo): + City the hotel is located in. + + This field is a member of `oneof`_ ``dimension``. + product_category (google.ads.googleads.v24.common.types.ProductCategoryInfo): + Category of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_brand (google.ads.googleads.v24.common.types.ProductBrandInfo): + Brand of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_channel (google.ads.googleads.v24.common.types.ProductChannelInfo): + Locality of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_channel_exclusivity (google.ads.googleads.v24.common.types.ProductChannelExclusivityInfo): + Availability of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_condition (google.ads.googleads.v24.common.types.ProductConditionInfo): + Condition of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_custom_attribute (google.ads.googleads.v24.common.types.ProductCustomAttributeInfo): + Custom attribute of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_item_id (google.ads.googleads.v24.common.types.ProductItemIdInfo): + Item id of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_type (google.ads.googleads.v24.common.types.ProductTypeInfo): + Type of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_grouping (google.ads.googleads.v24.common.types.ProductGroupingInfo): + Grouping of a product offer. This listing + dimension is deprecated and it is supported only + in Display campaigns. + + This field is a member of `oneof`_ ``dimension``. + product_labels (google.ads.googleads.v24.common.types.ProductLabelsInfo): + Labels of a product offer. This listing + dimension is deprecated and it is supported only + in Display campaigns. + + This field is a member of `oneof`_ ``dimension``. + product_legacy_condition (google.ads.googleads.v24.common.types.ProductLegacyConditionInfo): + Legacy condition of a product offer. This + listing dimension is deprecated and it is + supported only in Display campaigns. + + This field is a member of `oneof`_ ``dimension``. + product_type_full (google.ads.googleads.v24.common.types.ProductTypeFullInfo): + Full type of a product offer. This listing + dimension is deprecated and it is supported only + in Display campaigns. + + This field is a member of `oneof`_ ``dimension``. + activity_id (google.ads.googleads.v24.common.types.ActivityIdInfo): + Advertiser-specific activity ID. + + This field is a member of `oneof`_ ``dimension``. + activity_rating (google.ads.googleads.v24.common.types.ActivityRatingInfo): + Rating of the activity as a number 1 to 5, + where 5 is the best. + + This field is a member of `oneof`_ ``dimension``. + activity_country (google.ads.googleads.v24.common.types.ActivityCountryInfo): + The country where the travel activity is + available. + + This field is a member of `oneof`_ ``dimension``. + activity_state (google.ads.googleads.v24.common.types.ActivityStateInfo): + The state where the travel activity is + available. + + This field is a member of `oneof`_ ``dimension``. + activity_city (google.ads.googleads.v24.common.types.ActivityCityInfo): + The city where the travel activity is + available. + + This field is a member of `oneof`_ ``dimension``. + unknown_listing_dimension (google.ads.googleads.v24.common.types.UnknownListingDimensionInfo): + Unknown dimension. Set when no other listing + dimension is set. + + This field is a member of `oneof`_ ``dimension``. + """ + + hotel_id: "HotelIdInfo" = proto.Field( + proto.MESSAGE, + number=2, + oneof="dimension", + message="HotelIdInfo", + ) + hotel_class: "HotelClassInfo" = proto.Field( + proto.MESSAGE, + number=3, + oneof="dimension", + message="HotelClassInfo", + ) + hotel_country_region: "HotelCountryRegionInfo" = proto.Field( + proto.MESSAGE, + number=4, + oneof="dimension", + message="HotelCountryRegionInfo", + ) + hotel_state: "HotelStateInfo" = proto.Field( + proto.MESSAGE, + number=5, + oneof="dimension", + message="HotelStateInfo", + ) + hotel_city: "HotelCityInfo" = proto.Field( + proto.MESSAGE, + number=6, + oneof="dimension", + message="HotelCityInfo", + ) + product_category: "ProductCategoryInfo" = proto.Field( + proto.MESSAGE, + number=24, + oneof="dimension", + message="ProductCategoryInfo", + ) + product_brand: "ProductBrandInfo" = proto.Field( + proto.MESSAGE, + number=15, + oneof="dimension", + message="ProductBrandInfo", + ) + product_channel: "ProductChannelInfo" = proto.Field( + proto.MESSAGE, + number=8, + oneof="dimension", + message="ProductChannelInfo", + ) + product_channel_exclusivity: "ProductChannelExclusivityInfo" = proto.Field( + proto.MESSAGE, + number=9, + oneof="dimension", + message="ProductChannelExclusivityInfo", + ) + product_condition: "ProductConditionInfo" = proto.Field( + proto.MESSAGE, + number=10, + oneof="dimension", + message="ProductConditionInfo", + ) + product_custom_attribute: "ProductCustomAttributeInfo" = proto.Field( + proto.MESSAGE, + number=16, + oneof="dimension", + message="ProductCustomAttributeInfo", + ) + product_item_id: "ProductItemIdInfo" = proto.Field( + proto.MESSAGE, + number=11, + oneof="dimension", + message="ProductItemIdInfo", + ) + product_type: "ProductTypeInfo" = proto.Field( + proto.MESSAGE, + number=12, + oneof="dimension", + message="ProductTypeInfo", + ) + product_grouping: "ProductGroupingInfo" = proto.Field( + proto.MESSAGE, + number=17, + oneof="dimension", + message="ProductGroupingInfo", + ) + product_labels: "ProductLabelsInfo" = proto.Field( + proto.MESSAGE, + number=18, + oneof="dimension", + message="ProductLabelsInfo", + ) + product_legacy_condition: "ProductLegacyConditionInfo" = proto.Field( + proto.MESSAGE, + number=19, + oneof="dimension", + message="ProductLegacyConditionInfo", + ) + product_type_full: "ProductTypeFullInfo" = proto.Field( + proto.MESSAGE, + number=20, + oneof="dimension", + message="ProductTypeFullInfo", + ) + activity_id: "ActivityIdInfo" = proto.Field( + proto.MESSAGE, + number=21, + oneof="dimension", + message="ActivityIdInfo", + ) + activity_rating: "ActivityRatingInfo" = proto.Field( + proto.MESSAGE, + number=22, + oneof="dimension", + message="ActivityRatingInfo", + ) + activity_country: "ActivityCountryInfo" = proto.Field( + proto.MESSAGE, + number=23, + oneof="dimension", + message="ActivityCountryInfo", + ) + activity_state: "ActivityStateInfo" = proto.Field( + proto.MESSAGE, + number=25, + oneof="dimension", + message="ActivityStateInfo", + ) + activity_city: "ActivityCityInfo" = proto.Field( + proto.MESSAGE, + number=26, + oneof="dimension", + message="ActivityCityInfo", + ) + unknown_listing_dimension: "UnknownListingDimensionInfo" = proto.Field( + proto.MESSAGE, + number=14, + oneof="dimension", + message="UnknownListingDimensionInfo", + ) + + +class HotelIdInfo(proto.Message): + r"""Advertiser-specific hotel ID. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + String value of the hotel ID. + + This field is a member of `oneof`_ ``_value``. + """ + + value: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class HotelClassInfo(proto.Message): + r"""Class of the hotel as a number of stars 1 to 5. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (int): + Long value of the hotel class. + + This field is a member of `oneof`_ ``_value``. + """ + + value: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + +class HotelCountryRegionInfo(proto.Message): + r"""Country or Region the hotel is located in. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + country_region_criterion (str): + The Geo Target Constant resource name. + + This field is a member of `oneof`_ ``_country_region_criterion``. + """ + + country_region_criterion: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class HotelStateInfo(proto.Message): + r"""State the hotel is located in. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + state_criterion (str): + The Geo Target Constant resource name. + + This field is a member of `oneof`_ ``_state_criterion``. + """ + + state_criterion: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class HotelCityInfo(proto.Message): + r"""City the hotel is located in. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + city_criterion (str): + The Geo Target Constant resource name. + + This field is a member of `oneof`_ ``_city_criterion``. + """ + + city_criterion: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class ProductCategoryInfo(proto.Message): + r"""Category of a product offer. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + category_id (int): + ID of the product category. + + This ID is equivalent to the google_product_category ID as + described in this article: + https://support.google.com/merchants/answer/6324436 + + This field is a member of `oneof`_ ``_category_id``. + level (google.ads.googleads.v24.enums.types.ProductCategoryLevelEnum.ProductCategoryLevel): + Level of the product category. + """ + + category_id: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + level: ( + product_category_level.ProductCategoryLevelEnum.ProductCategoryLevel + ) = proto.Field( + proto.ENUM, + number=2, + enum=product_category_level.ProductCategoryLevelEnum.ProductCategoryLevel, + ) + + +class ProductBrandInfo(proto.Message): + r"""Brand of the product. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + String value of the product brand. + + This field is a member of `oneof`_ ``_value``. + """ + + value: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class ProductChannelInfo(proto.Message): + r"""Locality of a product offer. + + Attributes: + channel (google.ads.googleads.v24.enums.types.ProductChannelEnum.ProductChannel): + Value of the locality. + """ + + channel: gage_product_channel.ProductChannelEnum.ProductChannel = ( + proto.Field( + proto.ENUM, + number=1, + enum=gage_product_channel.ProductChannelEnum.ProductChannel, + ) + ) + + +class ProductChannelExclusivityInfo(proto.Message): + r"""Availability of a product offer. + + Attributes: + channel_exclusivity (google.ads.googleads.v24.enums.types.ProductChannelExclusivityEnum.ProductChannelExclusivity): + Value of the availability. + """ + + channel_exclusivity: ( + gage_product_channel_exclusivity.ProductChannelExclusivityEnum.ProductChannelExclusivity + ) = proto.Field( + proto.ENUM, + number=1, + enum=gage_product_channel_exclusivity.ProductChannelExclusivityEnum.ProductChannelExclusivity, + ) + + +class ProductConditionInfo(proto.Message): + r"""Condition of a product offer. + + Attributes: + condition (google.ads.googleads.v24.enums.types.ProductConditionEnum.ProductCondition): + Value of the condition. + """ + + condition: gage_product_condition.ProductConditionEnum.ProductCondition = ( + proto.Field( + proto.ENUM, + number=1, + enum=gage_product_condition.ProductConditionEnum.ProductCondition, + ) + ) + + +class ProductCustomAttributeInfo(proto.Message): + r"""Custom attribute of a product offer. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + String value of the product custom attribute. + + This field is a member of `oneof`_ ``_value``. + index (google.ads.googleads.v24.enums.types.ProductCustomAttributeIndexEnum.ProductCustomAttributeIndex): + Indicates the index of the custom attribute. + """ + + value: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + index: ( + product_custom_attribute_index.ProductCustomAttributeIndexEnum.ProductCustomAttributeIndex + ) = proto.Field( + proto.ENUM, + number=2, + enum=product_custom_attribute_index.ProductCustomAttributeIndexEnum.ProductCustomAttributeIndex, + ) + + +class ProductItemIdInfo(proto.Message): + r"""Item id of a product offer. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + Value of the id. + + This field is a member of `oneof`_ ``_value``. + """ + + value: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class ProductTypeInfo(proto.Message): + r"""Type of a product offer. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + Value of the type. + + This field is a member of `oneof`_ ``_value``. + level (google.ads.googleads.v24.enums.types.ProductTypeLevelEnum.ProductTypeLevel): + Level of the type. + """ + + value: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + level: product_type_level.ProductTypeLevelEnum.ProductTypeLevel = ( + proto.Field( + proto.ENUM, + number=2, + enum=product_type_level.ProductTypeLevelEnum.ProductTypeLevel, + ) + ) + + +class ProductGroupingInfo(proto.Message): + r"""Grouping of a product offer. This listing dimension is + deprecated and it is supported only in Display campaigns. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + String value of the product grouping. + + This field is a member of `oneof`_ ``_value``. + """ + + value: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class ProductLabelsInfo(proto.Message): + r"""Labels of a product offer. This listing dimension is + deprecated and it is supported only in Display campaigns. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + String value of the product labels. + + This field is a member of `oneof`_ ``_value``. + """ + + value: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class ProductLegacyConditionInfo(proto.Message): + r"""Legacy condition of a product offer. This listing dimension + is deprecated and it is supported only in Display campaigns. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + String value of the product legacy condition. + + This field is a member of `oneof`_ ``_value``. + """ + + value: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class ProductTypeFullInfo(proto.Message): + r"""Full type of a product offer. This listing dimension is + deprecated and it is supported only in Display campaigns. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + String value of the product full type. + + This field is a member of `oneof`_ ``_value``. + """ + + value: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class UnknownListingDimensionInfo(proto.Message): + r"""Unknown listing dimension.""" + + +class HotelDateSelectionTypeInfo(proto.Message): + r"""Criterion for hotel date selection (default dates versus user + selected). + + Attributes: + type_ (google.ads.googleads.v24.enums.types.HotelDateSelectionTypeEnum.HotelDateSelectionType): + Type of the hotel date selection + """ + + type_: ( + hotel_date_selection_type.HotelDateSelectionTypeEnum.HotelDateSelectionType + ) = proto.Field( + proto.ENUM, + number=1, + enum=hotel_date_selection_type.HotelDateSelectionTypeEnum.HotelDateSelectionType, + ) + + +class HotelAdvanceBookingWindowInfo(proto.Message): + r"""Criterion for number of days prior to the stay the booking is + being made. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + min_days (int): + Low end of the number of days prior to the + stay. + + This field is a member of `oneof`_ ``_min_days``. + max_days (int): + High end of the number of days prior to the + stay. + + This field is a member of `oneof`_ ``_max_days``. + """ + + min_days: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + max_days: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + + +class HotelLengthOfStayInfo(proto.Message): + r"""Criterion for length of hotel stay in nights. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + min_nights (int): + Low end of the number of nights in the stay. + + This field is a member of `oneof`_ ``_min_nights``. + max_nights (int): + High end of the number of nights in the stay. + + This field is a member of `oneof`_ ``_max_nights``. + """ + + min_nights: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + max_nights: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + + +class HotelCheckInDateRangeInfo(proto.Message): + r"""Criterion for a check-in date range. + + Attributes: + start_date (str): + Start date in the YYYY-MM-DD format. + end_date (str): + End date in the YYYY-MM-DD format. + """ + + start_date: str = proto.Field( + proto.STRING, + number=1, + ) + end_date: str = proto.Field( + proto.STRING, + number=2, + ) + + +class HotelCheckInDayInfo(proto.Message): + r"""Criterion for day of the week the booking is for. + + Attributes: + day_of_week (google.ads.googleads.v24.enums.types.DayOfWeekEnum.DayOfWeek): + The day of the week. + """ + + day_of_week: gage_day_of_week.DayOfWeekEnum.DayOfWeek = proto.Field( + proto.ENUM, + number=1, + enum=gage_day_of_week.DayOfWeekEnum.DayOfWeek, + ) + + +class ActivityIdInfo(proto.Message): + r"""Advertiser-specific activity ID. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + String value of the activity ID. + + This field is a member of `oneof`_ ``_value``. + """ + + value: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class ActivityRatingInfo(proto.Message): + r"""Rating of the activity as a number 1 to 5, where 5 is the + best. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (int): + Long value of the activity rating. + + This field is a member of `oneof`_ ``_value``. + """ + + value: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + + +class ActivityCountryInfo(proto.Message): + r"""The country where the travel activity is available. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + String value of the activity country. The Geo + Target Constant resource name. + + This field is a member of `oneof`_ ``_value``. + """ + + value: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class ActivityStateInfo(proto.Message): + r"""The state where the travel activity is available. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + String value of the activity state. The Geo + Target Constant resource name. + + This field is a member of `oneof`_ ``_value``. + """ + + value: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class ActivityCityInfo(proto.Message): + r"""The city where the travel activity is available. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + String value of the activity city. The Geo + Target Constant resource name. + + This field is a member of `oneof`_ ``_value``. + """ + + value: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class InteractionTypeInfo(proto.Message): + r"""Criterion for Interaction Type. + + Attributes: + type_ (google.ads.googleads.v24.enums.types.InteractionTypeEnum.InteractionType): + The interaction type. + """ + + type_: interaction_type.InteractionTypeEnum.InteractionType = proto.Field( + proto.ENUM, + number=1, + enum=interaction_type.InteractionTypeEnum.InteractionType, + ) + + +class AdScheduleInfo(proto.Message): + r"""Represents an AdSchedule criterion. + + AdSchedule is specified as the day of the week and a time + interval within which ads will be shown. + + No more than six AdSchedules can be added for the same day. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + start_minute (google.ads.googleads.v24.enums.types.MinuteOfHourEnum.MinuteOfHour): + Minutes after the start hour at which this + schedule starts. + This field is required for CREATE operations and + is prohibited on UPDATE operations. + end_minute (google.ads.googleads.v24.enums.types.MinuteOfHourEnum.MinuteOfHour): + Minutes after the end hour at which this + schedule ends. The schedule is exclusive of the + end minute. + + This field is required for CREATE operations and + is prohibited on UPDATE operations. + start_hour (int): + Starting hour in 24 hour time. + This field must be between 0 and 23, inclusive. + + This field is required for CREATE operations and + is prohibited on UPDATE operations. + + This field is a member of `oneof`_ ``_start_hour``. + end_hour (int): + Ending hour in 24 hour time; 24 signifies end + of the day. This field must be between 0 and 24, + inclusive. + + This field is required for CREATE operations and + is prohibited on UPDATE operations. + + This field is a member of `oneof`_ ``_end_hour``. + day_of_week (google.ads.googleads.v24.enums.types.DayOfWeekEnum.DayOfWeek): + Day of the week the schedule applies to. + + This field is required for CREATE operations and + is prohibited on UPDATE operations. + """ + + start_minute: minute_of_hour.MinuteOfHourEnum.MinuteOfHour = proto.Field( + proto.ENUM, + number=1, + enum=minute_of_hour.MinuteOfHourEnum.MinuteOfHour, + ) + end_minute: minute_of_hour.MinuteOfHourEnum.MinuteOfHour = proto.Field( + proto.ENUM, + number=2, + enum=minute_of_hour.MinuteOfHourEnum.MinuteOfHour, + ) + start_hour: int = proto.Field( + proto.INT32, + number=6, + optional=True, + ) + end_hour: int = proto.Field( + proto.INT32, + number=7, + optional=True, + ) + day_of_week: gage_day_of_week.DayOfWeekEnum.DayOfWeek = proto.Field( + proto.ENUM, + number=5, + enum=gage_day_of_week.DayOfWeekEnum.DayOfWeek, + ) + + +class AgeRangeInfo(proto.Message): + r"""An age range criterion. + + Attributes: + type_ (google.ads.googleads.v24.enums.types.AgeRangeTypeEnum.AgeRangeType): + Type of the age range. + """ + + type_: age_range_type.AgeRangeTypeEnum.AgeRangeType = proto.Field( + proto.ENUM, + number=1, + enum=age_range_type.AgeRangeTypeEnum.AgeRangeType, + ) + + +class GenderInfo(proto.Message): + r"""A gender criterion. + + Attributes: + type_ (google.ads.googleads.v24.enums.types.GenderTypeEnum.GenderType): + Type of the gender. + """ + + type_: gender_type.GenderTypeEnum.GenderType = proto.Field( + proto.ENUM, + number=1, + enum=gender_type.GenderTypeEnum.GenderType, + ) + + +class IncomeRangeInfo(proto.Message): + r"""An income range criterion. + + Attributes: + type_ (google.ads.googleads.v24.enums.types.IncomeRangeTypeEnum.IncomeRangeType): + Type of the income range. + """ + + type_: income_range_type.IncomeRangeTypeEnum.IncomeRangeType = proto.Field( + proto.ENUM, + number=1, + enum=income_range_type.IncomeRangeTypeEnum.IncomeRangeType, + ) + + +class ParentalStatusInfo(proto.Message): + r"""A parental status criterion. + + Attributes: + type_ (google.ads.googleads.v24.enums.types.ParentalStatusTypeEnum.ParentalStatusType): + Type of the parental status. + """ + + type_: parental_status_type.ParentalStatusTypeEnum.ParentalStatusType = ( + proto.Field( + proto.ENUM, + number=1, + enum=parental_status_type.ParentalStatusTypeEnum.ParentalStatusType, + ) + ) + + +class YouTubeVideoInfo(proto.Message): + r"""A YouTube Video criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + video_id (str): + YouTube video id as it appears on the YouTube + watch page. + + This field is a member of `oneof`_ ``_video_id``. + """ + + video_id: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class YouTubeChannelInfo(proto.Message): + r"""A YouTube Channel criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + channel_id (str): + The YouTube uploader channel id or the + channel code of a YouTube channel. + + This field is a member of `oneof`_ ``_channel_id``. + """ + + channel_id: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class UserListInfo(proto.Message): + r"""A User List criterion. Represents a user list that is defined + by the advertiser to be targeted. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + user_list (str): + The User List resource name. + + This field is a member of `oneof`_ ``_user_list``. + """ + + user_list: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class ProximityInfo(proto.Message): + r"""A Proximity criterion. The geo point and radius determine + what geographical area is included. The address is a description + of the geo point that does not affect ad serving. + + There are two ways to create a proximity. First, by setting an + address and radius. The geo point will be automatically + computed. Second, by setting a geo point and radius. The address + is an optional label that won't be validated. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + geo_point (google.ads.googleads.v24.common.types.GeoPointInfo): + Latitude and longitude. + radius (float): + The radius of the proximity. + + This field is a member of `oneof`_ ``_radius``. + radius_units (google.ads.googleads.v24.enums.types.ProximityRadiusUnitsEnum.ProximityRadiusUnits): + The unit of measurement of the radius. + Default is KILOMETERS. + address (google.ads.googleads.v24.common.types.AddressInfo): + Full address. + """ + + geo_point: "GeoPointInfo" = proto.Field( + proto.MESSAGE, + number=1, + message="GeoPointInfo", + ) + radius: float = proto.Field( + proto.DOUBLE, + number=5, + optional=True, + ) + radius_units: ( + proximity_radius_units.ProximityRadiusUnitsEnum.ProximityRadiusUnits + ) = proto.Field( + proto.ENUM, + number=3, + enum=proximity_radius_units.ProximityRadiusUnitsEnum.ProximityRadiusUnits, + ) + address: "AddressInfo" = proto.Field( + proto.MESSAGE, + number=4, + message="AddressInfo", + ) + + +class GeoPointInfo(proto.Message): + r"""Geo point for proximity criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + longitude_in_micro_degrees (int): + Micro degrees for the longitude. + + This field is a member of `oneof`_ ``_longitude_in_micro_degrees``. + latitude_in_micro_degrees (int): + Micro degrees for the latitude. + + This field is a member of `oneof`_ ``_latitude_in_micro_degrees``. + """ + + longitude_in_micro_degrees: int = proto.Field( + proto.INT32, + number=3, + optional=True, + ) + latitude_in_micro_degrees: int = proto.Field( + proto.INT32, + number=4, + optional=True, + ) + + +class AddressInfo(proto.Message): + r"""Address for proximity criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + postal_code (str): + Postal code. + + This field is a member of `oneof`_ ``_postal_code``. + province_code (str): + Province or state code. + + This field is a member of `oneof`_ ``_province_code``. + country_code (str): + Country code. + + This field is a member of `oneof`_ ``_country_code``. + province_name (str): + Province or state name. + + This field is a member of `oneof`_ ``_province_name``. + street_address (str): + Street address line 1. + + This field is a member of `oneof`_ ``_street_address``. + street_address2 (str): + Street address line 2. This field is write-only. It is only + used for calculating the longitude and latitude of an + address when geo_point is empty. + + This field is a member of `oneof`_ ``_street_address2``. + city_name (str): + Name of the city. + + This field is a member of `oneof`_ ``_city_name``. + """ + + postal_code: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + province_code: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + country_code: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + province_name: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + street_address: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + street_address2: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + city_name: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + + +class TopicInfo(proto.Message): + r"""A topic criterion. Use topics to target or exclude placements + in the Google Display Network based on the category into which + the placement falls (for example, "Pets & Animals/Pets/Dogs"). + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + topic_constant (str): + The Topic Constant resource name. + + This field is a member of `oneof`_ ``_topic_constant``. + path (MutableSequence[str]): + The category to target or exclude. Each + subsequent element in the array describes a more + specific sub-category. For example, "Pets & + Animals", "Pets", "Dogs" represents the "Pets & + Animals/Pets/Dogs" category. + """ + + topic_constant: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + path: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=4, + ) + + +class LanguageInfo(proto.Message): + r"""A language criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + language_constant (str): + The language constant resource name. + + This field is a member of `oneof`_ ``_language_constant``. + """ + + language_constant: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class IpBlockInfo(proto.Message): + r"""An IpBlock criterion used for excluding IP addresses. + + We support excluding individual IP addresses or CIDR blocks. Create + one IpBlockInfo criterion for each individual IP address or CIDR + block you want to exclude. You can exclude up to 500 IP addresses + per campaign. For more details, see `Exclude IP + addresses `__. + + IPv4 examples: + + - Individual address: 192.168.0.1 + + - Individual address as CIDR block: 192.168.0.1/32 + + - CIDR block: 192.168.0.0/24 + + IPv6 examples: + + - Individual address: 2001:db8:a0b:12f0::1 + + - Individual address as CIDR block: 2001:db8:a0b:12f0::1/128 + + - CIDR block: 2001:db8::/48 + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + ip_address (str): + The IP address or the CIDR block to be + excluded. + + This field is a member of `oneof`_ ``_ip_address``. + """ + + ip_address: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class ContentLabelInfo(proto.Message): + r"""Content Label for category exclusion. + + Attributes: + type_ (google.ads.googleads.v24.enums.types.ContentLabelTypeEnum.ContentLabelType): + Content label type, required for CREATE + operations. + """ + + type_: content_label_type.ContentLabelTypeEnum.ContentLabelType = ( + proto.Field( + proto.ENUM, + number=1, + enum=content_label_type.ContentLabelTypeEnum.ContentLabelType, + ) + ) + + +class CarrierInfo(proto.Message): + r"""Represents a Carrier Criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + carrier_constant (str): + The Carrier constant resource name. + + This field is a member of `oneof`_ ``_carrier_constant``. + """ + + carrier_constant: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class UserInterestInfo(proto.Message): + r"""Represents a particular interest-based topic to be targeted. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + user_interest_category (str): + The UserInterest resource name. + + This field is a member of `oneof`_ ``_user_interest_category``. + """ + + user_interest_category: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class WebpageInfo(proto.Message): + r"""Represents a criterion for targeting webpages of an + advertiser's website. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + criterion_name (str): + The name of the criterion that is defined by + this parameter. The name value will be used for + identifying, sorting and filtering criteria with + this type of parameters. + + This field is required for CREATE operations and + is prohibited on UPDATE operations. + + This field is a member of `oneof`_ ``_criterion_name``. + conditions (MutableSequence[google.ads.googleads.v24.common.types.WebpageConditionInfo]): + Conditions, or logical expressions, for + webpage targeting. The list of webpage targeting + conditions are and-ed together when evaluated + for targeting. An empty list of conditions + indicates all pages of the campaign's website + are targeted. + + This field is required for CREATE operations and + is prohibited on UPDATE operations. + coverage_percentage (float): + Website criteria coverage percentage. This is + the computed percentage of website coverage + based on the website target, negative website + target and negative keywords in the ad group and + campaign. For instance, when coverage returns as + 1, it indicates it has 100% coverage. This field + is read-only. + sample (google.ads.googleads.v24.common.types.WebpageSampleInfo): + List of sample urls that match the website + target. This field is read-only. + """ + + criterion_name: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + conditions: MutableSequence["WebpageConditionInfo"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="WebpageConditionInfo", + ) + coverage_percentage: float = proto.Field( + proto.DOUBLE, + number=4, + ) + sample: "WebpageSampleInfo" = proto.Field( + proto.MESSAGE, + number=5, + message="WebpageSampleInfo", + ) + + +class WebpageConditionInfo(proto.Message): + r"""Logical expression for targeting webpages of an advertiser's + website. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + operand (google.ads.googleads.v24.enums.types.WebpageConditionOperandEnum.WebpageConditionOperand): + Operand of webpage targeting condition. + operator (google.ads.googleads.v24.enums.types.WebpageConditionOperatorEnum.WebpageConditionOperator): + Operator of webpage targeting condition. + argument (str): + Argument of webpage targeting condition. + + This field is a member of `oneof`_ ``_argument``. + """ + + operand: ( + webpage_condition_operand.WebpageConditionOperandEnum.WebpageConditionOperand + ) = proto.Field( + proto.ENUM, + number=1, + enum=webpage_condition_operand.WebpageConditionOperandEnum.WebpageConditionOperand, + ) + operator: ( + webpage_condition_operator.WebpageConditionOperatorEnum.WebpageConditionOperator + ) = proto.Field( + proto.ENUM, + number=2, + enum=webpage_condition_operator.WebpageConditionOperatorEnum.WebpageConditionOperator, + ) + argument: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + + +class WebpageListInfo(proto.Message): + r"""Represents a list of webpage criteria. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + shared_set (str): + Shared set resource name of the webpage list. + + This field is a member of `oneof`_ ``_shared_set``. + """ + + shared_set: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class WebpageSampleInfo(proto.Message): + r"""List of sample urls that match the website target + + Attributes: + sample_urls (MutableSequence[str]): + Webpage sample urls + """ + + sample_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + + +class OperatingSystemVersionInfo(proto.Message): + r"""Represents an operating system version to be targeted. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + operating_system_version_constant (str): + The operating system version constant + resource name. + + This field is a member of `oneof`_ ``_operating_system_version_constant``. + """ + + operating_system_version_constant: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class AppPaymentModelInfo(proto.Message): + r"""An app payment model criterion. + + Attributes: + type_ (google.ads.googleads.v24.enums.types.AppPaymentModelTypeEnum.AppPaymentModelType): + Type of the app payment model. + """ + + type_: ( + app_payment_model_type.AppPaymentModelTypeEnum.AppPaymentModelType + ) = proto.Field( + proto.ENUM, + number=1, + enum=app_payment_model_type.AppPaymentModelTypeEnum.AppPaymentModelType, + ) + + +class MobileDeviceInfo(proto.Message): + r"""A mobile device criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + mobile_device_constant (str): + The mobile device constant resource name. + + This field is a member of `oneof`_ ``_mobile_device_constant``. + """ + + mobile_device_constant: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class CustomAffinityInfo(proto.Message): + r"""A custom affinity criterion. + A criterion of this type is only targetable. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + custom_affinity (str): + The CustomInterest resource name. + + This field is a member of `oneof`_ ``_custom_affinity``. + """ + + custom_affinity: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class CustomIntentInfo(proto.Message): + r"""A custom intent criterion. + A criterion of this type is only targetable. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + custom_intent (str): + The CustomInterest resource name. + + This field is a member of `oneof`_ ``_custom_intent``. + """ + + custom_intent: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class LocationGroupInfo(proto.Message): + r"""A radius around a list of locations specified through a feed + or assetSet. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + geo_target_constants (MutableSequence[str]): + Geo target constant(s) restricting the scope + of the geographic area within the feed. + Currently only one geo target constant is + allowed. Cannot be set with AssetSet fields. + radius (int): + Distance in units specifying the radius + around targeted locations. This is required and + must be set in CREATE operations. + + This field is a member of `oneof`_ ``_radius``. + radius_units (google.ads.googleads.v24.enums.types.LocationGroupRadiusUnitsEnum.LocationGroupRadiusUnits): + Unit of the radius. Miles and meters are + supported for geo target constants. Milli miles + and meters are supported for feed item sets and + asset sets. This is required and must be set in + CREATE operations. + feed_item_sets (MutableSequence[str]): + FeedItemSets whose FeedItems are targeted. If multiple IDs + are specified, then all items that appear in at least one + set are targeted. This field cannot be used with + geo_target_constants. This is optional and can only be set + in CREATE operations. Cannot be set with AssetSet fields. + enable_customer_level_location_asset_set (bool): + Denotes that the latest customer level asset set is used for + targeting. Used with radius and radius_units. Cannot be used + with feed, geo target constants or feed item sets. When + using asset sets, either this field or + location_group_asset_sets should be specified. Both cannot + be used at the same time. This can only be set in CREATE + operations. + + This field is a member of `oneof`_ ``_enable_customer_level_location_asset_set``. + location_group_asset_sets (MutableSequence[str]): + AssetSets whose Assets are targeted. If multiple IDs are + specified, then all items that appear in at least one set + are targeted. This field cannot be used with feed, geo + target constants or feed item sets. When using asset sets, + either this field or + enable_customer_level_location_asset_set should be + specified. Both cannot be used at the same time. This can + only be set in CREATE operations. + """ + + geo_target_constants: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=6, + ) + radius: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + radius_units: ( + location_group_radius_units.LocationGroupRadiusUnitsEnum.LocationGroupRadiusUnits + ) = proto.Field( + proto.ENUM, + number=4, + enum=location_group_radius_units.LocationGroupRadiusUnitsEnum.LocationGroupRadiusUnits, + ) + feed_item_sets: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=8, + ) + enable_customer_level_location_asset_set: bool = proto.Field( + proto.BOOL, + number=9, + optional=True, + ) + location_group_asset_sets: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=10, + ) + + +class CustomAudienceInfo(proto.Message): + r"""A custom audience criterion. + + Attributes: + custom_audience (str): + The CustomAudience resource name. + """ + + custom_audience: str = proto.Field( + proto.STRING, + number=1, + ) + + +class CombinedAudienceInfo(proto.Message): + r"""A combined audience criterion. + + Attributes: + combined_audience (str): + The CombinedAudience resource name. + """ + + combined_audience: str = proto.Field( + proto.STRING, + number=1, + ) + + +class AudienceInfo(proto.Message): + r"""An audience criterion. + + Attributes: + audience (str): + The Audience resource name. + """ + + audience: str = proto.Field( + proto.STRING, + number=1, + ) + + +class KeywordThemeInfo(proto.Message): + r"""A Smart Campaign keyword theme. + + 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: + keyword_theme_constant (str): + The resource name of a Smart Campaign keyword theme + constant. + ``keywordThemeConstants/{keyword_theme_id}~{sub_keyword_theme_id}`` + + This field is a member of `oneof`_ ``keyword_theme``. + free_form_keyword_theme (str): + Free-form text to be matched to a Smart + Campaign keyword theme constant on a best-effort + basis. + + This field is a member of `oneof`_ ``keyword_theme``. + """ + + keyword_theme_constant: str = proto.Field( + proto.STRING, + number=1, + oneof="keyword_theme", + ) + free_form_keyword_theme: str = proto.Field( + proto.STRING, + number=2, + oneof="keyword_theme", + ) + + +class LocalServiceIdInfo(proto.Message): + r"""A Local Services Ads service ID. Represents a service type (such as + install_faucet) that a Local Services Campaign can target. + + Attributes: + service_id (str): + The criterion resource name. + """ + + service_id: str = proto.Field( + proto.STRING, + number=1, + ) + + +class SearchThemeInfo(proto.Message): + r"""A Search Theme criterion only on Performance Max campaign. + Represents a keyword-like advertiser input. + + Attributes: + text (str): + Each Search Theme has a value of a simple + string, like keywords. There are limits on + overall length, allowed characters, and number + of words. + """ + + text: str = proto.Field( + proto.STRING, + number=1, + ) + + +class BrandInfo(proto.Message): + r"""Represents a Brand Criterion used for targeting based on + commercial knowledge graph. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + display_name (str): + Output only. A text representation of a + brand. + + This field is a member of `oneof`_ ``_display_name``. + entity_id (str): + The Commercial KG MID for the brand. + + This field is a member of `oneof`_ ``_entity_id``. + primary_url (str): + Output only. The primary url of a brand. + + This field is a member of `oneof`_ ``_primary_url``. + rejection_reason (google.ads.googleads.v24.enums.types.BrandRequestRejectionReasonEnum.BrandRequestRejectionReason): + Output only. The rejection reason when a + brand status is REJECTED. + + This field is a member of `oneof`_ ``_rejection_reason``. + status (google.ads.googleads.v24.enums.types.BrandStateEnum.BrandState): + Output only. The status of a brand. + + This field is a member of `oneof`_ ``_status``. + """ + + display_name: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + entity_id: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + primary_url: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + rejection_reason: ( + brand_request_rejection_reason.BrandRequestRejectionReasonEnum.BrandRequestRejectionReason + ) = proto.Field( + proto.ENUM, + number=4, + optional=True, + enum=brand_request_rejection_reason.BrandRequestRejectionReasonEnum.BrandRequestRejectionReason, + ) + status: brand_state.BrandStateEnum.BrandState = proto.Field( + proto.ENUM, + number=5, + optional=True, + enum=brand_state.BrandStateEnum.BrandState, + ) + + +class BrandListInfo(proto.Message): + r"""A Brand List Criterion is used to specify a list of brands. The list + is represented as a SharedSet id type BRAND_HINT. A criterion of + this type can be either targeted or excluded. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + shared_set (str): + Shared set resource name of the brand list. + + This field is a member of `oneof`_ ``_shared_set``. + """ + + shared_set: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class LifeEventInfo(proto.Message): + r"""Represents a life event criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + life_event_id (int): + Taxonomy id of the life event. + + This field is a member of `oneof`_ ``_life_event_id``. + """ + + life_event_id: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + + +class ExtendedDemographicInfo(proto.Message): + r"""Represents an extended demographic criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + extended_demographic_id (int): + Taxonomy id of the extended demographic + group. + + This field is a member of `oneof`_ ``_extended_demographic_id``. + """ + + extended_demographic_id: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + + +class VideoLineupInfo(proto.Message): + r"""A Video lineup criterion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + video_lineup_id (int): + ID for a Video lineup. Contact your Google + business development representative for details. + + This field is a member of `oneof`_ ``_video_lineup_id``. + """ + + video_lineup_id: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + + +class PlacementListInfo(proto.Message): + r"""A Placement List criterion. Represents a shared set + of placements that can be excluded at the account-level. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + shared_set (str): + The PlacementListInfo shared set resource + name. + + This field is a member of `oneof`_ ``_shared_set``. + """ + + shared_set: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class VerticalAdsItemGroupRuleListInfo(proto.Message): + r"""A criterion for targeting a shared set of rules for item + groups in Vertical Ads (e.g., for hotel ads). + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + shared_set (str): + The shared set resource name of the vertical + ads item group rule list. + + This field is a member of `oneof`_ ``_shared_set``. + """ + + shared_set: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class VerticalAdsItemGroupRuleInfo(proto.Message): + r"""A criterion to represent a single item group rule in Vertical + Ads. + + 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: + item_code (str): + The id specifying a particular Vertical Ad + listing. + + This field is a member of `oneof`_ ``dimension``. + country_criterion_id (str): + The resource name of the Geo Target Constant + for the country. + + This field is a member of `oneof`_ ``dimension``. + region_criterion_id (str): + The resource name of the Geo Target Constant + for the region. + + This field is a member of `oneof`_ ``dimension``. + city_criterion_id (str): + The resource name of the Geo Target Constant + for the city. + + This field is a member of `oneof`_ ``dimension``. + hotel_class (int): + Integer value specifying the class rating for + a hotel. Ranges from 1 to 5 stars. + + This field is a member of `oneof`_ ``dimension``. + """ + + item_code: str = proto.Field( + proto.STRING, + number=1, + oneof="dimension", + ) + country_criterion_id: str = proto.Field( + proto.STRING, + number=2, + oneof="dimension", + ) + region_criterion_id: str = proto.Field( + proto.STRING, + number=3, + oneof="dimension", + ) + city_criterion_id: str = proto.Field( + proto.STRING, + number=4, + oneof="dimension", + ) + hotel_class: int = proto.Field( + proto.INT64, + number=6, + oneof="dimension", + ) + + +class RetailFilterBundle(proto.Message): + r"""Represents a Retail Filter Bundle, used to link an ad group + to a shared set containing retail filters. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + shared_set (str): + The resource name of the shared set that + contains the retail filter. This field is + required. + + This field is a member of `oneof`_ ``_shared_set``. + """ + + shared_set: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class RetailFilter(proto.Message): + r"""Represents a Retail Filter. + + 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: + expression (google.ads.googleads.v24.common.types.RetailFilterExpression): + An expression node. At this time, this can + only be an OR node. + + This field is a member of `oneof`_ ``node``. + tag (google.ads.googleads.v24.common.types.RetailTag): + A tag node. + + This field is a member of `oneof`_ ``node``. + """ + + expression: "RetailFilterExpression" = proto.Field( + proto.MESSAGE, + number=1, + oneof="node", + message="RetailFilterExpression", + ) + tag: "RetailTag" = proto.Field( + proto.MESSAGE, + number=2, + oneof="node", + message="RetailTag", + ) + + +class RetailFilterExpression(proto.Message): + r"""Represents a Retail Filter Expression. Tags grouped within an + expression are joined with OR operator. A product needs to have + any of these tags to satisfy expression condition. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + name (str): + The name of the expression. This name is used + for grouping Retail Tags into one logical + expression with OR operator. The name can + contain at most 20 characters. Only lowercase + latin letters, underscores, and numbers are + allowed. This field is required and must be + unique within the shared set. + + This field is a member of `oneof`_ ``_name``. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class RetailTag(proto.Message): + r"""Represents a Retail Filter Tag. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + The value of the tag. + It can contain at most 50 characters. All + Unicode characters except comma and newline are + allowed. + This field is required. + + This field is a member of `oneof`_ ``_value``. + expression_name (str): + The name of the expression this tag belongs + to. If empty, the tag is a top-level condition. + + This field is a member of `oneof`_ ``_expression_name``. + """ + + value: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + expression_name: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/criterion_category_availability.py b/google/ads/googleads/v24/common/types/criterion_category_availability.py new file mode 100644 index 000000000..b7ff61737 --- /dev/null +++ b/google/ads/googleads/v24/common/types/criterion_category_availability.py @@ -0,0 +1,176 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + advertising_channel_sub_type as gage_advertising_channel_sub_type, +) +from google.ads.googleads.v24.enums.types import ( + advertising_channel_type as gage_advertising_channel_type, +) +from google.ads.googleads.v24.enums.types import ( + criterion_category_channel_availability_mode, +) +from google.ads.googleads.v24.enums.types import ( + criterion_category_locale_availability_mode, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "CriterionCategoryAvailability", + "CriterionCategoryChannelAvailability", + "CriterionCategoryLocaleAvailability", + }, +) + + +class CriterionCategoryAvailability(proto.Message): + r"""Information of category availability, per advertising + channel. + + Attributes: + channel (google.ads.googleads.v24.common.types.CriterionCategoryChannelAvailability): + Channel types and subtypes that are available + to the category. + locale (MutableSequence[google.ads.googleads.v24.common.types.CriterionCategoryLocaleAvailability]): + Locales that are available to the category + for the channel. + """ + + channel: "CriterionCategoryChannelAvailability" = proto.Field( + proto.MESSAGE, + number=1, + message="CriterionCategoryChannelAvailability", + ) + locale: MutableSequence["CriterionCategoryLocaleAvailability"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CriterionCategoryLocaleAvailability", + ) + ) + + +class CriterionCategoryChannelAvailability(proto.Message): + r"""Information of advertising channel type and subtypes a + category is available in. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + availability_mode (google.ads.googleads.v24.enums.types.CriterionCategoryChannelAvailabilityModeEnum.CriterionCategoryChannelAvailabilityMode): + Format of the channel availability. Can be ALL_CHANNELS (the + rest of the fields will not be set), CHANNEL_TYPE (only + advertising_channel_type type will be set, the category is + available to all sub types under it) or + CHANNEL_TYPE_AND_SUBTYPES (advertising_channel_type, + advertising_channel_sub_type, and + include_default_channel_sub_type will all be set). + advertising_channel_type (google.ads.googleads.v24.enums.types.AdvertisingChannelTypeEnum.AdvertisingChannelType): + Channel type the category is available to. + advertising_channel_sub_type (MutableSequence[google.ads.googleads.v24.enums.types.AdvertisingChannelSubTypeEnum.AdvertisingChannelSubType]): + Channel subtypes under the channel type the + category is available to. + include_default_channel_sub_type (bool): + Whether default channel sub type is included. For example, + advertising_channel_type being DISPLAY and + include_default_channel_sub_type being false means that the + default display campaign where channel sub type is not set + is not included in this availability configuration. + + This field is a member of `oneof`_ ``_include_default_channel_sub_type``. + """ + + availability_mode: ( + criterion_category_channel_availability_mode.CriterionCategoryChannelAvailabilityModeEnum.CriterionCategoryChannelAvailabilityMode + ) = proto.Field( + proto.ENUM, + number=1, + enum=criterion_category_channel_availability_mode.CriterionCategoryChannelAvailabilityModeEnum.CriterionCategoryChannelAvailabilityMode, + ) + advertising_channel_type: ( + gage_advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType, + ) + advertising_channel_sub_type: MutableSequence[ + gage_advertising_channel_sub_type.AdvertisingChannelSubTypeEnum.AdvertisingChannelSubType + ] = proto.RepeatedField( + proto.ENUM, + number=3, + enum=gage_advertising_channel_sub_type.AdvertisingChannelSubTypeEnum.AdvertisingChannelSubType, + ) + include_default_channel_sub_type: bool = proto.Field( + proto.BOOL, + number=5, + optional=True, + ) + + +class CriterionCategoryLocaleAvailability(proto.Message): + r"""Information about which locales a category is available in. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + availability_mode (google.ads.googleads.v24.enums.types.CriterionCategoryLocaleAvailabilityModeEnum.CriterionCategoryLocaleAvailabilityMode): + Format of the locale availability. Can be LAUNCHED_TO_ALL + (both country and language will be empty), COUNTRY (only + country will be set), LANGUAGE (only language wil be set), + COUNTRY_AND_LANGUAGE (both country and language will be + set). + country_code (str): + The ISO-3166-1 alpha-2 country code + associated with the category. + + This field is a member of `oneof`_ ``_country_code``. + language_code (str): + ISO 639-1 code of the language associated + with the category. + + This field is a member of `oneof`_ ``_language_code``. + """ + + availability_mode: ( + criterion_category_locale_availability_mode.CriterionCategoryLocaleAvailabilityModeEnum.CriterionCategoryLocaleAvailabilityMode + ) = proto.Field( + proto.ENUM, + number=1, + enum=criterion_category_locale_availability_mode.CriterionCategoryLocaleAvailabilityModeEnum.CriterionCategoryLocaleAvailabilityMode, + ) + country_code: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + language_code: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/custom_parameter.py b/google/ads/googleads/v24/common/types/custom_parameter.py new file mode 100644 index 000000000..197c2067e --- /dev/null +++ b/google/ads/googleads/v24/common/types/custom_parameter.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "CustomParameter", + }, +) + + +class CustomParameter(proto.Message): + r"""A mapping that can be used by custom parameter tags in a + ``tracking_url_template``, ``final_urls``, or ``mobile_final_urls``. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + key (str): + The key matching the parameter tag name. + + This field is a member of `oneof`_ ``_key``. + value (str): + The value to be substituted. + + This field is a member of `oneof`_ ``_value``. + """ + + key: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + value: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/customizer_value.py b/google/ads/googleads/v24/common/types/customizer_value.py new file mode 100644 index 000000000..a979ed531 --- /dev/null +++ b/google/ads/googleads/v24/common/types/customizer_value.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import customizer_attribute_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "CustomizerValue", + }, +) + + +class CustomizerValue(proto.Message): + r"""A customizer value that is referenced in customizer linkage + entities like CustomerCustomizer, CampaignCustomizer, etc. + + Attributes: + type_ (google.ads.googleads.v24.enums.types.CustomizerAttributeTypeEnum.CustomizerAttributeType): + Required. The data type for the customizer value. It must + match the attribute type. The string_value content must + match the constraints associated with the type. + string_value (str): + Required. Value to insert in creative text. + Customizer values of all types are stored as + string to make formatting unambiguous. + """ + + type_: ( + customizer_attribute_type.CustomizerAttributeTypeEnum.CustomizerAttributeType + ) = proto.Field( + proto.ENUM, + number=1, + enum=customizer_attribute_type.CustomizerAttributeTypeEnum.CustomizerAttributeType, + ) + string_value: str = proto.Field( + proto.STRING, + number=2, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/dates.py b/google/ads/googleads/v24/common/types/dates.py new file mode 100644 index 000000000..158626e4c --- /dev/null +++ b/google/ads/googleads/v24/common/types/dates.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import month_of_year + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "DateRange", + "YearMonthRange", + "YearMonth", + }, +) + + +class DateRange(proto.Message): + r"""A date range. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + start_date (str): + The start date, in yyyy-mm-dd format. This + date is inclusive. + + This field is a member of `oneof`_ ``_start_date``. + end_date (str): + The end date, in yyyy-mm-dd format. This date + is inclusive. + + This field is a member of `oneof`_ ``_end_date``. + """ + + start_date: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + end_date: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + + +class YearMonthRange(proto.Message): + r"""The year month range inclusive of the start and end months. + Eg: A year month range to represent Jan 2020 would be: (Jan + 2020, Jan 2020). + + Attributes: + start (google.ads.googleads.v24.common.types.YearMonth): + The inclusive start year month. + end (google.ads.googleads.v24.common.types.YearMonth): + The inclusive end year month. + """ + + start: "YearMonth" = proto.Field( + proto.MESSAGE, + number=1, + message="YearMonth", + ) + end: "YearMonth" = proto.Field( + proto.MESSAGE, + number=2, + message="YearMonth", + ) + + +class YearMonth(proto.Message): + r"""Year month. + + Attributes: + year (int): + The year (for example, 2020). + month (google.ads.googleads.v24.enums.types.MonthOfYearEnum.MonthOfYear): + The month of the year. (for example, + FEBRUARY). + """ + + year: int = proto.Field( + proto.INT64, + number=1, + ) + month: month_of_year.MonthOfYearEnum.MonthOfYear = proto.Field( + proto.ENUM, + number=2, + enum=month_of_year.MonthOfYearEnum.MonthOfYear, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/extensions.py b/google/ads/googleads/v24/common/types/extensions.py new file mode 100644 index 000000000..a7fff21e8 --- /dev/null +++ b/google/ads/googleads/v24/common/types/extensions.py @@ -0,0 +1,225 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import custom_parameter +from google.ads.googleads.v24.enums.types import ( + call_conversion_reporting_state as gage_call_conversion_reporting_state, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "CallFeedItem", + "CalloutFeedItem", + "SitelinkFeedItem", + }, +) + + +class CallFeedItem(proto.Message): + r"""Represents a Call extension. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + phone_number (str): + The advertiser's phone number to append to + the ad. This string must not be empty. + + This field is a member of `oneof`_ ``_phone_number``. + country_code (str): + Uppercase two-letter country code of the + advertiser's phone number. This string must not + be empty. + + This field is a member of `oneof`_ ``_country_code``. + call_tracking_enabled (bool): + Indicates whether call tracking is enabled. + By default, call tracking is not enabled. + + This field is a member of `oneof`_ ``_call_tracking_enabled``. + call_conversion_action (str): + The conversion action to attribute a call conversion to. If + not set a default conversion action is used. This field only + has effect if call_tracking_enabled is set to true. + Otherwise this field is ignored. + + This field is a member of `oneof`_ ``_call_conversion_action``. + call_conversion_tracking_disabled (bool): + If true, disable call conversion tracking. + call_conversion_action should not be set if this is true. + Optional. + + This field is a member of `oneof`_ ``_call_conversion_tracking_disabled``. + call_conversion_reporting_state (google.ads.googleads.v24.enums.types.CallConversionReportingStateEnum.CallConversionReportingState): + Enum value that indicates whether this call + extension uses its own call conversion setting + (or just have call conversion disabled), or + following the account level setting. + """ + + phone_number: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + country_code: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + call_tracking_enabled: bool = proto.Field( + proto.BOOL, + number=9, + optional=True, + ) + call_conversion_action: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + call_conversion_tracking_disabled: bool = proto.Field( + proto.BOOL, + number=11, + optional=True, + ) + call_conversion_reporting_state: ( + gage_call_conversion_reporting_state.CallConversionReportingStateEnum.CallConversionReportingState + ) = proto.Field( + proto.ENUM, + number=6, + enum=gage_call_conversion_reporting_state.CallConversionReportingStateEnum.CallConversionReportingState, + ) + + +class CalloutFeedItem(proto.Message): + r"""Represents a callout extension. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + callout_text (str): + The callout text. + The length of this string should be between 1 + and 25, inclusive. + + This field is a member of `oneof`_ ``_callout_text``. + """ + + callout_text: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class SitelinkFeedItem(proto.Message): + r"""Represents a sitelink. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + link_text (str): + URL display text for the sitelink. + The length of this string should be between 1 + and 25, inclusive. + + This field is a member of `oneof`_ ``_link_text``. + line1 (str): + First line of the description for the + sitelink. If this value is set, line2 must also + be set. The length of this string should be + between 0 and 35, inclusive. + + This field is a member of `oneof`_ ``_line1``. + line2 (str): + Second line of the description for the + sitelink. If this value is set, line1 must also + be set. The length of this string should be + between 0 and 35, inclusive. + + This field is a member of `oneof`_ ``_line2``. + final_urls (MutableSequence[str]): + A list of possible final URLs after all cross + domain redirects. + final_mobile_urls (MutableSequence[str]): + A list of possible final mobile URLs after + all cross domain redirects. + tracking_url_template (str): + URL template for constructing a tracking URL. + + This field is a member of `oneof`_ ``_tracking_url_template``. + url_custom_parameters (MutableSequence[google.ads.googleads.v24.common.types.CustomParameter]): + A list of mappings to be used for substituting URL custom + parameter tags in the tracking_url_template, final_urls, + and/or final_mobile_urls. + final_url_suffix (str): + Final URL suffix to be appended to landing + page URLs served with parallel tracking. + + This field is a member of `oneof`_ ``_final_url_suffix``. + """ + + link_text: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + line1: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + line2: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + final_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=12, + ) + final_mobile_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=13, + ) + tracking_url_template: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + url_custom_parameters: MutableSequence[custom_parameter.CustomParameter] = ( + proto.RepeatedField( + proto.MESSAGE, + number=7, + message=custom_parameter.CustomParameter, + ) + ) + final_url_suffix: str = proto.Field( + proto.STRING, + number=15, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/feed_common.py b/google/ads/googleads/v24/common/types/feed_common.py new file mode 100644 index 000000000..98c3f9075 --- /dev/null +++ b/google/ads/googleads/v24/common/types/feed_common.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "Money", + }, +) + + +class Money(proto.Message): + r"""Represents a price in a particular currency. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + currency_code (str): + Three-character ISO 4217 currency code. + + This field is a member of `oneof`_ ``_currency_code``. + amount_micros (int): + Amount in micros. One million is equivalent + to one unit. + + This field is a member of `oneof`_ ``_amount_micros``. + """ + + currency_code: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + amount_micros: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/final_app_url.py b/google/ads/googleads/v24/common/types/final_app_url.py new file mode 100644 index 000000000..29b23bd77 --- /dev/null +++ b/google/ads/googleads/v24/common/types/final_app_url.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import app_url_operating_system_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "FinalAppUrl", + }, +) + + +class FinalAppUrl(proto.Message): + r"""A URL for deep linking into an app for the given operating + system. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + os_type (google.ads.googleads.v24.enums.types.AppUrlOperatingSystemTypeEnum.AppUrlOperatingSystemType): + The operating system targeted by this URL. + Required. + url (str): + The app deep link URL. Deep links specify a location in an + app that corresponds to the content you'd like to show, and + should be of the form {scheme}://{host_path} The scheme + identifies which app to open. For your app, you can use a + custom scheme that starts with the app's name. The host and + path specify the unique location in the app where your + content exists. Example: "exampleapp://productid_1234". + Required. + + This field is a member of `oneof`_ ``_url``. + """ + + os_type: ( + app_url_operating_system_type.AppUrlOperatingSystemTypeEnum.AppUrlOperatingSystemType + ) = proto.Field( + proto.ENUM, + number=1, + enum=app_url_operating_system_type.AppUrlOperatingSystemTypeEnum.AppUrlOperatingSystemType, + ) + url: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/frequency_cap.py b/google/ads/googleads/v24/common/types/frequency_cap.py new file mode 100644 index 000000000..a34956160 --- /dev/null +++ b/google/ads/googleads/v24/common/types/frequency_cap.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import frequency_cap_event_type +from google.ads.googleads.v24.enums.types import frequency_cap_level +from google.ads.googleads.v24.enums.types import frequency_cap_time_unit + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "FrequencyCapEntry", + "FrequencyCapKey", + }, +) + + +class FrequencyCapEntry(proto.Message): + r"""A rule specifying the maximum number of times an ad (or some + set of ads) can be shown to a user over a particular time + period. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + key (google.ads.googleads.v24.common.types.FrequencyCapKey): + The key of a particular frequency cap. There + can be no more than one frequency cap with the + same key. + cap (int): + Maximum number of events allowed during the + time range by this cap. + + This field is a member of `oneof`_ ``_cap``. + """ + + key: "FrequencyCapKey" = proto.Field( + proto.MESSAGE, + number=1, + message="FrequencyCapKey", + ) + cap: int = proto.Field( + proto.INT32, + number=3, + optional=True, + ) + + +class FrequencyCapKey(proto.Message): + r"""A group of fields used as keys for a frequency cap. + There can be no more than one frequency cap with the same key. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + level (google.ads.googleads.v24.enums.types.FrequencyCapLevelEnum.FrequencyCapLevel): + The level on which the cap is to be applied + (for example, ad group ad, ad group). The cap is + applied to all the entities of this level. + event_type (google.ads.googleads.v24.enums.types.FrequencyCapEventTypeEnum.FrequencyCapEventType): + The type of event that the cap applies to + (for example, impression). + time_unit (google.ads.googleads.v24.enums.types.FrequencyCapTimeUnitEnum.FrequencyCapTimeUnit): + Unit of time the cap is defined at (for + example, day, week). + time_length (int): + Number of time units the cap lasts. + + This field is a member of `oneof`_ ``_time_length``. + """ + + level: frequency_cap_level.FrequencyCapLevelEnum.FrequencyCapLevel = ( + proto.Field( + proto.ENUM, + number=1, + enum=frequency_cap_level.FrequencyCapLevelEnum.FrequencyCapLevel, + ) + ) + event_type: ( + frequency_cap_event_type.FrequencyCapEventTypeEnum.FrequencyCapEventType + ) = proto.Field( + proto.ENUM, + number=3, + enum=frequency_cap_event_type.FrequencyCapEventTypeEnum.FrequencyCapEventType, + ) + time_unit: ( + frequency_cap_time_unit.FrequencyCapTimeUnitEnum.FrequencyCapTimeUnit + ) = proto.Field( + proto.ENUM, + number=2, + enum=frequency_cap_time_unit.FrequencyCapTimeUnitEnum.FrequencyCapTimeUnit, + ) + time_length: int = proto.Field( + proto.INT32, + number=5, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/goal_common.py b/google/ads/googleads/v24/common/types/goal_common.py new file mode 100644 index 000000000..8c59cb8ee --- /dev/null +++ b/google/ads/googleads/v24/common/types/goal_common.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerLifecycleOptimizationValueSettings", + }, +) + + +class CustomerLifecycleOptimizationValueSettings(proto.Message): + r"""Lifecycle goal optimization value settings. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + additional_value (float): + Value of the lifecycle goal. For example, for + retention goals, value is the incremental + conversion value for lapsed customers who are + not of high value. + + This field is a member of `oneof`_ ``_additional_value``. + additional_high_lifetime_value (float): + High lifetime value of the lifecycle goal. + For example, for customer acquisition goals, + high lifetime value is the incremental + conversion value for lapsed customers who are of + high value. High lifetime value should be + greater than value, if set. + + This field is a member of `oneof`_ ``_additional_high_lifetime_value``. + """ + + additional_value: float = proto.Field( + proto.DOUBLE, + number=1, + optional=True, + ) + additional_high_lifetime_value: float = proto.Field( + proto.DOUBLE, + number=2, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/goal_setting.py b/google/ads/googleads/v24/common/types/goal_setting.py new file mode 100644 index 000000000..3d699167d --- /dev/null +++ b/google/ads/googleads/v24/common/types/goal_setting.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import goal_common + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "GoalSetting", + }, +) + + +class GoalSetting(proto.Message): + r"""Goal setting.""" + + class RetentionGoal(proto.Message): + r"""Retention goal settings. + + Attributes: + value_settings (google.ads.googleads.v24.common.types.CustomerLifecycleOptimizationValueSettings): + Retention goal value settings. + """ + + value_settings: ( + goal_common.CustomerLifecycleOptimizationValueSettings + ) = proto.Field( + proto.MESSAGE, + number=1, + message=goal_common.CustomerLifecycleOptimizationValueSettings, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/keyword_plan_common.py b/google/ads/googleads/v24/common/types/keyword_plan_common.py new file mode 100644 index 000000000..9498822ee --- /dev/null +++ b/google/ads/googleads/v24/common/types/keyword_plan_common.py @@ -0,0 +1,337 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import dates +from google.ads.googleads.v24.enums.types import device as gage_device +from google.ads.googleads.v24.enums.types import ( + keyword_plan_aggregate_metric_type, +) +from google.ads.googleads.v24.enums.types import keyword_plan_competition_level +from google.ads.googleads.v24.enums.types import keyword_plan_concept_group_type +from google.ads.googleads.v24.enums.types import month_of_year + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanHistoricalMetrics", + "HistoricalMetricsOptions", + "MonthlySearchVolume", + "KeywordPlanAggregateMetrics", + "KeywordPlanAggregateMetricResults", + "KeywordPlanDeviceSearches", + "KeywordAnnotations", + "KeywordConcept", + "ConceptGroup", + }, +) + + +class KeywordPlanHistoricalMetrics(proto.Message): + r"""Historical metrics specific to the targeting options + selected. Targeting options include geographies, network, and so + on. Refer to + https://support.google.com/google-ads/answer/3022575 for more + details. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + avg_monthly_searches (int): + Approximate number of monthly searches on + this query, averaged for the past 12 months. + + This field is a member of `oneof`_ ``_avg_monthly_searches``. + monthly_search_volumes (MutableSequence[google.ads.googleads.v24.common.types.MonthlySearchVolume]): + Approximate number of searches on this query + for the past twelve months. + competition (google.ads.googleads.v24.enums.types.KeywordPlanCompetitionLevelEnum.KeywordPlanCompetitionLevel): + The competition level for the query. + competition_index (int): + The competition index for the query in the range [0, 100]. + Shows how competitive ad placement is for a keyword. The + level of competition from 0-100 is determined by the number + of ad slots filled divided by the total number of ad slots + available. If not enough data is available, null is + returned. + + This field is a member of `oneof`_ ``_competition_index``. + low_top_of_page_bid_micros (int): + Top of page bid low range (20th percentile) + in micros for the keyword. + + This field is a member of `oneof`_ ``_low_top_of_page_bid_micros``. + high_top_of_page_bid_micros (int): + Top of page bid high range (80th percentile) + in micros for the keyword. + + This field is a member of `oneof`_ ``_high_top_of_page_bid_micros``. + average_cpc_micros (int): + Average Cost Per Click in micros for the + keyword. + + This field is a member of `oneof`_ ``_average_cpc_micros``. + """ + + avg_monthly_searches: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + monthly_search_volumes: MutableSequence["MonthlySearchVolume"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=6, + message="MonthlySearchVolume", + ) + ) + competition: ( + keyword_plan_competition_level.KeywordPlanCompetitionLevelEnum.KeywordPlanCompetitionLevel + ) = proto.Field( + proto.ENUM, + number=2, + enum=keyword_plan_competition_level.KeywordPlanCompetitionLevelEnum.KeywordPlanCompetitionLevel, + ) + competition_index: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + low_top_of_page_bid_micros: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + high_top_of_page_bid_micros: int = proto.Field( + proto.INT64, + number=10, + optional=True, + ) + average_cpc_micros: int = proto.Field( + proto.INT64, + number=11, + optional=True, + ) + + +class HistoricalMetricsOptions(proto.Message): + r"""Historical metrics options. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + year_month_range (google.ads.googleads.v24.common.types.YearMonthRange): + The year month range for historical metrics. If not + specified, metrics for the past 12 months are returned. + Search metrics are available for the past 4 years. If the + search volume is not available for the entire + year_month_range provided, the subset of the year month + range for which search volume is available are returned. + + This field is a member of `oneof`_ ``_year_month_range``. + include_average_cpc (bool): + Indicates whether to include average cost per + click value. Average CPC is provided only for + legacy support. + """ + + year_month_range: dates.YearMonthRange = proto.Field( + proto.MESSAGE, + number=1, + optional=True, + message=dates.YearMonthRange, + ) + include_average_cpc: bool = proto.Field( + proto.BOOL, + number=2, + ) + + +class MonthlySearchVolume(proto.Message): + r"""Monthly search volume. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + year (int): + The year of the search volume (for example, + 2020). + + This field is a member of `oneof`_ ``_year``. + month (google.ads.googleads.v24.enums.types.MonthOfYearEnum.MonthOfYear): + The month of the search volume. + monthly_searches (int): + Approximate number of searches for the month. + A null value indicates the search volume is + unavailable for that month. + + This field is a member of `oneof`_ ``_monthly_searches``. + """ + + year: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + month: month_of_year.MonthOfYearEnum.MonthOfYear = proto.Field( + proto.ENUM, + number=2, + enum=month_of_year.MonthOfYearEnum.MonthOfYear, + ) + monthly_searches: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + + +class KeywordPlanAggregateMetrics(proto.Message): + r"""The aggregate metrics specification of the request. + + Attributes: + aggregate_metric_types (MutableSequence[google.ads.googleads.v24.enums.types.KeywordPlanAggregateMetricTypeEnum.KeywordPlanAggregateMetricType]): + The list of aggregate metrics to fetch data. + """ + + aggregate_metric_types: MutableSequence[ + keyword_plan_aggregate_metric_type.KeywordPlanAggregateMetricTypeEnum.KeywordPlanAggregateMetricType + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum=keyword_plan_aggregate_metric_type.KeywordPlanAggregateMetricTypeEnum.KeywordPlanAggregateMetricType, + ) + + +class KeywordPlanAggregateMetricResults(proto.Message): + r"""The aggregated historical metrics for keyword plan keywords. + + Attributes: + device_searches (MutableSequence[google.ads.googleads.v24.common.types.KeywordPlanDeviceSearches]): + The aggregate searches for all the keywords + segmented by device for the specified time. + Supports the following device types: MOBILE, + TABLET, DESKTOP. + + This is only set when + KeywordPlanAggregateMetricTypeEnum.DEVICE is set + in the KeywordPlanAggregateMetrics field in the + request. + """ + + device_searches: MutableSequence["KeywordPlanDeviceSearches"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="KeywordPlanDeviceSearches", + ) + ) + + +class KeywordPlanDeviceSearches(proto.Message): + r"""The total searches for the device type during the specified + time period. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + device (google.ads.googleads.v24.enums.types.DeviceEnum.Device): + The device type. + search_count (int): + The total searches for the device. + + This field is a member of `oneof`_ ``_search_count``. + """ + + device: gage_device.DeviceEnum.Device = proto.Field( + proto.ENUM, + number=1, + enum=gage_device.DeviceEnum.Device, + ) + search_count: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + +class KeywordAnnotations(proto.Message): + r"""The annotations for the keyword plan keywords. + + Attributes: + concepts (MutableSequence[google.ads.googleads.v24.common.types.KeywordConcept]): + The list of concepts for the keyword. + """ + + concepts: MutableSequence["KeywordConcept"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="KeywordConcept", + ) + + +class KeywordConcept(proto.Message): + r"""The concept for the keyword. + + Attributes: + name (str): + The concept name for the keyword in the concept_group. + concept_group (google.ads.googleads.v24.common.types.ConceptGroup): + The concept group of the concept details. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + concept_group: "ConceptGroup" = proto.Field( + proto.MESSAGE, + number=2, + message="ConceptGroup", + ) + + +class ConceptGroup(proto.Message): + r"""The concept group for the keyword concept. + + Attributes: + name (str): + The concept group name. + type_ (google.ads.googleads.v24.enums.types.KeywordPlanConceptGroupTypeEnum.KeywordPlanConceptGroupType): + The concept group type. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + type_: ( + keyword_plan_concept_group_type.KeywordPlanConceptGroupTypeEnum.KeywordPlanConceptGroupType + ) = proto.Field( + proto.ENUM, + number=2, + enum=keyword_plan_concept_group_type.KeywordPlanConceptGroupTypeEnum.KeywordPlanConceptGroupType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/lifecycle_goals.py b/google/ads/googleads/v24/common/types/lifecycle_goals.py new file mode 100644 index 000000000..c7ff94a8d --- /dev/null +++ b/google/ads/googleads/v24/common/types/lifecycle_goals.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "LifecycleGoalValueSettings", + }, +) + + +class LifecycleGoalValueSettings(proto.Message): + r"""Lifecycle goal value settings. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (float): + Value of the lifecycle goal. For example, for + customer acquisition goal, value is the + incremental conversion value for new customers + who are not of high value. + + This field is a member of `oneof`_ ``_value``. + high_lifetime_value (float): + High lifetime value of the lifecycle goal. + For example, for customer acquisition goal, high + lifetime value is the incremental conversion + value for new customers who are of high value. + High lifetime value should be greater than + value, if set. + + This field is a member of `oneof`_ ``_high_lifetime_value``. + """ + + value: float = proto.Field( + proto.DOUBLE, + number=1, + optional=True, + ) + high_lifetime_value: float = proto.Field( + proto.DOUBLE, + number=2, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/local_services.py b/google/ads/googleads/v24/common/types/local_services.py new file mode 100644 index 000000000..2ffcf6503 --- /dev/null +++ b/google/ads/googleads/v24/common/types/local_services.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesDocumentReadOnly", + }, +) + + +class LocalServicesDocumentReadOnly(proto.Message): + r"""A Local Services Document with read only accessible data. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + document_url (str): + URL to access an already uploaded Local + Services document. + + This field is a member of `oneof`_ ``_document_url``. + """ + + document_url: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/metric_goal.py b/google/ads/googleads/v24/common/types/metric_goal.py new file mode 100644 index 000000000..fde898c90 --- /dev/null +++ b/google/ads/googleads/v24/common/types/metric_goal.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import experiment_metric +from google.ads.googleads.v24.enums.types import experiment_metric_direction + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "MetricGoal", + }, +) + + +class MetricGoal(proto.Message): + r"""A metric goal for an experiment. + + Attributes: + metric (google.ads.googleads.v24.enums.types.ExperimentMetricEnum.ExperimentMetric): + The metric of the goal. For example, clicks, + impressions, cost, conversions, etc. + direction (google.ads.googleads.v24.enums.types.ExperimentMetricDirectionEnum.ExperimentMetricDirection): + The metric direction of the goal. For + example, increase, decrease, no change. + """ + + metric: experiment_metric.ExperimentMetricEnum.ExperimentMetric = ( + proto.Field( + proto.ENUM, + number=1, + enum=experiment_metric.ExperimentMetricEnum.ExperimentMetric, + ) + ) + direction: ( + experiment_metric_direction.ExperimentMetricDirectionEnum.ExperimentMetricDirection + ) = proto.Field( + proto.ENUM, + number=2, + enum=experiment_metric_direction.ExperimentMetricDirectionEnum.ExperimentMetricDirection, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/metrics.py b/google/ads/googleads/v24/common/types/metrics.py new file mode 100644 index 000000000..a05f44cda --- /dev/null +++ b/google/ads/googleads/v24/common/types/metrics.py @@ -0,0 +1,3376 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import interaction_event_type +from google.ads.googleads.v24.enums.types import quality_score_bucket + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "Metrics", + "SearchVolumeRange", + }, +) + + +class Metrics(proto.Message): + r"""Metrics data. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + absolute_top_impression_percentage (float): + Search absolute top impression share is the + percentage of your Search ad impressions that + are shown in the most prominent Search position. + + This field is a member of `oneof`_ ``_absolute_top_impression_percentage``. + active_view_cpm (float): + Average cost of viewable impressions + (``active_view_impressions``). + + This field is a member of `oneof`_ ``_active_view_cpm``. + active_view_ctr (float): + Active view measurable clicks divided by + active view viewable impressions. + This metric is reported only for the Display + Network. + + This field is a member of `oneof`_ ``_active_view_ctr``. + active_view_impressions (int): + A measurement of how often your ad has become + viewable on a Display Network site. + + This field is a member of `oneof`_ ``_active_view_impressions``. + active_view_measurability (float): + The ratio of impressions that could be + measured by Active View over the number of + served impressions. + + This field is a member of `oneof`_ ``_active_view_measurability``. + active_view_measurable_cost_micros (int): + The cost of the impressions you received that + were measurable by Active View. + + This field is a member of `oneof`_ ``_active_view_measurable_cost_micros``. + active_view_measurable_impressions (int): + The number of times your ads are appearing on + placements in positions where they can be seen. + + This field is a member of `oneof`_ ``_active_view_measurable_impressions``. + active_view_viewability (float): + The percentage of time when your ad appeared + on an Active View enabled site (measurable + impressions) and was viewable (viewable + impressions). + + This field is a member of `oneof`_ ``_active_view_viewability``. + all_conversions_from_interactions_rate (float): + All conversions from interactions (as oppose + to view through conversions) divided by the + number of ad interactions. + + This field is a member of `oneof`_ ``_all_conversions_from_interactions_rate``. + all_conversions_value (float): + The value of all conversions. + + This field is a member of `oneof`_ ``_all_conversions_value``. + all_conversions_value_by_conversion_date (float): + The value of all conversions. When this column is selected + with date, the values in date column means the conversion + date. Details for the by_conversion_date columns are + available at + https://support.google.com/google-ads/answer/9549009. + + This field is a member of `oneof`_ ``_all_conversions_value_by_conversion_date``. + all_new_customer_lifetime_value (float): + All of new customers' lifetime conversion value. If you have + set up customer acquisition goal at either account level or + campaign level, this will include the additional conversion + value from new customers for both biddable and non-biddable + conversions. If your campaign has adopted the customer + acquisition goal and selected "bid higher for new + customers", these values will be included in + "all_conversions_value". See + https://support.google.com/google-ads/answer/12080169 for + more details. + + This field is a member of `oneof`_ ``_all_new_customer_lifetime_value``. + all_conversions (float): + The total number of conversions. This includes all + conversions regardless of the value of + include_in_conversions_metric. + + This field is a member of `oneof`_ ``_all_conversions``. + all_conversions_by_conversion_date (float): + The total number of conversions. This includes all + conversions regardless of the value of + include_in_conversions_metric. When this column is selected + with date, the values in date column means the conversion + date. Details for the by_conversion_date columns are + available at + https://support.google.com/google-ads/answer/9549009. + + This field is a member of `oneof`_ ``_all_conversions_by_conversion_date``. + all_conversions_value_per_cost (float): + The value of all conversions divided by the + total cost of ad interactions (such as clicks + for text ads or views for video ads). + + This field is a member of `oneof`_ ``_all_conversions_value_per_cost``. + all_conversions_from_click_to_call (float): + The number of times people clicked the "Call" + button to call a business during or after + clicking an ad. This number doesn't include + whether or not calls were connected, or the + duration of any calls. + + This metric applies to feed items only. + + This field is a member of `oneof`_ ``_all_conversions_from_click_to_call``. + all_conversions_from_directions (float): + The number of times people clicked a "Get + directions" button to navigate to a business + after clicking an ad. + + This metric applies to feed items only. + + This field is a member of `oneof`_ ``_all_conversions_from_directions``. + all_conversions_from_interactions_value_per_interaction (float): + The value of all conversions from + interactions divided by the total number of + interactions. + + This field is a member of `oneof`_ ``_all_conversions_from_interactions_value_per_interaction``. + all_conversions_from_menu (float): + The number of times people clicked a link to + view a business's menu after clicking an ad. + + This metric applies to feed items only. + + This field is a member of `oneof`_ ``_all_conversions_from_menu``. + all_conversions_from_order (float): + The number of times people placed an order at + a business after clicking an ad. + + This metric applies to feed items only. + + This field is a member of `oneof`_ ``_all_conversions_from_order``. + all_conversions_from_other_engagement (float): + The number of other conversions (for example, + posting a review or saving a location for a + business) that occurred after people clicked an + ad. + + This metric applies to feed items only. + + This field is a member of `oneof`_ ``_all_conversions_from_other_engagement``. + all_conversions_from_store_visit (float): + Estimated number of times people visited a + business after clicking an ad. + This metric applies to feed items only. + + This field is a member of `oneof`_ ``_all_conversions_from_store_visit``. + all_conversions_from_store_website (float): + The number of times that people were taken to + a business's URL after clicking an ad. + + This metric applies to feed items only. + + This field is a member of `oneof`_ ``_all_conversions_from_store_website``. + auction_insight_search_absolute_top_impression_percentage (float): + This metric is part of the Auction Insights + report, and tells how often the ads of another + participant showed in the most prominent + position on the search results page. + This percentage is computed only over the + auctions that you appeared in the page. + + This metric is not publicly available. + + This field is a member of `oneof`_ ``_auction_insight_search_absolute_top_impression_percentage``. + auction_insight_search_impression_share (float): + This metric is part of the Auction Insights + report, and tells the percentage of impressions + that another participant obtained, over the + total number of impressions that your ads were + eligible for. Any value below 0.1 is reported as + 0.0999. + + This metric is not publicly available. + + This field is a member of `oneof`_ ``_auction_insight_search_impression_share``. + auction_insight_search_outranking_share (float): + This metric is part of the Auction Insights + report, and tells the percentage of impressions + that your ads outranked (showed above) another + participant in the auction, compared to the + total number of impressions that your ads were + eligible for. + Any value below 0.1 is reported as 0.0999. + + This metric is not publicly available. + + This field is a member of `oneof`_ ``_auction_insight_search_outranking_share``. + auction_insight_search_overlap_rate (float): + This metric is part of the Auction Insights + report, and tells how often another + participant's ad received an impression when + your ad also received an impression. + + This metric is not publicly available. + + This field is a member of `oneof`_ ``_auction_insight_search_overlap_rate``. + auction_insight_search_position_above_rate (float): + This metric is part of the Auction Insights + report, and tells how often another + participant's ad was shown in a higher position + than yours, when both of your ads were shown at + the same page. + + This metric is not publicly available. + + This field is a member of `oneof`_ ``_auction_insight_search_position_above_rate``. + auction_insight_search_top_impression_percentage (float): + This metric is part of the Auction Insights + report, and tells how often the ads of another + participant showed adjacent to the top organic + search results. This percentage is computed only + over the auctions that you appeared in the page. + + This metric is not publicly available. + + This field is a member of `oneof`_ ``_auction_insight_search_top_impression_percentage``. + average_cost (float): + The average amount you pay per interaction. + This amount is the total cost of your ads + divided by the total number of interactions. + + This field is a member of `oneof`_ ``_average_cost``. + average_cpc (float): + The total cost of all clicks divided by the + total number of clicks received. + + This field is a member of `oneof`_ ``_average_cpc``. + average_cpe (float): + The average amount that you've been charged + for an ad engagement. This amount is the total + cost of all ad engagements divided by the total + number of ad engagements. + + This field is a member of `oneof`_ ``_average_cpe``. + average_cpm (float): + Average cost-per-thousand impressions (CPM). + + This field is a member of `oneof`_ ``_average_cpm``. + trueview_average_cpv (float): + The average amount you pay each time someone + views your ad. The average CPV is defined by the + total cost of all ad views divided by the number + of TrueView views. + + This field is a member of `oneof`_ ``_trueview_average_cpv``. + average_page_views (float): + Average number of pages viewed per session. + + This field is a member of `oneof`_ ``_average_page_views``. + average_time_on_site (float): + Total duration of all sessions (in seconds) / + number of sessions. Imported from Google + Analytics. + + This field is a member of `oneof`_ ``_average_time_on_site``. + benchmark_average_max_cpc (float): + An indication of how other advertisers are + bidding on similar products. + + This field is a member of `oneof`_ ``_benchmark_average_max_cpc``. + biddable_app_install_conversions (float): + Number of app installs. + + This field is a member of `oneof`_ ``_biddable_app_install_conversions``. + biddable_app_post_install_conversions (float): + Number of in-app actions. + + This field is a member of `oneof`_ ``_biddable_app_post_install_conversions``. + biddable_cohort_app_post_install_conversions (float): + Participated in-app actions. The number of in + app actions that come directly or indirectly + from the campaign. + + This field is a member of `oneof`_ ``_biddable_cohort_app_post_install_conversions``. + benchmark_ctr (float): + An indication on how other advertisers' + Shopping ads for similar products are performing + based on how often people who see their ad click + on it. + + This field is a member of `oneof`_ ``_benchmark_ctr``. + bounce_rate (float): + Percentage of clicks where the user only + visited a single page on your site. Imported + from Google Analytics. + + This field is a member of `oneof`_ ``_bounce_rate``. + clicks (int): + The number of clicks. + + This field is a member of `oneof`_ ``_clicks``. + combined_clicks (int): + The number of times your ad or your site's + listing in the unpaid results was clicked. See + the help page at + https://support.google.com/google-ads/answer/3097241 + for details. + + This field is a member of `oneof`_ ``_combined_clicks``. + combined_clicks_per_query (float): + The number of times your ad or your site's listing in the + unpaid results was clicked (combined_clicks) divided by + combined_queries. See the help page at + https://support.google.com/google-ads/answer/3097241 for + details. + + This field is a member of `oneof`_ ``_combined_clicks_per_query``. + combined_queries (int): + The number of searches that returned pages + from your site in the unpaid results or showed + one of your text ads. See the help page at + https://support.google.com/google-ads/answer/3097241 + for details. + + This field is a member of `oneof`_ ``_combined_queries``. + content_budget_lost_impression_share (float): + The estimated percent of times that your ad + was eligible to show on the Display Network but + didn't because your budget was too low. Note: + Content budget lost impression share is reported + in the range of 0 to 0.9. Any value above 0.9 is + reported as 0.9001. + + This field is a member of `oneof`_ ``_content_budget_lost_impression_share``. + content_impression_share (float): + The impressions you've received on the + Display Network divided by the estimated number + of impressions you were eligible to receive. + Note: Content impression share is reported in + the range of 0.1 to 1. Any value below 0.1 is + reported as 0.0999. + + This field is a member of `oneof`_ ``_content_impression_share``. + conversion_last_received_request_date_time (str): + The last date/time a conversion tag for this + conversion action successfully fired and was + seen by Google Ads. This firing event may not + have been the result of an attributable + conversion (for example, because the tag was + fired from a browser that did not previously + click an ad from an appropriate advertiser). The + date/time is in the customer's time zone. + + This field is a member of `oneof`_ ``_conversion_last_received_request_date_time``. + conversion_last_conversion_date (str): + The date of the most recent conversion for + this conversion action. The date is in the + customer's time zone. + + This field is a member of `oneof`_ ``_conversion_last_conversion_date``. + content_rank_lost_impression_share (float): + The estimated percentage of impressions on + the Display Network that your ads didn't receive + due to poor Ad Rank. Note: Content rank lost + impression share is reported in the range of 0 + to 0.9. Any value above 0.9 is reported as + 0.9001. + + This field is a member of `oneof`_ ``_content_rank_lost_impression_share``. + conversions_from_interactions_rate (float): + Conversions from interactions divided by the number of ad + interactions (such as clicks for text ads or views for video + ads). This only includes conversion actions which + include_in_conversions_metric attribute is set to true. If + you use conversion-based bidding, your bid strategies will + optimize for these conversions. + + This field is a member of `oneof`_ ``_conversions_from_interactions_rate``. + conversions_value (float): + The value of conversions. This only includes conversion + actions which include_in_conversions_metric attribute is set + to true. If you use conversion-based bidding, your bid + strategies will optimize for these conversions. + + This field is a member of `oneof`_ ``_conversions_value``. + conversions_value_by_conversion_date (float): + The value of conversions. This only includes conversion + actions which include_in_conversions_metric attribute is set + to true. If you use conversion-based bidding, your bid + strategies will optimize for these conversions. When this + column is selected with date, the values in date column + means the conversion date. Details for the + by_conversion_date columns are available at + https://support.google.com/google-ads/answer/9549009. + + This field is a member of `oneof`_ ``_conversions_value_by_conversion_date``. + new_customer_lifetime_value (float): + New customers' lifetime conversion value. If you have set up + customer acquisition goal at either account level or + campaign level, this will include the additional conversion + value from new customers for biddable conversions. If your + campaign has adopted the customer acquisition goal and + selected "bid higher for new customers", these values will + be included in "conversions_value" for optimization. See + https://support.google.com/google-ads/answer/12080169 for + more details. + + This field is a member of `oneof`_ ``_new_customer_lifetime_value``. + conversions_value_per_cost (float): + The value of conversions divided by the cost of ad + interactions. This only includes conversion actions which + include_in_conversions_metric attribute is set to true. If + you use conversion-based bidding, your bid strategies will + optimize for these conversions. + + This field is a member of `oneof`_ ``_conversions_value_per_cost``. + conversions_from_interactions_value_per_interaction (float): + The value of conversions from interactions divided by the + number of ad interactions. This only includes conversion + actions which include_in_conversions_metric attribute is set + to true. If you use conversion-based bidding, your bid + strategies will optimize for these conversions. + + This field is a member of `oneof`_ ``_conversions_from_interactions_value_per_interaction``. + conversions (float): + The number of conversions. This only includes conversion + actions which include_in_conversions_metric attribute is set + to true. If you use conversion-based bidding, your bid + strategies will optimize for these conversions. + + This field is a member of `oneof`_ ``_conversions``. + conversions_by_conversion_date (float): + The number of conversions. This only includes conversion + actions which include_in_conversions_metric attribute is set + to true. If you use conversion-based bidding, your bid + strategies will optimize for these conversions. When this + column is selected with date, the values in date column + means the conversion date. Details for the + by_conversion_date columns are available at + https://support.google.com/google-ads/answer/9549009. + + This field is a member of `oneof`_ ``_conversions_by_conversion_date``. + cost_micros (int): + The sum of your cost-per-click (CPC) and + cost-per-thousand impressions (CPM) costs during + this period. + + This field is a member of `oneof`_ ``_cost_micros``. + cost_per_all_conversions (float): + The cost of ad interactions divided by all + conversions. + + This field is a member of `oneof`_ ``_cost_per_all_conversions``. + cost_per_conversion (float): + The cost of ad interactions divided by conversions. This + only includes conversion actions which + include_in_conversions_metric attribute is set to true. If + you use conversion-based bidding, your bid strategies will + optimize for these conversions. + + This field is a member of `oneof`_ ``_cost_per_conversion``. + cost_per_current_model_attributed_conversion (float): + The cost of ad interactions divided by current model + attributed conversions. This only includes conversion + actions which include_in_conversions_metric attribute is set + to true. If you use conversion-based bidding, your bid + strategies will optimize for these conversions. + + This field is a member of `oneof`_ ``_cost_per_current_model_attributed_conversion``. + cross_device_conversions (float): + Conversions from when a customer clicks on a Google Ads ad + on one device, then converts on a different device or + browser. Cross-device conversions are already included in + all_conversions. + + This field is a member of `oneof`_ ``_cross_device_conversions``. + cross_device_conversions_by_conversion_date (float): + The number of cross-device conversions by conversion date. + Details for the by_conversion_date columns are available at + https://support.google.com/google-ads/answer/9549009. + + This field is a member of `oneof`_ ``_cross_device_conversions_by_conversion_date``. + cross_device_conversions_value (float): + The sum of the value of cross-device + conversions. + + This field is a member of `oneof`_ ``_cross_device_conversions_value``. + cross_device_conversions_value_micros (int): + The sum of the value of cross-device + conversions, in micros. + + This field is a member of `oneof`_ ``_cross_device_conversions_value_micros``. + cross_device_conversions_value_by_conversion_date (float): + The sum of cross-device conversions value by conversion + date. Details for the by_conversion_date columns are + available at + https://support.google.com/google-ads/answer/9549009. + + This field is a member of `oneof`_ ``_cross_device_conversions_value_by_conversion_date``. + ctr (float): + The number of clicks your ad receives + (Clicks) divided by the number of times your ad + is shown (Impressions). + + This field is a member of `oneof`_ ``_ctr``. + current_model_attributed_conversions (float): + Shows how your historic conversions data would look under + the attribution model you've currently selected. This only + includes conversion actions which + include_in_conversions_metric attribute is set to true. If + you use conversion-based bidding, your bid strategies will + optimize for these conversions. + + This field is a member of `oneof`_ ``_current_model_attributed_conversions``. + current_model_attributed_conversions_from_interactions_rate (float): + Current model attributed conversions from interactions + divided by the number of ad interactions (such as clicks for + text ads or views for video ads). This only includes + conversion actions which include_in_conversions_metric + attribute is set to true. If you use conversion-based + bidding, your bid strategies will optimize for these + conversions. + + This field is a member of `oneof`_ ``_current_model_attributed_conversions_from_interactions_rate``. + current_model_attributed_conversions_from_interactions_value_per_interaction (float): + The value of current model attributed conversions from + interactions divided by the number of ad interactions. This + only includes conversion actions which + include_in_conversions_metric attribute is set to true. If + you use conversion-based bidding, your bid strategies will + optimize for these conversions. + + This field is a member of `oneof`_ ``_current_model_attributed_conversions_from_interactions_value_per_interaction``. + current_model_attributed_conversions_value (float): + The value of current model attributed conversions. This only + includes conversion actions which + include_in_conversions_metric attribute is set to true. If + you use conversion-based bidding, your bid strategies will + optimize for these conversions. + + This field is a member of `oneof`_ ``_current_model_attributed_conversions_value``. + current_model_attributed_conversions_value_per_cost (float): + The value of current model attributed conversions divided by + the cost of ad interactions. This only includes conversion + actions which include_in_conversions_metric attribute is set + to true. If you use conversion-based bidding, your bid + strategies will optimize for these conversions. + + This field is a member of `oneof`_ ``_current_model_attributed_conversions_value_per_cost``. + engagement_rate (float): + How often people engage with your ad after + it's shown to them. This is the number of ad + expansions divided by the number of times your + ad is shown. + + This field is a member of `oneof`_ ``_engagement_rate``. + engagements (int): + The number of engagements. + An engagement occurs when a viewer expands your + Lightbox ad. Also, in the future, other ad types + may support engagement metrics. + + This field is a member of `oneof`_ ``_engagements``. + hotel_average_lead_value_micros (float): + Average lead value based on clicks. + + This field is a member of `oneof`_ ``_hotel_average_lead_value_micros``. + hotel_commission_rate_micros (int): + Commission bid rate in micros. A 20% + commission is represented as 200,000. + + This field is a member of `oneof`_ ``_hotel_commission_rate_micros``. + hotel_expected_commission_cost (float): + Expected commission cost. The result of multiplying the + commission value times the hotel_commission_rate in + advertiser currency. + + This field is a member of `oneof`_ ``_hotel_expected_commission_cost``. + hotel_price_difference_percentage (float): + The average price difference between the + price offered by reporting hotel advertiser and + the cheapest price offered by the competing + advertiser. + + This field is a member of `oneof`_ ``_hotel_price_difference_percentage``. + hotel_eligible_impressions (int): + The number of impressions that hotel partners + could have had given their feed performance. + + This field is a member of `oneof`_ ``_hotel_eligible_impressions``. + historical_creative_quality_score (google.ads.googleads.v24.enums.types.QualityScoreBucketEnum.QualityScoreBucket): + The creative historical quality score. + historical_landing_page_quality_score (google.ads.googleads.v24.enums.types.QualityScoreBucketEnum.QualityScoreBucket): + The quality of historical landing page + experience. + historical_quality_score (int): + The historical quality score. + + This field is a member of `oneof`_ ``_historical_quality_score``. + historical_search_predicted_ctr (google.ads.googleads.v24.enums.types.QualityScoreBucketEnum.QualityScoreBucket): + The historical search predicted click through + rate (CTR). + gmail_forwards (int): + The number of times the ad was forwarded to + someone else as a message. + + This field is a member of `oneof`_ ``_gmail_forwards``. + gmail_saves (int): + The number of times someone has saved your + Gmail ad to their inbox as a message. + + This field is a member of `oneof`_ ``_gmail_saves``. + gmail_secondary_clicks (int): + The number of clicks to the landing page on + the expanded state of Gmail ads. + + This field is a member of `oneof`_ ``_gmail_secondary_clicks``. + impressions_from_store_reach (int): + The number of times a business's + location-based ad was shown. + This metric applies to feed items only. + + This field is a member of `oneof`_ ``_impressions_from_store_reach``. + impressions (int): + Count of how often your ad has appeared on a + search results page or website on the Google + Network. + + This field is a member of `oneof`_ ``_impressions``. + interaction_rate (float): + How often people interact with your ad after + it is shown to them. This is the number of + interactions divided by the number of times your + ad is shown. + + This field is a member of `oneof`_ ``_interaction_rate``. + interactions (int): + The number of interactions. + An interaction is the main user action + associated with an ad format-clicks for text and + shopping ads, views for video ads, and so on. + + This field is a member of `oneof`_ ``_interactions``. + interaction_event_types (MutableSequence[google.ads.googleads.v24.enums.types.InteractionEventTypeEnum.InteractionEventType]): + The types of payable and free interactions. + invalid_click_rate (float): + The percentage of clicks filtered out of your + total number of clicks (filtered + non-filtered + clicks) during the reporting period. + + This field is a member of `oneof`_ ``_invalid_click_rate``. + invalid_clicks (int): + Number of clicks Google considers + illegitimate and doesn't charge you for. + + This field is a member of `oneof`_ ``_invalid_clicks``. + general_invalid_click_rate (float): + The percentage of clicks that have been + filtered out of your total number of clicks + (filtered + non-filtered clicks) due to being + general invalid clicks. These are clicks Google + considers illegitimate that are detected through + routine means of filtration (that is, known + invalid data-center traffic, bots and spiders or + other crawlers, irregular patterns, etc). You're + not charged for them, and they don't affect your + account statistics. See the help page at + https://support.google.com/campaignmanager/answer/6076504 + for details. + + This field is a member of `oneof`_ ``_general_invalid_click_rate``. + general_invalid_clicks (int): + Number of general invalid clicks. These are a + subset of your invalid clicks that are detected + through routine means of filtration (such as + known invalid data-center traffic, bots and + spiders or other crawlers, irregular patterns, + etc.). You're not charged for them, and they + don't affect your account statistics. See the + help page at + https://support.google.com/campaignmanager/answer/6076504 + for details. + + This field is a member of `oneof`_ ``_general_invalid_clicks``. + message_chats (int): + Number of message chats initiated for Click + To Message impressions that were message + tracking eligible. + + This field is a member of `oneof`_ ``_message_chats``. + message_impressions (int): + Number of Click To Message impressions that + were message tracking eligible. + + This field is a member of `oneof`_ ``_message_impressions``. + message_chat_rate (float): + Number of message chats initiated (message_chats) divided by + the number of message impressions (message_impressions). + Rate at which a user initiates a message chat from an ad + impression with a messaging option and message tracking + enabled. Note that this rate can be more than 1.0 for a + given message impression. + + This field is a member of `oneof`_ ``_message_chat_rate``. + mobile_friendly_clicks_percentage (float): + The percentage of mobile clicks that go to a + mobile-friendly page. + + This field is a member of `oneof`_ ``_mobile_friendly_clicks_percentage``. + optimization_score_uplift (float): + Total optimization score uplift of all + recommendations. + + This field is a member of `oneof`_ ``_optimization_score_uplift``. + optimization_score_url (str): + URL for the optimization score page in the Google Ads web + interface. This metric can be selected from ``customer`` or + ``campaign``, and can be segmented by + ``segments.recommendation_type``. For example, + ``SELECT metrics.optimization_score_url, segments.recommendation_type FROM customer`` + will return a URL for each unique (customer, + recommendation_type) combination. + + This field is a member of `oneof`_ ``_optimization_score_url``. + organic_clicks (int): + The number of times someone clicked your + site's listing in the unpaid results for a + particular query. See the help page at + https://support.google.com/google-ads/answer/3097241 + for details. + + This field is a member of `oneof`_ ``_organic_clicks``. + organic_clicks_per_query (float): + The number of times someone clicked your site's listing in + the unpaid results (organic_clicks) divided by the total + number of searches that returned pages from your site + (organic_queries). See the help page at + https://support.google.com/google-ads/answer/3097241 for + details. + + This field is a member of `oneof`_ ``_organic_clicks_per_query``. + organic_impressions (int): + The number of listings for your site in the + unpaid search results. See the help page at + https://support.google.com/google-ads/answer/3097241 + for details. + + This field is a member of `oneof`_ ``_organic_impressions``. + organic_impressions_per_query (float): + The number of times a page from your site was listed in the + unpaid search results (organic_impressions) divided by the + number of searches returning your site's listing in the + unpaid results (organic_queries). See the help page at + https://support.google.com/google-ads/answer/3097241 for + details. + + This field is a member of `oneof`_ ``_organic_impressions_per_query``. + organic_queries (int): + The total number of searches that returned + your site's listing in the unpaid results. See + the help page at + https://support.google.com/google-ads/answer/3097241 + for details. + + This field is a member of `oneof`_ ``_organic_queries``. + percent_new_visitors (float): + Percentage of first-time sessions (from + people who had never visited your site before). + Imported from Google Analytics. + + This field is a member of `oneof`_ ``_percent_new_visitors``. + phone_calls (int): + Number of offline phone calls. + + This field is a member of `oneof`_ ``_phone_calls``. + phone_impressions (int): + Number of offline phone impressions. + + This field is a member of `oneof`_ ``_phone_impressions``. + phone_through_rate (float): + Number of phone calls received (phone_calls) divided by the + number of times your phone number is shown + (phone_impressions). + + This field is a member of `oneof`_ ``_phone_through_rate``. + relative_ctr (float): + Your clickthrough rate (Ctr) divided by the + average clickthrough rate of all advertisers on + the websites that show your ads. Measures how + your ads perform on Display Network sites + compared to other ads on the same sites. + + This field is a member of `oneof`_ ``_relative_ctr``. + search_absolute_top_impression_share (float): + The percentage of the customer's Shopping or + Search ad impressions that are shown in the most + prominent Shopping position. See + https://support.google.com/google-ads/answer/7501826 + for details. Any value below 0.1 is reported as + 0.0999. + + This field is a member of `oneof`_ ``_search_absolute_top_impression_share``. + search_budget_lost_absolute_top_impression_share (float): + The number estimating how often your ad + wasn't the very first ad among the top ads in + the search results due to a low budget. Note: + Search budget lost absolute top impression share + is reported in the range of 0 to 0.9. Any value + above 0.9 is reported as 0.9001. + + This field is a member of `oneof`_ ``_search_budget_lost_absolute_top_impression_share``. + search_budget_lost_impression_share (float): + The estimated percent of times that your ad + was eligible to show on the Search Network but + didn't because your budget was too low. Note: + Search budget lost impression share is reported + in the range of 0 to 0.9. Any value above 0.9 is + reported as 0.9001. + + This field is a member of `oneof`_ ``_search_budget_lost_impression_share``. + search_budget_lost_top_impression_share (float): + The number estimating how often your ad + didn't show adjacent to the top organic search + results due to a low budget. Note: Search budget + lost top impression share is reported in the + range of 0 to 0.9. Any value above 0.9 is + reported as 0.9001. + + This field is a member of `oneof`_ ``_search_budget_lost_top_impression_share``. + search_click_share (float): + The number of clicks you've received on the + Search Network divided by the estimated number + of clicks you were eligible to receive. Note: + Search click share is reported in the range of + 0.1 to 1. Any value below 0.1 is reported as + 0.0999. + + This field is a member of `oneof`_ ``_search_click_share``. + search_exact_match_impression_share (float): + The impressions you've received divided by + the estimated number of impressions you were + eligible to receive on the Search Network for + search terms that matched your keywords exactly + (or were close variants of your keyword), + regardless of your keyword match types. Note: + Search exact match impression share is reported + in the range of 0.1 to 1. Any value below 0.1 is + reported as 0.0999. + + This field is a member of `oneof`_ ``_search_exact_match_impression_share``. + search_impression_share (float): + The impressions you've received on the Search + Network divided by the estimated number of + impressions you were eligible to receive. Note: + Search impression share is reported in the range + of 0.1 to 1. Any value below 0.1 is reported as + 0.0999. + + This field is a member of `oneof`_ ``_search_impression_share``. + search_rank_lost_absolute_top_impression_share (float): + The number estimating how often your ad + wasn't the very first ad among the top ads in + the search results due to poor Ad Rank. Note: + Search rank lost absolute top impression share + is reported in the range of 0 to 0.9. Any value + above 0.9 is reported as 0.9001. + + This field is a member of `oneof`_ ``_search_rank_lost_absolute_top_impression_share``. + search_rank_lost_impression_share (float): + The estimated percentage of impressions on + the Search Network that your ads didn't receive + due to poor Ad Rank. Note: Search rank lost + impression share is reported in the range of 0 + to 0.9. Any value above 0.9 is reported as + 0.9001. + + This field is a member of `oneof`_ ``_search_rank_lost_impression_share``. + search_rank_lost_top_impression_share (float): + The number estimating how often your ad + didn't show adjacent to the top organic search + results due to poor Ad Rank. Note: Search rank + lost top impression share is reported in the + range of 0 to 0.9. Any value above 0.9 is + reported as 0.9001. + + This field is a member of `oneof`_ ``_search_rank_lost_top_impression_share``. + search_top_impression_share (float): + The impressions you've received among the top + ads compared to the estimated number of + impressions you were eligible to receive among + the top ads. Note: Search top impression share + is reported in the range of 0.1 to 1. Any value + below 0.1 is reported as 0.0999. + + Top ads are generally above the top organic + results, although they may show below the top + organic results on certain queries. + + This field is a member of `oneof`_ ``_search_top_impression_share``. + search_volume (google.ads.googleads.v24.common.types.SearchVolumeRange): + Search volume range for a search term insight + category. + + This field is a member of `oneof`_ ``_search_volume``. + speed_score (int): + A measure of how quickly your page loads + after clicks on your mobile ads. The score is a + range from 1 to 10, 10 being the fastest. + + This field is a member of `oneof`_ ``_speed_score``. + average_target_cpa_micros (int): + The average Target CPA, or unset if not + available (for example, for campaigns that had + traffic from portfolio bidding strategies or + non-tCPA). + + This field is a member of `oneof`_ ``_average_target_cpa_micros``. + average_target_roas (float): + The average Target ROAS, or unset if not + available (for example, for campaigns that had + traffic from portfolio bidding strategies or + non-tROAS). + + This field is a member of `oneof`_ ``_average_target_roas``. + top_impression_percentage (float): + The percent of your ad impressions that are + shown adjacent to the top organic search + results. + + This field is a member of `oneof`_ ``_top_impression_percentage``. + valid_accelerated_mobile_pages_clicks_percentage (float): + The percentage of ad clicks to Accelerated + Mobile Pages (AMP) landing pages that reach a + valid AMP page. + + This field is a member of `oneof`_ ``_valid_accelerated_mobile_pages_clicks_percentage``. + value_per_all_conversions (float): + The value of all conversions divided by the + number of all conversions. + + This field is a member of `oneof`_ ``_value_per_all_conversions``. + value_per_all_conversions_by_conversion_date (float): + The value of all conversions divided by the number of all + conversions. When this column is selected with date, the + values in date column means the conversion date. Details for + the by_conversion_date columns are available at + https://support.google.com/google-ads/answer/9549009. + + This field is a member of `oneof`_ ``_value_per_all_conversions_by_conversion_date``. + value_per_conversion (float): + The value of conversions divided by the number of + conversions. This only includes conversion actions which + include_in_conversions_metric attribute is set to true. If + you use conversion-based bidding, your bid strategies will + optimize for these conversions. + + This field is a member of `oneof`_ ``_value_per_conversion``. + value_per_conversions_by_conversion_date (float): + The value of conversions divided by the number of + conversions. This only includes conversion actions which + include_in_conversions_metric attribute is set to true. If + you use conversion-based bidding, your bid strategies will + optimize for these conversions. When this column is selected + with date, the values in date column means the conversion + date. Details for the by_conversion_date columns are + available at + https://support.google.com/google-ads/answer/9549009. + + This field is a member of `oneof`_ ``_value_per_conversions_by_conversion_date``. + value_per_current_model_attributed_conversion (float): + The value of current model attributed conversions divided by + the number of the conversions. This only includes conversion + actions which include_in_conversions_metric attribute is set + to true. If you use conversion-based bidding, your bid + strategies will optimize for these conversions. + + This field is a member of `oneof`_ ``_value_per_current_model_attributed_conversion``. + video_quartile_p100_rate (float): + Percentage of impressions where the viewer + watched all of your video. + + This field is a member of `oneof`_ ``_video_quartile_p100_rate``. + video_quartile_p25_rate (float): + Percentage of impressions where the viewer + watched 25% of your video. + + This field is a member of `oneof`_ ``_video_quartile_p25_rate``. + video_quartile_p50_rate (float): + Percentage of impressions where the viewer + watched 50% of your video. + + This field is a member of `oneof`_ ``_video_quartile_p50_rate``. + video_quartile_p75_rate (float): + Percentage of impressions where the viewer + watched 75% of your video. + + This field is a member of `oneof`_ ``_video_quartile_p75_rate``. + video_trueview_view_rate (float): + The number of TrueView views your video ad + receives divided by its number of impressions, + including thumbnail impressions for TrueView + in-display ads. + + This field is a member of `oneof`_ ``_video_trueview_view_rate``. + video_trueview_views (int): + The number of TrueView views your video ads + received. + + This field is a member of `oneof`_ ``_video_trueview_views``. + view_through_conversions (int): + The total number of view-through conversions. + These happen when a customer sees an image or + rich media ad, then later completes a conversion + on your site without interacting with (for + example, clicking on) another ad. + + This field is a member of `oneof`_ ``_view_through_conversions``. + sk_ad_network_installs (int): + The number of iOS Store Kit Ad Network + conversions. + sk_ad_network_total_conversions (int): + The total number of iOS Store Kit Ad Network + conversions. + publisher_purchased_clicks (int): + Clicks from properties not owned by the + publisher for which the traffic the publisher + has paid for or acquired through incentivized + activity + publisher_organic_clicks (int): + Clicks from properties for which the traffic + the publisher has not paid for or acquired + through incentivized activity + publisher_unknown_clicks (int): + Clicks from traffic which is not identified + as "Publisher Purchased" or "Publisher Organic". + all_conversions_from_location_asset_click_to_call (float): + Number of call button clicks on any location + surface after a chargeable ad event (click or + impression). This measure is coming from Asset + based location. + + This field is a member of `oneof`_ ``_all_conversions_from_location_asset_click_to_call``. + all_conversions_from_location_asset_directions (float): + Number of driving directions clicks on any + location surface after a chargeable ad event + (click or impression). This measure is coming + from Asset based location. + + This field is a member of `oneof`_ ``_all_conversions_from_location_asset_directions``. + all_conversions_from_location_asset_menu (float): + Number of menu link clicks on any location + surface after a chargeable ad event (click or + impression). This measure is coming from Asset + based location. + + This field is a member of `oneof`_ ``_all_conversions_from_location_asset_menu``. + all_conversions_from_location_asset_order (float): + Number of order clicks on any location + surface after a chargeable ad event (click or + impression). This measure is coming from Asset + based location. + + This field is a member of `oneof`_ ``_all_conversions_from_location_asset_order``. + all_conversions_from_location_asset_other_engagement (float): + Number of other types of local action clicks + on any location surface after a chargeable ad + event (click or impression). This measure is + coming from Asset based location. + + This field is a member of `oneof`_ ``_all_conversions_from_location_asset_other_engagement``. + all_conversions_from_location_asset_store_visits (float): + Estimated number of visits to the business + after a chargeable ad event (click or + impression). This measure is coming from Asset + based location. + + This field is a member of `oneof`_ ``_all_conversions_from_location_asset_store_visits``. + all_conversions_from_location_asset_website (float): + Number of website URL clicks on any location + surface after a chargeable ad event (click or + impression). This measure is coming from Asset + based location. + + This field is a member of `oneof`_ ``_all_conversions_from_location_asset_website``. + eligible_impressions_from_location_asset_store_reach (int): + Number of impressions in which the business + location was shown or the location was used for + targeting. This measure is coming from Asset + based location. + + This field is a member of `oneof`_ ``_eligible_impressions_from_location_asset_store_reach``. + view_through_conversions_from_location_asset_click_to_call (float): + Number of call button clicks on any location + surface after an impression. This measure is + coming from Asset based location. + + This field is a member of `oneof`_ ``_view_through_conversions_from_location_asset_click_to_call``. + view_through_conversions_from_location_asset_directions (float): + Number of driving directions clicks on any + location surface after an impression. This + measure is coming from Asset based location. + + This field is a member of `oneof`_ ``_view_through_conversions_from_location_asset_directions``. + view_through_conversions_from_location_asset_menu (float): + Number of menu link clicks on any location + surface after an impression. This measure is + coming from Asset based location. + + This field is a member of `oneof`_ ``_view_through_conversions_from_location_asset_menu``. + view_through_conversions_from_location_asset_order (float): + Number of order clicks on any location + surface after an impression. This measure is + coming from Asset based location. + + This field is a member of `oneof`_ ``_view_through_conversions_from_location_asset_order``. + view_through_conversions_from_location_asset_other_engagement (float): + Number of other types of local action clicks + on any location surface after an impression. + This measure is coming from Asset based + location. + + This field is a member of `oneof`_ ``_view_through_conversions_from_location_asset_other_engagement``. + view_through_conversions_from_location_asset_store_visits (float): + Estimated number of visits to the business + after an impression. This measure is coming from + Asset based location. + + This field is a member of `oneof`_ ``_view_through_conversions_from_location_asset_store_visits``. + view_through_conversions_from_location_asset_website (float): + Number of website URL clicks on any location + surface after an impression. This measure is + coming from Asset based location. + + This field is a member of `oneof`_ ``_view_through_conversions_from_location_asset_website``. + orders (float): + Orders is the total number of purchase + conversions you received attributed to your ads. + How it works: You report conversions with cart + data for completed purchases on your website. If + a conversion is attributed to previous + interactions with your ads (clicks for text or + Shopping ads, views for video ads etc.) it's + counted as an order. Example: Someone clicked on + a Shopping ad for a hat then bought the same hat + and a shirt in an order on your website. Even + though they bought 2 products, this would count + as 1 order. + This metric is only available if you report + conversions with cart data. + + This field is a member of `oneof`_ ``_orders``. + average_order_value_micros (int): + Average order value is the average revenue + you made per order attributed to your ads. + How it works: You report conversions with cart + data for completed purchases on your website. + Average order value is the total revenue from + your orders divided by the total number of + orders. + Example: You received 3 orders which made $10, + $15 and $20 worth of revenue. The average order + value is $15 = ($10 + $15 + $20)/3. This metric + is only available if you report conversions with + cart data. + + This field is a member of `oneof`_ ``_average_order_value_micros``. + average_cart_size (float): + Average cart size is the average number of + products in each order attributed to your ads. + How it works: You report conversions with cart + data for completed purchases on your website. + Average cart size is the total number of + products sold divided by the total number of + orders you received. Example: You received 2 + orders, the first included 3 products and the + second included 2. The average cart size is 2.5 + products = (3+2)/2. This metric is only + available if you report conversions with cart + data. + + This field is a member of `oneof`_ ``_average_cart_size``. + cost_of_goods_sold_micros (int): + Cost of goods sold (COGS) is the total cost + of the products you sold in orders attributed to + your ads. How it works: You can add a cost of + goods sold value to every product in Merchant + Center. If you report conversions with cart + data, the products you sold are matched with + their cost of goods sold value and this can be + used to calculate the gross profit you made on + each order. Example: Someone clicked on a + Shopping ad for a hat then bought the same hat + and a shirt. The hat has a cost of goods sold + value of $3, the shirt has a cost of goods sold + value of $5. The cost of goods sold for this + order is $8 = $3 + $5. + This metric is only available if you report + conversions with cart data. + + This field is a member of `oneof`_ ``_cost_of_goods_sold_micros``. + gross_profit_micros (int): + Gross profit is the profit you made from + orders attributed to your ads minus the cost of + goods sold (COGS). How it works: Gross profit is + the revenue you made from sales attributed to + your ads minus cost of goods sold. Gross profit + calculations only include products that have a + cost of goods sold value in Merchant Center. + Example: Someone clicked on a Shopping ad for a + hat then bought the same hat and a shirt in an + order from your website. The hat is priced $10 + and the shirt is priced $20. The hat has a cost + of goods sold value of $3, but the shirt has no + cost of goods sold value. Gross profit for this + order will only take into account the hat, so + it's $7 = $10 - $3. This metric is only + available if you report conversions with cart + data. + + This field is a member of `oneof`_ ``_gross_profit_micros``. + gross_profit_margin (float): + Gross profit margin is the percentage gross + profit you made from orders attributed to your + ads, after taking out the cost of goods sold + (COGS). How it works: You report conversions + with cart data for completed purchases on your + website. Gross profit margin is the gross profit + you made divided by your total revenue and + multiplied by 100%. Gross profit margin + calculations only include products that have a + cost of goods sold value in Merchant Center. + Example: Someone bought a hat and a shirt in an + order on your website. The hat is priced $10 and + has a cost of goods sold value of $3. The shirt + is priced $20 but has no cost of goods sold + value. Gross profit margin for this order will + only take into account the hat because it has a + cost of goods sold value, so it's 70% = ($10 - + $3)/$10 x 100%. This metric is only available if + you report conversions with cart data. + + This field is a member of `oneof`_ ``_gross_profit_margin``. + revenue_micros (int): + Revenue is the total amount you made from + orders attributed to your ads. How it works: You + report conversions with cart data for completed + purchases on your website. Revenue is the total + value of all the orders you received attributed + to your ads, minus any discount. + Example: Someone clicked on a Shopping ad for a + hat then bought the same hat and a shirt in an + order from your website. The hat is priced $10 + and the shirt is priced $20. The entire order + has a $5 discount. The revenue from this order + is $25 = ($10 + $20) - $5. + This metric is only available if you report + conversions with cart data. + + This field is a member of `oneof`_ ``_revenue_micros``. + units_sold (float): + Units sold is the total number of products + sold from orders attributed to your ads. + How it works: You report conversions with cart + data for completed purchases on your website. + Units sold is the total number of products sold + from all orders attributed to your ads. + Example: Someone clicked on a Shopping ad for a + hat then bought the same hat, a shirt and a + jacket. The units sold in this order is 3. This + metric is only available if you report + conversions with cart data. + + This field is a member of `oneof`_ ``_units_sold``. + cross_sell_cost_of_goods_sold_micros (int): + Cross-sell cost of goods sold (COGS) is the + total cost of products sold as a result of + advertising a different product. How it works: + You report conversions with cart data for + completed purchases on your website. If the ad + that was interacted with before the purchase has + an associated product (see Shopping Ads) then + this product is considered the advertised + product. Any product included in the order the + customer places is a sold product. If these + products don't match then this is considered + cross-sell. Cross-sell cost of goods sold is the + total cost of the products sold that weren't + advertised. + Example: Someone clicked on a Shopping ad for a + hat then bought the same hat and a shirt. The + hat has a cost of goods sold value of $3, the + shirt has a cost of goods sold value of $5. The + cross-sell cost of goods sold for this order is + $5. + This metric is only available if you report + conversions with cart data. + + This field is a member of `oneof`_ ``_cross_sell_cost_of_goods_sold_micros``. + cross_sell_gross_profit_micros (int): + Cross-sell gross profit is the profit you + made from products sold as a result of + advertising a different product, minus cost of + goods sold (COGS). How it works: You report + conversions with cart data for completed + purchases on your website. If the ad that was + interacted with before the purchase has an + associated product (see Shopping Ads) then this + product is considered the advertised product. + Any product included in the purchase is a sold + product. If these products don't match then this + is considered cross-sell. Cross-sell gross + profit is the revenue you made from cross-sell + attributed to your ads minus the cost of the + goods sold. Example: Someone clicked on a + Shopping ad for a hat then bought the same hat + and a shirt. The shirt is priced $20 and has a + cost of goods sold value of $5. The cross-sell + gross profit of this order is $15 = $20 - $5. + This metric is only available if you report + conversions with cart data. + + This field is a member of `oneof`_ ``_cross_sell_gross_profit_micros``. + cross_sell_revenue_micros (int): + Cross-sell revenue is the total amount you + made from products sold as a result of + advertising a different product. How it works: + You report conversions with cart data for + completed purchases on your website. If the ad + that was interacted with before the purchase has + an associated product (see Shopping Ads) then + this product is considered the advertised + product. Any product included in the order the + customer places is a sold product. If these + products don't match then this is considered + cross-sell. Cross-sell revenue is the total + value you made from cross-sell attributed to + your ads. + Example: Someone clicked on a Shopping ad for a + hat then bought the same hat and a shirt. The + hat is priced $10 and the shirt is priced $20. + The cross-sell revenue of this order is $20. + This metric is only available if you report + conversions with cart data. + + This field is a member of `oneof`_ ``_cross_sell_revenue_micros``. + cross_sell_units_sold (float): + Cross-sell units sold is the total number of + products sold as a result of advertising a + different product. How it works: You report + conversions with cart data for completed + purchases on your website. If the ad that was + interacted with before the purchase has an + associated product (see Shopping Ads) then this + product is considered the advertised product. + Any product included in the order the customer + places is a sold product. If these products + don't match then this is considered cross-sell. + Cross-sell units sold is the total number of + cross-sold products from all orders attributed + to your ads. Example: Someone clicked on a + Shopping ad for a hat then bought the same hat, + a shirt and a jacket. The cross-sell units sold + in this order is 2. This metric is only + available if you report conversions with cart + data. + + This field is a member of `oneof`_ ``_cross_sell_units_sold``. + lead_cost_of_goods_sold_micros (int): + Lead cost of goods sold (COGS) is the total + cost of products sold as a result of advertising + the same product. How it works: You report + conversions with cart data for completed + purchases on your website. If the ad that was + interacted with has an associated product (see + Shopping Ads) then this product is considered + the advertised product. Any product included in + the order the customer places is a sold product. + If the advertised and sold products match, then + the cost of these goods is counted under lead + cost of goods sold. Example: Someone clicked on + a Shopping ad for a hat then bought the same hat + and a shirt. The hat has a cost of goods sold + value of $3, the shirt has a cost of goods sold + value of $5. The lead cost of goods sold for + this order is $3. + This metric is only available if you report + conversions with cart data. + + This field is a member of `oneof`_ ``_lead_cost_of_goods_sold_micros``. + lead_gross_profit_micros (int): + Lead gross profit is the profit you made from + products sold as a result of advertising the + same product, minus cost of goods sold (COGS). + How it works: You report conversions with cart + data for completed purchases on your website. If + the ad that was interacted with before the + purchase has an associated product (see Shopping + Ads) then this product is considered the + advertised product. Any product included in the + order the customer places is a sold product. If + the advertised and sold products match, then the + revenue you made from these sales minus the cost + of goods sold is your lead gross profit. + Example: Someone clicked on a Shopping ad for a + hat then bought the same hat and a shirt. The + hat is priced $10 and has a cost of goods sold + value of $3. The lead gross profit of this order + is $7 = $10 - $3. This metric is only available + if you report conversions with cart data. + + This field is a member of `oneof`_ ``_lead_gross_profit_micros``. + lead_revenue_micros (int): + Lead revenue is the total amount you made + from products sold as a result of advertising + the same product. How it works: You report + conversions with cart data for completed + purchases on your website. If the ad that was + interacted with before the purchase has an + associated product (see Shopping Ads) then this + product is considered the advertised product. + Any product included in the order the customer + places is a sold product. If the advertised and + sold products match, then the total value you + made from the sales of these products is shown + under lead revenue. + Example: Someone clicked on a Shopping ad for a + hat then bought the same hat and a shirt. The + hat is priced $10 and the shirt is priced $20. + The lead revenue of this order is $10. + This metric is only available if you report + conversions with cart data. + + This field is a member of `oneof`_ ``_lead_revenue_micros``. + lead_units_sold (float): + Lead units sold is the total number of + products sold as a result of advertising the + same product. How it works: You report + conversions with cart data for completed + purchases on your website. If the ad that was + interacted with before the purchase has an + associated product (see Shopping Ads) then this + product is considered the advertised product. + Any product included in the order the customer + places is a sold product. If the advertised and + sold products match, then the total number of + these products sold is shown under lead units + sold. Example: Someone clicked on a Shopping ad + for a hat then bought the same hat, a shirt and + a jacket. The lead units sold in this order is + 1. This metric is only available if you report + conversions with cart data. + + This field is a member of `oneof`_ ``_lead_units_sold``. + unique_users (int): + The number of unique users who saw your ad + during the requested time period. This metric + cannot be aggregated, and can only be requested + for date ranges of 92 days or less. This metric + is available for following campaign types - + Display, Video, Discovery and App. + + This field is a member of `oneof`_ ``_unique_users``. + average_impression_frequency_per_user (float): + The average number of times a unique user saw + your ad during the requested time period. This + metric cannot be aggregated, and can only be + requested for date ranges of 92 days or less. + This metric is available for following campaign + types - Display, Video, Discovery and App. + + This field is a member of `oneof`_ ``_average_impression_frequency_per_user``. + linked_entities_count (int): + Number of linked resources in which the asset + is used. This metric can only be selected with + ChannelAggregateAssetView and + CampaignAggregateAssetView. + + This field is a member of `oneof`_ ``_linked_entities_count``. + linked_sample_entities (MutableSequence[str]): + A list of up to 20 sample linked resources in + which the asset is used. This metric can only be + selected with ChannelAggregateAssetView and + CampaignAggregateAssetView. + asset_pinned_total_count (int): + Number of total usages in which the asset is + pinned. This metric can only be selected with + ChannelAggregateAssetView and + CampaignAggregateAssetView. + This metric is only supported in Search channel. + + This field is a member of `oneof`_ ``_asset_pinned_total_count``. + asset_pinned_as_headline_position_one_count (int): + Number of entities in which the asset is + pinned to headline 1. This metric can only be + selected with ChannelAggregateAssetView and + CampaignAggregateAssetView. + This metric is only supported in Search channel. + + This field is a member of `oneof`_ ``_asset_pinned_as_headline_position_one_count``. + asset_pinned_as_headline_position_two_count (int): + Number of entities in which the asset is + pinned to headline 2. This metric can only be + selected with ChannelAggregateAssetView and + CampaignAggregateAssetView. + This metric is only supported in Search channel. + + This field is a member of `oneof`_ ``_asset_pinned_as_headline_position_two_count``. + asset_pinned_as_headline_position_three_count (int): + Number of entities in which the asset is + pinned to headline 3. This metric can only be + selected with ChannelAggregateAssetView and + CampaignAggregateAssetView. + This metric is only supported in Search channel. + + This field is a member of `oneof`_ ``_asset_pinned_as_headline_position_three_count``. + asset_pinned_as_description_position_one_count (int): + Number of entities in which the asset is + pinned to description 1. This metric can only be + selected with ChannelAggregateAssetView and + CampaignAggregateAssetView. + This metric is only supported in Search channel. + + This field is a member of `oneof`_ ``_asset_pinned_as_description_position_one_count``. + asset_pinned_as_description_position_two_count (int): + Number of entities in which the asset is + pinned to description 2. This metric can only be + selected with ChannelAggregateAssetView and + CampaignAggregateAssetView. + This metric is only supported in Search channel. + + This field is a member of `oneof`_ ``_asset_pinned_as_description_position_two_count``. + store_visits_last_click_model_attributed_conversions (float): + The amount of business visits attributed by + the last click model. + + This field is a member of `oneof`_ ``_store_visits_last_click_model_attributed_conversions``. + results_conversions_purchase (float): + The purchase conversion stats for the unified + goals results. + + This field is a member of `oneof`_ ``_results_conversions_purchase``. + video_trueview_view_rate_in_feed (float): + The number of TrueView views divided by + number of impressions that can potentially lead + to TrueView views for in-feed formats. + + This field is a member of `oneof`_ ``_video_trueview_view_rate_in_feed``. + video_trueview_view_rate_in_stream (float): + The number of TrueView views divided by + number of impressions that can potentially lead + to TrueView views for in-stream formats. + + This field is a member of `oneof`_ ``_video_trueview_view_rate_in_stream``. + video_trueview_view_rate_shorts (float): + The number of TrueView views divided by + number of impressions that can potentially lead + to TrueView views for Shorts ads. + + This field is a member of `oneof`_ ``_video_trueview_view_rate_shorts``. + coviewed_impressions (int): + All co-viewed impressions represent the total number of + people who saw your ad. This includes people who are signed + into their Google Account, as well as other people who are + watching the same ad on a connected TV. This metric is only + available for the Campaign resource with adjusted_age_range + and adjusted_gender segments. These segmentations are + mandatory to get the all coviewed impressions. + + This field is a member of `oneof`_ ``_coviewed_impressions``. + primary_impressions (int): + Primary impression is counted each time your ad is served. + This metric is only available for the Campaign resource with + adjusted_age_range and adjusted_gender segments. These + segmentations are mandatory to get the primary impressions. + + This field is a member of `oneof`_ ``_primary_impressions``. + platform_comparable_conversions_from_interactions_rate (float): + Platform comparable conversions from interactions divided by + the number of ad interactions (such as clicks for text ads + or views for video ads). This only includes conversion + actions for which include_in_conversions_metric attribute is + set to true. If you use conversion-based bidding, your bid + strategies will optimize for these conversions. + + This field is a member of `oneof`_ ``_platform_comparable_conversions_from_interactions_rate``. + platform_comparable_conversions (float): + The number of platform comparable conversions. This only + includes conversion actions for which + include_in_conversions_metric attribute is set to true. If + you use conversion-based bidding, your bid strategies will + optimize for these conversions. + + This field is a member of `oneof`_ ``_platform_comparable_conversions``. + platform_comparable_conversions_value (float): + The value of platform comparable conversions. This only + includes conversion actions which + include_in_conversions_metric attribute is set to true. If + you use conversion-based bidding, your bid strategies will + optimize for these conversions. + + This field is a member of `oneof`_ ``_platform_comparable_conversions_value``. + platform_comparable_conversions_value_per_cost (float): + The value of conversions divided by the cost of ad + interactions. This only includes conversion actions for + which include_in_conversions_metric attribute is set to + true. If you use conversion-based bidding, your bid + strategies will optimize for these conversions. + + This field is a member of `oneof`_ ``_platform_comparable_conversions_value_per_cost``. + platform_comparable_conversions_by_conversion_date (float): + The number of platform comparable conversions. When this + metric is segmented by date, the values in the date segment + represent the conversion date. This only includes conversion + actions for which include_in_conversions_metric attribute is + set to true. If you use conversion-based bidding, your bid + strategies will optimize for these conversions. + + This field is a member of `oneof`_ ``_platform_comparable_conversions_by_conversion_date``. + platform_comparable_conversions_value_by_conversion_date (float): + The value of platform comparable conversions. When this + metric is segmented by date, the values in the date segment + represent the conversion date. This only includes conversion + actions for which include_in_conversions_metric attribute is + set to true. If you use conversion-based bidding, your bid + strategies will optimize for these conversions. + + This field is a member of `oneof`_ ``_platform_comparable_conversions_value_by_conversion_date``. + platform_comparable_conversions_from_interactions_value_per_interaction (float): + The value of platform comparable conversions from + interactions divided by the number of ad interactions. This + only includes conversion actions for which + include_in_conversions_metric attribute is set to true. If + you use conversion-based bidding, your bid strategies will + optimize for these conversions. + + This field is a member of `oneof`_ ``_platform_comparable_conversions_from_interactions_value_per_interaction``. + cost_per_platform_comparable_conversion (float): + The cost of ad interactions divided by the number of + platform comparable conversions. This only includes + conversion actions for which include_in_conversions_metric + attribute is set to true. If you use conversion-based + bidding, your bid strategies will optimize for these + conversions. + + This field is a member of `oneof`_ ``_cost_per_platform_comparable_conversion``. + value_per_platform_comparable_conversion (float): + The value of platform comparable conversions divided by the + number of platform comparable conversions. This only + includes conversion actions for which + include_in_conversions_metric attribute is set to true. If + you use conversion-based bidding, your bid strategies will + optimize for these conversions. + + This field is a member of `oneof`_ ``_value_per_platform_comparable_conversion``. + value_per_platform_comparable_conversions_by_conversion_date (float): + The value of platform comparable conversions divided by the + number of platform comparable conversions. When this metric + is segmented by date, the values in the date segment + represent the conversion date. This only includes conversion + actions for which include_in_conversions_metric attribute is + set to true. If you use conversion-based bidding, your bid + strategies will optimize for these conversions. + + This field is a member of `oneof`_ ``_value_per_platform_comparable_conversions_by_conversion_date``. + cost_converted_currency_per_platform_comparable_conversion (float): + The cost of the platform comparable + conversion in the currency of the authorized + customer. + + This field is a member of `oneof`_ ``_cost_converted_currency_per_platform_comparable_conversion``. + unique_users_two_plus (int): + This metric counts the unique individuals who + were shown your video ad two or more times + within the selected date range. This metric + cannot be aggregated, and can only be requested + for date ranges of 31 days or less. + + This field is a member of `oneof`_ ``_unique_users_two_plus``. + unique_users_three_plus (int): + This metric counts the unique individuals who + were shown your video ad three or more times + within the selected date range. This metric + cannot be aggregated, and can only be requested + for date ranges of 31 days or less. + + This field is a member of `oneof`_ ``_unique_users_three_plus``. + unique_users_four_plus (int): + This metric counts the unique individuals who + were shown your video ad four or more times + within the selected date range. This metric + cannot be aggregated, and can only be requested + for date ranges of 31 days or less. + + This field is a member of `oneof`_ ``_unique_users_four_plus``. + unique_users_five_plus (int): + This metric counts the unique individuals who + were shown your video ad five or more times + within the selected date range. This metric + cannot be aggregated, and can only be requested + for date ranges of 31 days or less. + + This field is a member of `oneof`_ ``_unique_users_five_plus``. + unique_users_ten_plus (int): + This metric counts the unique individuals who + were shown your video ad ten or more times + within the selected date range. This metric + cannot be aggregated, and can only be requested + for date ranges of 31 days or less. + + This field is a member of `oneof`_ ``_unique_users_ten_plus``. + value_adjustment (float): + The conversion value rule adjustment from + biddable conversions in all conversion + categories. + + This field is a member of `oneof`_ ``_value_adjustment``. + all_value_adjustment (float): + The conversion value rule adjustment from all + conversions in all conversion categories. + + This field is a member of `oneof`_ ``_all_value_adjustment``. + clicks_unique_query_clusters (int): + Unique query intent cluster count for clicks. + + This field is a member of `oneof`_ ``_clicks_unique_query_clusters``. + conversions_unique_query_clusters (int): + Unique query intent cluster count for + conversions. + + This field is a member of `oneof`_ ``_conversions_unique_query_clusters``. + impressions_unique_query_clusters (int): + Unique query intent cluster count for + impressions. + + This field is a member of `oneof`_ ``_impressions_unique_query_clusters``. + video_watch_time_duration_millis (int): + Total watch time duration in milliseconds for + video impressions that started playing. For a + small percentage of impressions, we may not be + able to measure the watch time accurately. In + such cases, we adjust the total time to account + for any unmeasured time by applying the average + watch time of impressions that were measured. + + This field is a member of `oneof`_ ``_video_watch_time_duration_millis``. + average_video_watch_time_duration_millis (int): + Average video watch time duration in + milliseconds for video impressions that started + playing. + + This field is a member of `oneof`_ ``_average_video_watch_time_duration_millis``. + svr (int): + This feature is available to allowlisted + accounts only. + + This field is a member of `oneof`_ ``_svr``. + active_view_audibility_measurable_impressions (int): + The number of impressions for which Active + View could measure if the ad was audible. + + This field is a member of `oneof`_ ``_active_view_audibility_measurable_impressions``. + active_view_audibility_measurable_impressions_rate (float): + The number of impressions for which Active + View could measure if the ad was audible, + divided by the total number of impressions with + Active View audio enabled. + + This field is a member of `oneof`_ ``_active_view_audibility_measurable_impressions_rate``. + active_view_audibility_invalid_measurable_impressions_rate (float): + The number of impressions for which Active + View could measure audibility, but that were + filtered out by traffic quality filters, divided + by the total number of impressions measurable + for audibility. + + This field is a member of `oneof`_ ``_active_view_audibility_invalid_measurable_impressions_rate``. + active_view_audibility_invalid_givt_measurable_impressions_rate (float): + The number of impressions for which Active + View could measure audibility, but that were + filtered out by traffic quality filters, divided + by the total number of impressions measurable + for audibility. Only includes GIVT (general + invalid traffic) impressions. + + This field is a member of `oneof`_ ``_active_view_audibility_invalid_givt_measurable_impressions_rate``. + active_view_audible_impressions (int): + The number of impressions that were audible + (volume > 0%) at any point during the ad + playback. + + This field is a member of `oneof`_ ``_active_view_audible_impressions``. + active_view_audible_impressions_rate (float): + The number of impressions that were audible + (volume > 0%) at any point during the ad + playback, divided by the total number of + impressions measurable for audibility. + + This field is a member of `oneof`_ ``_active_view_audible_impressions_rate``. + active_view_audible_two_seconds_impressions (int): + The number of impressions that were audible + for at least 2 seconds (cumulative). + + This field is a member of `oneof`_ ``_active_view_audible_two_seconds_impressions``. + active_view_audible_two_seconds_impressions_rate (float): + The number of impressions that were audible + for at least 2 seconds (cumulative), divided by + the total number of impressions measurable for + audibility. + + This field is a member of `oneof`_ ``_active_view_audible_two_seconds_impressions_rate``. + active_view_audible_thirty_seconds_impressions (int): + The number of impressions that were audible + for at least 30 seconds (cumulative). + + This field is a member of `oneof`_ ``_active_view_audible_thirty_seconds_impressions``. + active_view_audible_thirty_seconds_impressions_rate (float): + The number of impressions that were audible + for at least 30 seconds (cumulative), divided by + the total number of impressions measurable for + audibility. + + This field is a member of `oneof`_ ``_active_view_audible_thirty_seconds_impressions_rate``. + active_view_audible_quartile_p25_rate (float): + The number of impressions that were audible + at the first quartile of the ad playback, + divided by the total number of impressions + measurable for audibility. + + This field is a member of `oneof`_ ``_active_view_audible_quartile_p25_rate``. + active_view_audible_quartile_p50_rate (float): + The number of impressions that were audible + at the second quartile of the ad playback, + divided by the total number of impressions + measurable for audibility. + + This field is a member of `oneof`_ ``_active_view_audible_quartile_p50_rate``. + active_view_audible_quartile_p75_rate (float): + The number of impressions that were audible + at the third quartile of the ad playback, + divided by the total number of impressions + measurable for audibility. + + This field is a member of `oneof`_ ``_active_view_audible_quartile_p75_rate``. + active_view_audible_quartile_p100_rate (float): + The number of impressions that were audible + at the fourth quartile of the ad playback, + divided by the total number of impressions + measurable for audibility. + + This field is a member of `oneof`_ ``_active_view_audible_quartile_p100_rate``. + biddable_indirect_install_first_in_app_conversion_micros (int): + The number of biddable first in app + conversions where the app install was driven by + interaction with a web campaign. + + This field is a member of `oneof`_ ``_biddable_indirect_install_first_in_app_conversion_micros``. + all_average_cart_size (float): + All average cart size is the average number of products in + each order attributed to your ads. Includes the amount from + the average_cart_size metric, plus avg. cart size from all + your conversion actions, even if your campaigns are not + actively optimizing towards them. It's calculated using + product info from cart data to give more detail than + conversion value alone. + + This field is a member of `oneof`_ ``_all_average_cart_size``. + all_average_order_value_micros (int): + All average order value is the average revenue you made per + order attributed to your ads. Includes the amount from the + average_order_value metric, plus avg. order value from all + your conversion actions, even if your campaigns are not + actively optimizing towards them. It's calculated using + product info from cart data to give more detail than + conversion value alone. + + This field is a member of `oneof`_ ``_all_average_order_value_micros``. + all_cost_of_goods_sold_micros (int): + All cost of goods sold is the total cost of the products you + sold in orders attributed to your ads. Includes the amount + from the cost_of_goods_sold_micros metric, plus cost of + goods sold from all conversion actions, even if your + campaigns are not actively optimizing towards them. It's + calculated using product info from cart data to give more + detail than conversion value alone. + + This field is a member of `oneof`_ ``_all_cost_of_goods_sold_micros``. + all_cross_sell_cost_of_goods_sold_micros (int): + All cross-sell cost of goods sold is the total cost of + products sold as a result of advertising a different + product. Includes the amount from the + cross_sell_cost_of_goods_sold_micros metric, plus cross-sell + cost of goods sold from all your conversion actions, even if + your campaigns are not actively optimizing towards them. + It's calculated using product info from cart data to give + more detail than conversion value alone. + + This field is a member of `oneof`_ ``_all_cross_sell_cost_of_goods_sold_micros``. + all_cross_sell_gross_profit_micros (int): + All cross-sell gross profit is the profit you made from + products sold as a result of advertising a different + product, minus cost of goods sold (COGS). Includes the + amount from the cross_sell_gross_profit_micros metric, plus + cross-sell gross profit from all your conversion actions, + even if your campaigns are not actively optimizing towards + them. It's calculated using product info from cart data to + give more detail than conversion value alone. + + This field is a member of `oneof`_ ``_all_cross_sell_gross_profit_micros``. + all_cross_sell_revenue_micros (int): + All cross-sell revenue is the total amount you made from + products sold as a result of advertising a different + product. Includes the amount from the + cross_sell_revenue_micros metric, plus cross-sell revenue + from all your conversion actions, even if your campaigns are + not actively optimizing towards them. It's calculated using + product info from cart data to give more detail than + conversion value alone. + + This field is a member of `oneof`_ ``_all_cross_sell_revenue_micros``. + all_cross_sell_units_sold (float): + All cross-sell units sold is the total number of products + sold as a result of advertising a different product. + Includes the amount shown in the cross_sell_units_sold + metric, plus cross-sell units sold from all your conversion + actions, even if your campaigns are not actively optimizing + towards them. It's calculated using product info from cart + data to give more detail than conversion value alone. + + This field is a member of `oneof`_ ``_all_cross_sell_units_sold``. + all_gross_profit_margin (float): + All gross profit margin is the percentage gross profit you + made from orders attributed to your ads, after taking out + the cost of goods sold (COGS). This value is between 0.0 and + 1.0, where 1.0 means 100%. Includes the amount from the + gross_profit_margin metric, plus gross profit margin across + all conversion actions, even if your campaigns are not + actively optimizing towards them. It's calculated using + product info from cart data to give more detail than + conversion value alone. + + This field is a member of `oneof`_ ``_all_gross_profit_margin``. + all_gross_profit_micros (int): + All gross profit is the total profit made from orders + attributed to your ads minus the cost of goods sold (COGS). + Includes the amount from the gross_profit_micros metric, + plus gross profit from all your conversion actions, even if + your campaigns are not actively optimizing towards them. + It's calculated using product info from cart data to give + more detail than conversion value alone. + + This field is a member of `oneof`_ ``_all_gross_profit_micros``. + all_lead_cost_of_goods_sold_micros (int): + All lead cost of goods sold is the total cost of products + sold as a result of advertising the same product. Includes + the amount shown in the lead_cost_of_goods_sold_micros + metric, plus lead cost of goods sold from all your + conversion actions, even if your campaigns are not actively + optimizing towards them. It's calculated using product info + from cart data to give more detail than conversion value + alone. + + This field is a member of `oneof`_ ``_all_lead_cost_of_goods_sold_micros``. + all_lead_gross_profit_micros (int): + All lead gross profit is the profit you made from products + sold as a result of advertising the same product, minus cost + of goods sold (COGS). Includes the amount from the + lead_gross_profit_micros metric, plus lead gross profit from + all your conversion actions, even if your campaigns are not + actively optimizing towards them. It's calculated using + product info from cart data to give more detail than + conversion value alone. + + This field is a member of `oneof`_ ``_all_lead_gross_profit_micros``. + all_lead_revenue_micros (int): + All lead revenue is the total amount you made from products + sold as a result of advertising the same product. Includes + the amount shown in the lead_revenue_micros metric, plus + lead revenue from all your conversion actions, even if your + campaigns are not actively optimizing towards them. It's + calculated using product info from cart data to give more + detail than conversion value alone. + + This field is a member of `oneof`_ ``_all_lead_revenue_micros``. + all_lead_units_sold (float): + All lead units sold is the total number of products sold as + a result of advertising the same product. Includes the + amount shown in the lead_units_sold metric, plus lead units + sold from all your conversion actions, even if your + campaigns are not actively optimizing towards them. It's + calculated using product info from cart data to give more + detail than conversion value alone. + + This field is a member of `oneof`_ ``_all_lead_units_sold``. + all_orders (float): + All orders is total number of purchase + conversions attributed to your ads. Includes the + amount from the orders metric, plus orders from + all your conversion actions, even if your + campaigns are not actively optimizing towards + them. + It's calculated using product info from cart + data to give more detail than conversion value + alone. + + This field is a member of `oneof`_ ``_all_orders``. + all_revenue_micros (int): + All revenue is the total you made from orders attributed to + your ads. Includes the amount from the revenue_micros + metric, plus revenue from all your conversion actions, even + if your campaigns are not actively optimizing towards them. + It's calculated using product info from cart data to give + more detail than conversion value alone. + + This field is a member of `oneof`_ ``_all_revenue_micros``. + all_units_sold (float): + All units sold is the total number of products sold from + orders attributed to your ads. Includes the amount from the + units_sold metric, plus units sold from all your conversion + actions, even if your campaigns are not actively optimizing + towards them. It's calculated using product info from cart + data to give more detail than conversion value alone. + + This field is a member of `oneof`_ ``_all_units_sold``. + """ + + absolute_top_impression_percentage: float = proto.Field( + proto.DOUBLE, + number=183, + optional=True, + ) + active_view_cpm: float = proto.Field( + proto.DOUBLE, + number=184, + optional=True, + ) + active_view_ctr: float = proto.Field( + proto.DOUBLE, + number=185, + optional=True, + ) + active_view_impressions: int = proto.Field( + proto.INT64, + number=186, + optional=True, + ) + active_view_measurability: float = proto.Field( + proto.DOUBLE, + number=187, + optional=True, + ) + active_view_measurable_cost_micros: int = proto.Field( + proto.INT64, + number=188, + optional=True, + ) + active_view_measurable_impressions: int = proto.Field( + proto.INT64, + number=189, + optional=True, + ) + active_view_viewability: float = proto.Field( + proto.DOUBLE, + number=190, + optional=True, + ) + all_conversions_from_interactions_rate: float = proto.Field( + proto.DOUBLE, + number=191, + optional=True, + ) + all_conversions_value: float = proto.Field( + proto.DOUBLE, + number=192, + optional=True, + ) + all_conversions_value_by_conversion_date: float = proto.Field( + proto.DOUBLE, + number=240, + optional=True, + ) + all_new_customer_lifetime_value: float = proto.Field( + proto.DOUBLE, + number=294, + optional=True, + ) + all_conversions: float = proto.Field( + proto.DOUBLE, + number=193, + optional=True, + ) + all_conversions_by_conversion_date: float = proto.Field( + proto.DOUBLE, + number=241, + optional=True, + ) + all_conversions_value_per_cost: float = proto.Field( + proto.DOUBLE, + number=194, + optional=True, + ) + all_conversions_from_click_to_call: float = proto.Field( + proto.DOUBLE, + number=195, + optional=True, + ) + all_conversions_from_directions: float = proto.Field( + proto.DOUBLE, + number=196, + optional=True, + ) + all_conversions_from_interactions_value_per_interaction: float = ( + proto.Field( + proto.DOUBLE, + number=197, + optional=True, + ) + ) + all_conversions_from_menu: float = proto.Field( + proto.DOUBLE, + number=198, + optional=True, + ) + all_conversions_from_order: float = proto.Field( + proto.DOUBLE, + number=199, + optional=True, + ) + all_conversions_from_other_engagement: float = proto.Field( + proto.DOUBLE, + number=200, + optional=True, + ) + all_conversions_from_store_visit: float = proto.Field( + proto.DOUBLE, + number=201, + optional=True, + ) + all_conversions_from_store_website: float = proto.Field( + proto.DOUBLE, + number=202, + optional=True, + ) + auction_insight_search_absolute_top_impression_percentage: float = ( + proto.Field( + proto.DOUBLE, + number=258, + optional=True, + ) + ) + auction_insight_search_impression_share: float = proto.Field( + proto.DOUBLE, + number=259, + optional=True, + ) + auction_insight_search_outranking_share: float = proto.Field( + proto.DOUBLE, + number=260, + optional=True, + ) + auction_insight_search_overlap_rate: float = proto.Field( + proto.DOUBLE, + number=261, + optional=True, + ) + auction_insight_search_position_above_rate: float = proto.Field( + proto.DOUBLE, + number=262, + optional=True, + ) + auction_insight_search_top_impression_percentage: float = proto.Field( + proto.DOUBLE, + number=263, + optional=True, + ) + average_cost: float = proto.Field( + proto.DOUBLE, + number=203, + optional=True, + ) + average_cpc: float = proto.Field( + proto.DOUBLE, + number=204, + optional=True, + ) + average_cpe: float = proto.Field( + proto.DOUBLE, + number=205, + optional=True, + ) + average_cpm: float = proto.Field( + proto.DOUBLE, + number=206, + optional=True, + ) + trueview_average_cpv: float = proto.Field( + proto.DOUBLE, + number=405, + optional=True, + ) + average_page_views: float = proto.Field( + proto.DOUBLE, + number=208, + optional=True, + ) + average_time_on_site: float = proto.Field( + proto.DOUBLE, + number=209, + optional=True, + ) + benchmark_average_max_cpc: float = proto.Field( + proto.DOUBLE, + number=210, + optional=True, + ) + biddable_app_install_conversions: float = proto.Field( + proto.DOUBLE, + number=254, + optional=True, + ) + biddable_app_post_install_conversions: float = proto.Field( + proto.DOUBLE, + number=255, + optional=True, + ) + biddable_cohort_app_post_install_conversions: float = proto.Field( + proto.DOUBLE, + number=378, + optional=True, + ) + benchmark_ctr: float = proto.Field( + proto.DOUBLE, + number=211, + optional=True, + ) + bounce_rate: float = proto.Field( + proto.DOUBLE, + number=212, + optional=True, + ) + clicks: int = proto.Field( + proto.INT64, + number=131, + optional=True, + ) + combined_clicks: int = proto.Field( + proto.INT64, + number=156, + optional=True, + ) + combined_clicks_per_query: float = proto.Field( + proto.DOUBLE, + number=157, + optional=True, + ) + combined_queries: int = proto.Field( + proto.INT64, + number=158, + optional=True, + ) + content_budget_lost_impression_share: float = proto.Field( + proto.DOUBLE, + number=159, + optional=True, + ) + content_impression_share: float = proto.Field( + proto.DOUBLE, + number=160, + optional=True, + ) + conversion_last_received_request_date_time: str = proto.Field( + proto.STRING, + number=161, + optional=True, + ) + conversion_last_conversion_date: str = proto.Field( + proto.STRING, + number=162, + optional=True, + ) + content_rank_lost_impression_share: float = proto.Field( + proto.DOUBLE, + number=163, + optional=True, + ) + conversions_from_interactions_rate: float = proto.Field( + proto.DOUBLE, + number=164, + optional=True, + ) + conversions_value: float = proto.Field( + proto.DOUBLE, + number=165, + optional=True, + ) + conversions_value_by_conversion_date: float = proto.Field( + proto.DOUBLE, + number=242, + optional=True, + ) + new_customer_lifetime_value: float = proto.Field( + proto.DOUBLE, + number=293, + optional=True, + ) + conversions_value_per_cost: float = proto.Field( + proto.DOUBLE, + number=166, + optional=True, + ) + conversions_from_interactions_value_per_interaction: float = proto.Field( + proto.DOUBLE, + number=167, + optional=True, + ) + conversions: float = proto.Field( + proto.DOUBLE, + number=168, + optional=True, + ) + conversions_by_conversion_date: float = proto.Field( + proto.DOUBLE, + number=243, + optional=True, + ) + cost_micros: int = proto.Field( + proto.INT64, + number=169, + optional=True, + ) + cost_per_all_conversions: float = proto.Field( + proto.DOUBLE, + number=170, + optional=True, + ) + cost_per_conversion: float = proto.Field( + proto.DOUBLE, + number=171, + optional=True, + ) + cost_per_current_model_attributed_conversion: float = proto.Field( + proto.DOUBLE, + number=172, + optional=True, + ) + cross_device_conversions: float = proto.Field( + proto.DOUBLE, + number=173, + optional=True, + ) + cross_device_conversions_by_conversion_date: float = proto.Field( + proto.DOUBLE, + number=372, + optional=True, + ) + cross_device_conversions_value: float = proto.Field( + proto.DOUBLE, + number=253, + optional=True, + ) + cross_device_conversions_value_micros: int = proto.Field( + proto.INT64, + number=312, + optional=True, + ) + cross_device_conversions_value_by_conversion_date: float = proto.Field( + proto.DOUBLE, + number=373, + optional=True, + ) + ctr: float = proto.Field( + proto.DOUBLE, + number=174, + optional=True, + ) + current_model_attributed_conversions: float = proto.Field( + proto.DOUBLE, + number=175, + optional=True, + ) + current_model_attributed_conversions_from_interactions_rate: float = ( + proto.Field( + proto.DOUBLE, + number=176, + optional=True, + ) + ) + current_model_attributed_conversions_from_interactions_value_per_interaction: ( + float + ) = proto.Field( + proto.DOUBLE, + number=177, + optional=True, + ) + current_model_attributed_conversions_value: float = proto.Field( + proto.DOUBLE, + number=178, + optional=True, + ) + current_model_attributed_conversions_value_per_cost: float = proto.Field( + proto.DOUBLE, + number=179, + optional=True, + ) + engagement_rate: float = proto.Field( + proto.DOUBLE, + number=180, + optional=True, + ) + engagements: int = proto.Field( + proto.INT64, + number=181, + optional=True, + ) + hotel_average_lead_value_micros: float = proto.Field( + proto.DOUBLE, + number=213, + optional=True, + ) + hotel_commission_rate_micros: int = proto.Field( + proto.INT64, + number=256, + optional=True, + ) + hotel_expected_commission_cost: float = proto.Field( + proto.DOUBLE, + number=257, + optional=True, + ) + hotel_price_difference_percentage: float = proto.Field( + proto.DOUBLE, + number=214, + optional=True, + ) + hotel_eligible_impressions: int = proto.Field( + proto.INT64, + number=215, + optional=True, + ) + historical_creative_quality_score: ( + quality_score_bucket.QualityScoreBucketEnum.QualityScoreBucket + ) = proto.Field( + proto.ENUM, + number=80, + enum=quality_score_bucket.QualityScoreBucketEnum.QualityScoreBucket, + ) + historical_landing_page_quality_score: ( + quality_score_bucket.QualityScoreBucketEnum.QualityScoreBucket + ) = proto.Field( + proto.ENUM, + number=81, + enum=quality_score_bucket.QualityScoreBucketEnum.QualityScoreBucket, + ) + historical_quality_score: int = proto.Field( + proto.INT64, + number=216, + optional=True, + ) + historical_search_predicted_ctr: ( + quality_score_bucket.QualityScoreBucketEnum.QualityScoreBucket + ) = proto.Field( + proto.ENUM, + number=83, + enum=quality_score_bucket.QualityScoreBucketEnum.QualityScoreBucket, + ) + gmail_forwards: int = proto.Field( + proto.INT64, + number=217, + optional=True, + ) + gmail_saves: int = proto.Field( + proto.INT64, + number=218, + optional=True, + ) + gmail_secondary_clicks: int = proto.Field( + proto.INT64, + number=219, + optional=True, + ) + impressions_from_store_reach: int = proto.Field( + proto.INT64, + number=220, + optional=True, + ) + impressions: int = proto.Field( + proto.INT64, + number=221, + optional=True, + ) + interaction_rate: float = proto.Field( + proto.DOUBLE, + number=222, + optional=True, + ) + interactions: int = proto.Field( + proto.INT64, + number=223, + optional=True, + ) + interaction_event_types: MutableSequence[ + interaction_event_type.InteractionEventTypeEnum.InteractionEventType + ] = proto.RepeatedField( + proto.ENUM, + number=100, + enum=interaction_event_type.InteractionEventTypeEnum.InteractionEventType, + ) + invalid_click_rate: float = proto.Field( + proto.DOUBLE, + number=224, + optional=True, + ) + invalid_clicks: int = proto.Field( + proto.INT64, + number=225, + optional=True, + ) + general_invalid_click_rate: float = proto.Field( + proto.DOUBLE, + number=370, + optional=True, + ) + general_invalid_clicks: int = proto.Field( + proto.INT64, + number=371, + optional=True, + ) + message_chats: int = proto.Field( + proto.INT64, + number=226, + optional=True, + ) + message_impressions: int = proto.Field( + proto.INT64, + number=227, + optional=True, + ) + message_chat_rate: float = proto.Field( + proto.DOUBLE, + number=228, + optional=True, + ) + mobile_friendly_clicks_percentage: float = proto.Field( + proto.DOUBLE, + number=229, + optional=True, + ) + optimization_score_uplift: float = proto.Field( + proto.DOUBLE, + number=247, + optional=True, + ) + optimization_score_url: str = proto.Field( + proto.STRING, + number=248, + optional=True, + ) + organic_clicks: int = proto.Field( + proto.INT64, + number=230, + optional=True, + ) + organic_clicks_per_query: float = proto.Field( + proto.DOUBLE, + number=231, + optional=True, + ) + organic_impressions: int = proto.Field( + proto.INT64, + number=232, + optional=True, + ) + organic_impressions_per_query: float = proto.Field( + proto.DOUBLE, + number=233, + optional=True, + ) + organic_queries: int = proto.Field( + proto.INT64, + number=234, + optional=True, + ) + percent_new_visitors: float = proto.Field( + proto.DOUBLE, + number=235, + optional=True, + ) + phone_calls: int = proto.Field( + proto.INT64, + number=236, + optional=True, + ) + phone_impressions: int = proto.Field( + proto.INT64, + number=237, + optional=True, + ) + phone_through_rate: float = proto.Field( + proto.DOUBLE, + number=238, + optional=True, + ) + relative_ctr: float = proto.Field( + proto.DOUBLE, + number=239, + optional=True, + ) + search_absolute_top_impression_share: float = proto.Field( + proto.DOUBLE, + number=136, + optional=True, + ) + search_budget_lost_absolute_top_impression_share: float = proto.Field( + proto.DOUBLE, + number=137, + optional=True, + ) + search_budget_lost_impression_share: float = proto.Field( + proto.DOUBLE, + number=138, + optional=True, + ) + search_budget_lost_top_impression_share: float = proto.Field( + proto.DOUBLE, + number=139, + optional=True, + ) + search_click_share: float = proto.Field( + proto.DOUBLE, + number=140, + optional=True, + ) + search_exact_match_impression_share: float = proto.Field( + proto.DOUBLE, + number=141, + optional=True, + ) + search_impression_share: float = proto.Field( + proto.DOUBLE, + number=142, + optional=True, + ) + search_rank_lost_absolute_top_impression_share: float = proto.Field( + proto.DOUBLE, + number=143, + optional=True, + ) + search_rank_lost_impression_share: float = proto.Field( + proto.DOUBLE, + number=144, + optional=True, + ) + search_rank_lost_top_impression_share: float = proto.Field( + proto.DOUBLE, + number=145, + optional=True, + ) + search_top_impression_share: float = proto.Field( + proto.DOUBLE, + number=146, + optional=True, + ) + search_volume: "SearchVolumeRange" = proto.Field( + proto.MESSAGE, + number=295, + optional=True, + message="SearchVolumeRange", + ) + speed_score: int = proto.Field( + proto.INT64, + number=147, + optional=True, + ) + average_target_cpa_micros: int = proto.Field( + proto.INT64, + number=290, + optional=True, + ) + average_target_roas: float = proto.Field( + proto.DOUBLE, + number=250, + optional=True, + ) + top_impression_percentage: float = proto.Field( + proto.DOUBLE, + number=148, + optional=True, + ) + valid_accelerated_mobile_pages_clicks_percentage: float = proto.Field( + proto.DOUBLE, + number=149, + optional=True, + ) + value_per_all_conversions: float = proto.Field( + proto.DOUBLE, + number=150, + optional=True, + ) + value_per_all_conversions_by_conversion_date: float = proto.Field( + proto.DOUBLE, + number=244, + optional=True, + ) + value_per_conversion: float = proto.Field( + proto.DOUBLE, + number=151, + optional=True, + ) + value_per_conversions_by_conversion_date: float = proto.Field( + proto.DOUBLE, + number=245, + optional=True, + ) + value_per_current_model_attributed_conversion: float = proto.Field( + proto.DOUBLE, + number=152, + optional=True, + ) + video_quartile_p100_rate: float = proto.Field( + proto.DOUBLE, + number=132, + optional=True, + ) + video_quartile_p25_rate: float = proto.Field( + proto.DOUBLE, + number=133, + optional=True, + ) + video_quartile_p50_rate: float = proto.Field( + proto.DOUBLE, + number=134, + optional=True, + ) + video_quartile_p75_rate: float = proto.Field( + proto.DOUBLE, + number=135, + optional=True, + ) + video_trueview_view_rate: float = proto.Field( + proto.DOUBLE, + number=406, + optional=True, + ) + video_trueview_views: int = proto.Field( + proto.INT64, + number=407, + optional=True, + ) + view_through_conversions: int = proto.Field( + proto.INT64, + number=155, + optional=True, + ) + sk_ad_network_installs: int = proto.Field( + proto.INT64, + number=246, + ) + sk_ad_network_total_conversions: int = proto.Field( + proto.INT64, + number=292, + ) + publisher_purchased_clicks: int = proto.Field( + proto.INT64, + number=264, + ) + publisher_organic_clicks: int = proto.Field( + proto.INT64, + number=265, + ) + publisher_unknown_clicks: int = proto.Field( + proto.INT64, + number=266, + ) + all_conversions_from_location_asset_click_to_call: float = proto.Field( + proto.DOUBLE, + number=267, + optional=True, + ) + all_conversions_from_location_asset_directions: float = proto.Field( + proto.DOUBLE, + number=268, + optional=True, + ) + all_conversions_from_location_asset_menu: float = proto.Field( + proto.DOUBLE, + number=269, + optional=True, + ) + all_conversions_from_location_asset_order: float = proto.Field( + proto.DOUBLE, + number=270, + optional=True, + ) + all_conversions_from_location_asset_other_engagement: float = proto.Field( + proto.DOUBLE, + number=271, + optional=True, + ) + all_conversions_from_location_asset_store_visits: float = proto.Field( + proto.DOUBLE, + number=272, + optional=True, + ) + all_conversions_from_location_asset_website: float = proto.Field( + proto.DOUBLE, + number=273, + optional=True, + ) + eligible_impressions_from_location_asset_store_reach: int = proto.Field( + proto.INT64, + number=274, + optional=True, + ) + view_through_conversions_from_location_asset_click_to_call: float = ( + proto.Field( + proto.DOUBLE, + number=275, + optional=True, + ) + ) + view_through_conversions_from_location_asset_directions: float = ( + proto.Field( + proto.DOUBLE, + number=276, + optional=True, + ) + ) + view_through_conversions_from_location_asset_menu: float = proto.Field( + proto.DOUBLE, + number=277, + optional=True, + ) + view_through_conversions_from_location_asset_order: float = proto.Field( + proto.DOUBLE, + number=278, + optional=True, + ) + view_through_conversions_from_location_asset_other_engagement: float = ( + proto.Field( + proto.DOUBLE, + number=279, + optional=True, + ) + ) + view_through_conversions_from_location_asset_store_visits: float = ( + proto.Field( + proto.DOUBLE, + number=280, + optional=True, + ) + ) + view_through_conversions_from_location_asset_website: float = proto.Field( + proto.DOUBLE, + number=281, + optional=True, + ) + orders: float = proto.Field( + proto.DOUBLE, + number=296, + optional=True, + ) + average_order_value_micros: int = proto.Field( + proto.INT64, + number=297, + optional=True, + ) + average_cart_size: float = proto.Field( + proto.DOUBLE, + number=298, + optional=True, + ) + cost_of_goods_sold_micros: int = proto.Field( + proto.INT64, + number=299, + optional=True, + ) + gross_profit_micros: int = proto.Field( + proto.INT64, + number=300, + optional=True, + ) + gross_profit_margin: float = proto.Field( + proto.DOUBLE, + number=301, + optional=True, + ) + revenue_micros: int = proto.Field( + proto.INT64, + number=302, + optional=True, + ) + units_sold: float = proto.Field( + proto.DOUBLE, + number=303, + optional=True, + ) + cross_sell_cost_of_goods_sold_micros: int = proto.Field( + proto.INT64, + number=304, + optional=True, + ) + cross_sell_gross_profit_micros: int = proto.Field( + proto.INT64, + number=305, + optional=True, + ) + cross_sell_revenue_micros: int = proto.Field( + proto.INT64, + number=306, + optional=True, + ) + cross_sell_units_sold: float = proto.Field( + proto.DOUBLE, + number=307, + optional=True, + ) + lead_cost_of_goods_sold_micros: int = proto.Field( + proto.INT64, + number=308, + optional=True, + ) + lead_gross_profit_micros: int = proto.Field( + proto.INT64, + number=309, + optional=True, + ) + lead_revenue_micros: int = proto.Field( + proto.INT64, + number=310, + optional=True, + ) + lead_units_sold: float = proto.Field( + proto.DOUBLE, + number=311, + optional=True, + ) + unique_users: int = proto.Field( + proto.INT64, + number=319, + optional=True, + ) + average_impression_frequency_per_user: float = proto.Field( + proto.DOUBLE, + number=320, + optional=True, + ) + linked_entities_count: int = proto.Field( + proto.INT64, + number=341, + optional=True, + ) + linked_sample_entities: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=342, + ) + asset_pinned_total_count: int = proto.Field( + proto.INT64, + number=348, + optional=True, + ) + asset_pinned_as_headline_position_one_count: int = proto.Field( + proto.INT64, + number=349, + optional=True, + ) + asset_pinned_as_headline_position_two_count: int = proto.Field( + proto.INT64, + number=350, + optional=True, + ) + asset_pinned_as_headline_position_three_count: int = proto.Field( + proto.INT64, + number=351, + optional=True, + ) + asset_pinned_as_description_position_one_count: int = proto.Field( + proto.INT64, + number=352, + optional=True, + ) + asset_pinned_as_description_position_two_count: int = proto.Field( + proto.INT64, + number=353, + optional=True, + ) + store_visits_last_click_model_attributed_conversions: float = proto.Field( + proto.DOUBLE, + number=365, + optional=True, + ) + results_conversions_purchase: float = proto.Field( + proto.DOUBLE, + number=366, + optional=True, + ) + video_trueview_view_rate_in_feed: float = proto.Field( + proto.DOUBLE, + number=408, + optional=True, + ) + video_trueview_view_rate_in_stream: float = proto.Field( + proto.DOUBLE, + number=409, + optional=True, + ) + video_trueview_view_rate_shorts: float = proto.Field( + proto.DOUBLE, + number=410, + optional=True, + ) + coviewed_impressions: int = proto.Field( + proto.INT64, + number=380, + optional=True, + ) + primary_impressions: int = proto.Field( + proto.INT64, + number=381, + optional=True, + ) + platform_comparable_conversions_from_interactions_rate: float = proto.Field( + proto.DOUBLE, + number=382, + optional=True, + ) + platform_comparable_conversions: float = proto.Field( + proto.DOUBLE, + number=383, + optional=True, + ) + platform_comparable_conversions_value: float = proto.Field( + proto.DOUBLE, + number=384, + optional=True, + ) + platform_comparable_conversions_value_per_cost: float = proto.Field( + proto.DOUBLE, + number=385, + optional=True, + ) + platform_comparable_conversions_by_conversion_date: float = proto.Field( + proto.DOUBLE, + number=386, + optional=True, + ) + platform_comparable_conversions_value_by_conversion_date: float = ( + proto.Field( + proto.DOUBLE, + number=387, + optional=True, + ) + ) + platform_comparable_conversions_from_interactions_value_per_interaction: ( + float + ) = proto.Field( + proto.DOUBLE, + number=388, + optional=True, + ) + cost_per_platform_comparable_conversion: float = proto.Field( + proto.DOUBLE, + number=389, + optional=True, + ) + value_per_platform_comparable_conversion: float = proto.Field( + proto.DOUBLE, + number=390, + optional=True, + ) + value_per_platform_comparable_conversions_by_conversion_date: float = ( + proto.Field( + proto.DOUBLE, + number=391, + optional=True, + ) + ) + cost_converted_currency_per_platform_comparable_conversion: float = ( + proto.Field( + proto.DOUBLE, + number=392, + optional=True, + ) + ) + unique_users_two_plus: int = proto.Field( + proto.INT64, + number=393, + optional=True, + ) + unique_users_three_plus: int = proto.Field( + proto.INT64, + number=394, + optional=True, + ) + unique_users_four_plus: int = proto.Field( + proto.INT64, + number=395, + optional=True, + ) + unique_users_five_plus: int = proto.Field( + proto.INT64, + number=396, + optional=True, + ) + unique_users_ten_plus: int = proto.Field( + proto.INT64, + number=397, + optional=True, + ) + value_adjustment: float = proto.Field( + proto.DOUBLE, + number=398, + optional=True, + ) + all_value_adjustment: float = proto.Field( + proto.DOUBLE, + number=399, + optional=True, + ) + clicks_unique_query_clusters: int = proto.Field( + proto.INT64, + number=400, + optional=True, + ) + conversions_unique_query_clusters: int = proto.Field( + proto.INT64, + number=401, + optional=True, + ) + impressions_unique_query_clusters: int = proto.Field( + proto.INT64, + number=402, + optional=True, + ) + video_watch_time_duration_millis: int = proto.Field( + proto.INT64, + number=403, + optional=True, + ) + average_video_watch_time_duration_millis: int = proto.Field( + proto.INT64, + number=404, + optional=True, + ) + svr: int = proto.Field( + proto.INT64, + number=411, + optional=True, + ) + active_view_audibility_measurable_impressions: int = proto.Field( + proto.INT64, + number=412, + optional=True, + ) + active_view_audibility_measurable_impressions_rate: float = proto.Field( + proto.DOUBLE, + number=413, + optional=True, + ) + active_view_audibility_invalid_measurable_impressions_rate: float = ( + proto.Field( + proto.DOUBLE, + number=414, + optional=True, + ) + ) + active_view_audibility_invalid_givt_measurable_impressions_rate: float = ( + proto.Field( + proto.DOUBLE, + number=415, + optional=True, + ) + ) + active_view_audible_impressions: int = proto.Field( + proto.INT64, + number=416, + optional=True, + ) + active_view_audible_impressions_rate: float = proto.Field( + proto.DOUBLE, + number=417, + optional=True, + ) + active_view_audible_two_seconds_impressions: int = proto.Field( + proto.INT64, + number=418, + optional=True, + ) + active_view_audible_two_seconds_impressions_rate: float = proto.Field( + proto.DOUBLE, + number=419, + optional=True, + ) + active_view_audible_thirty_seconds_impressions: int = proto.Field( + proto.INT64, + number=420, + optional=True, + ) + active_view_audible_thirty_seconds_impressions_rate: float = proto.Field( + proto.DOUBLE, + number=421, + optional=True, + ) + active_view_audible_quartile_p25_rate: float = proto.Field( + proto.DOUBLE, + number=422, + optional=True, + ) + active_view_audible_quartile_p50_rate: float = proto.Field( + proto.DOUBLE, + number=423, + optional=True, + ) + active_view_audible_quartile_p75_rate: float = proto.Field( + proto.DOUBLE, + number=424, + optional=True, + ) + active_view_audible_quartile_p100_rate: float = proto.Field( + proto.DOUBLE, + number=425, + optional=True, + ) + biddable_indirect_install_first_in_app_conversion_micros: int = proto.Field( + proto.INT64, + number=426, + optional=True, + ) + all_average_cart_size: float = proto.Field( + proto.DOUBLE, + number=427, + optional=True, + ) + all_average_order_value_micros: int = proto.Field( + proto.INT64, + number=428, + optional=True, + ) + all_cost_of_goods_sold_micros: int = proto.Field( + proto.INT64, + number=429, + optional=True, + ) + all_cross_sell_cost_of_goods_sold_micros: int = proto.Field( + proto.INT64, + number=430, + optional=True, + ) + all_cross_sell_gross_profit_micros: int = proto.Field( + proto.INT64, + number=431, + optional=True, + ) + all_cross_sell_revenue_micros: int = proto.Field( + proto.INT64, + number=432, + optional=True, + ) + all_cross_sell_units_sold: float = proto.Field( + proto.DOUBLE, + number=433, + optional=True, + ) + all_gross_profit_margin: float = proto.Field( + proto.DOUBLE, + number=434, + optional=True, + ) + all_gross_profit_micros: int = proto.Field( + proto.INT64, + number=435, + optional=True, + ) + all_lead_cost_of_goods_sold_micros: int = proto.Field( + proto.INT64, + number=436, + optional=True, + ) + all_lead_gross_profit_micros: int = proto.Field( + proto.INT64, + number=437, + optional=True, + ) + all_lead_revenue_micros: int = proto.Field( + proto.INT64, + number=438, + optional=True, + ) + all_lead_units_sold: float = proto.Field( + proto.DOUBLE, + number=439, + optional=True, + ) + all_orders: float = proto.Field( + proto.DOUBLE, + number=440, + optional=True, + ) + all_revenue_micros: int = proto.Field( + proto.INT64, + number=441, + optional=True, + ) + all_units_sold: float = proto.Field( + proto.DOUBLE, + number=442, + optional=True, + ) + + +class SearchVolumeRange(proto.Message): + r"""Search volume range. + Actual search volume falls within this range. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + min_ (int): + Lower bound of search volume. + + This field is a member of `oneof`_ ``_min``. + max_ (int): + Upper bound of search volume. + + This field is a member of `oneof`_ ``_max``. + """ + + min_: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + max_: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/offline_user_data.py b/google/ads/googleads/v24/common/types/offline_user_data.py new file mode 100644 index 000000000..0b60d20f0 --- /dev/null +++ b/google/ads/googleads/v24/common/types/offline_user_data.py @@ -0,0 +1,798 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import consent as gagc_consent +from google.ads.googleads.v24.enums.types import ( + user_identifier_source as gage_user_identifier_source, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "OfflineUserAddressInfo", + "UserIdentifier", + "TransactionAttribute", + "StoreAttribute", + "ItemAttribute", + "UserData", + "UserAttribute", + "EventAttribute", + "EventItemAttribute", + "ShoppingLoyalty", + "CustomerMatchUserListMetadata", + "StoreSalesMetadata", + "StoreSalesThirdPartyMetadata", + }, +) + + +class OfflineUserAddressInfo(proto.Message): + r"""Address identifier of offline data. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + hashed_first_name (str): + First name of the user, which is hashed as + SHA-256 after normalized (Lowercase all + characters; Remove any extra spaces before, + after, and in between). + + This field is a member of `oneof`_ ``_hashed_first_name``. + hashed_last_name (str): + Last name of the user, which is hashed as + SHA-256 after normalized (lower case only and no + punctuation). + + This field is a member of `oneof`_ ``_hashed_last_name``. + city (str): + City of the address. Only accepted for Store + Sales and ConversionAdjustmentUploadService. + + This field is a member of `oneof`_ ``_city``. + state (str): + State code of the address. Only accepted for + Store Sales and + ConversionAdjustmentUploadService. + + This field is a member of `oneof`_ ``_state``. + country_code (str): + 2-letter country code in ISO-3166-1 alpha-2 + of the user's address. + + This field is a member of `oneof`_ ``_country_code``. + postal_code (str): + Postal code of the user's address. + + This field is a member of `oneof`_ ``_postal_code``. + hashed_street_address (str): + The street address of the user hashed using + SHA-256 hash function after normalization (lower + case only). Only accepted for + ConversionAdjustmentUploadService. + + This field is a member of `oneof`_ ``_hashed_street_address``. + """ + + hashed_first_name: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + hashed_last_name: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + city: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + state: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + country_code: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + postal_code: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + hashed_street_address: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + + +class UserIdentifier(proto.Message): + r"""User identifying information. + + 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: + user_identifier_source (google.ads.googleads.v24.enums.types.UserIdentifierSourceEnum.UserIdentifierSource): + Source of the user identifier when the upload + is from Store Sales, ConversionUploadService, or + ConversionAdjustmentUploadService. + hashed_email (str): + Hashed email address using SHA-256 hash + function after normalization. Accepted for + Customer Match, Store Sales, + ConversionUploadService, and + ConversionAdjustmentUploadService. + + This field is a member of `oneof`_ ``identifier``. + hashed_phone_number (str): + Hashed phone number using SHA-256 hash + function after normalization (E164 standard). + Accepted for Customer Match, Store Sales, + ConversionUploadService, and + ConversionAdjustmentUploadService. + + This field is a member of `oneof`_ ``identifier``. + mobile_id (str): + Mobile device ID (advertising ID/IDFA). + Accepted only for Customer Match. + + This field is a member of `oneof`_ ``identifier``. + third_party_user_id (str): + Advertiser-assigned user ID for Customer + Match upload, or third-party-assigned user ID + for Store Sales. Accepted only for Customer + Match and Store Sales. + + This field is a member of `oneof`_ ``identifier``. + address_info (google.ads.googleads.v24.common.types.OfflineUserAddressInfo): + Address information. Accepted only for + Customer Match, Store Sales, and + ConversionAdjustmentUploadService. + + This field is a member of `oneof`_ ``identifier``. + """ + + user_identifier_source: ( + gage_user_identifier_source.UserIdentifierSourceEnum.UserIdentifierSource + ) = proto.Field( + proto.ENUM, + number=6, + enum=gage_user_identifier_source.UserIdentifierSourceEnum.UserIdentifierSource, + ) + hashed_email: str = proto.Field( + proto.STRING, + number=7, + oneof="identifier", + ) + hashed_phone_number: str = proto.Field( + proto.STRING, + number=8, + oneof="identifier", + ) + mobile_id: str = proto.Field( + proto.STRING, + number=9, + oneof="identifier", + ) + third_party_user_id: str = proto.Field( + proto.STRING, + number=10, + oneof="identifier", + ) + address_info: "OfflineUserAddressInfo" = proto.Field( + proto.MESSAGE, + number=5, + oneof="identifier", + message="OfflineUserAddressInfo", + ) + + +class TransactionAttribute(proto.Message): + r"""Attribute of the store sales transaction. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + transaction_date_time (str): + Timestamp when transaction occurred. Required. The format is + "YYYY-MM-DD HH:MM:SS[+/-HH:MM]", where [+/-HH:MM] is an + optional timezone offset from UTC. If the offset is absent, + the API will use the account's timezone as default. + Examples: "2018-03-05 09:15:00" or "2018-02-01 + 14:34:30+03:00". + + This field is a member of `oneof`_ ``_transaction_date_time``. + transaction_amount_micros (float): + Transaction amount in micros. Required. + Transaction amount in micros needs to be greater + than 1000. If item Attributes are provided, it + represents the total value of the items, after + multiplying the unit price per item by the + quantity provided in the ItemAttributes. + + This field is a member of `oneof`_ ``_transaction_amount_micros``. + currency_code (str): + Transaction currency code. ISO 4217 + three-letter code is used. Required. + + This field is a member of `oneof`_ ``_currency_code``. + conversion_action (str): + The resource name of conversion action to + report conversions to. Required. + + This field is a member of `oneof`_ ``_conversion_action``. + order_id (str): + Transaction order id. Useful to group + transactions which are part of the same order. + + This field is a member of `oneof`_ ``_order_id``. + store_attribute (google.ads.googleads.v24.common.types.StoreAttribute): + Store attributes of the transaction. + custom_value (str): + Value of the custom variable for each + transaction. Allowed only if a custom key is + provided in the store sales metadata. + + This field is a member of `oneof`_ ``_custom_value``. + item_attribute (google.ads.googleads.v24.common.types.ItemAttribute): + Item attributes of the transaction. + Accessible only to customers on the allow-list. + """ + + transaction_date_time: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + transaction_amount_micros: float = proto.Field( + proto.DOUBLE, + number=9, + optional=True, + ) + currency_code: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + conversion_action: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + order_id: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + store_attribute: "StoreAttribute" = proto.Field( + proto.MESSAGE, + number=6, + message="StoreAttribute", + ) + custom_value: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + item_attribute: "ItemAttribute" = proto.Field( + proto.MESSAGE, + number=14, + message="ItemAttribute", + ) + + +class StoreAttribute(proto.Message): + r"""Store attributes of the transaction. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + store_code (str): + Store code from + https://support.google.com/business/answer/3370250#storecode + + This field is a member of `oneof`_ ``_store_code``. + """ + + store_code: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class ItemAttribute(proto.Message): + r"""Item attributes of the transaction. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + item_id (str): + A unique identifier of a product. It must be + the exact same Merchant Center Item ID you use + in your Google Merchant Center for this product. + Required. + merchant_id (int): + ID of the Merchant Center Account. + Required. + + This field is a member of `oneof`_ ``_merchant_id``. + country_code (str): + Common Locale Data Repository (CLDR) territory code of the + country associated with the feed where your items are + uploaded. See + https://developers.google.com/google-ads/api/reference/data/codes-formats#country-codes + for more information. This information is useful to + differentiate product information in cases where a product + (identified by item_id) is associated with multiple + countries. + language_code (str): + ISO 639-1 code of the language associated with the feed + where your items are uploaded. This information is useful to + differentiate product information in cases where a product + (identified by item_id) is associated with multiple + languages. + quantity (int): + The number of items sold. Defaults to 1 if + not set. + """ + + item_id: str = proto.Field( + proto.STRING, + number=1, + ) + merchant_id: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + country_code: str = proto.Field( + proto.STRING, + number=3, + ) + language_code: str = proto.Field( + proto.STRING, + number=4, + ) + quantity: int = proto.Field( + proto.INT64, + number=5, + ) + + +class UserData(proto.Message): + r"""User data holding user identifiers and attributes. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + user_identifiers (MutableSequence[google.ads.googleads.v24.common.types.UserIdentifier]): + User identification info. Required. + transaction_attribute (google.ads.googleads.v24.common.types.TransactionAttribute): + Additional transactions/attributes associated + with the user. Required when updating store + sales data. + user_attribute (google.ads.googleads.v24.common.types.UserAttribute): + Additional attributes associated with the + user. Required when updating customer match + attributes. These have an expiration of 540 + days. + consent (google.ads.googleads.v24.common.types.Consent): + The consent setting for the user. If set, + will override the job level consent for this + user. + + This field is a member of `oneof`_ ``_consent``. + """ + + user_identifiers: MutableSequence["UserIdentifier"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="UserIdentifier", + ) + transaction_attribute: "TransactionAttribute" = proto.Field( + proto.MESSAGE, + number=2, + message="TransactionAttribute", + ) + user_attribute: "UserAttribute" = proto.Field( + proto.MESSAGE, + number=3, + message="UserAttribute", + ) + consent: gagc_consent.Consent = proto.Field( + proto.MESSAGE, + number=4, + optional=True, + message=gagc_consent.Consent, + ) + + +class UserAttribute(proto.Message): + r"""User attribute, can only be used with CUSTOMER_MATCH_WITH_ATTRIBUTES + job type. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + lifetime_value_micros (int): + Advertiser defined lifetime value for the + user. + + This field is a member of `oneof`_ ``_lifetime_value_micros``. + lifetime_value_bucket (int): + Advertiser defined lifetime value bucket for + the user. The valid range for a lifetime value + bucket is from 1 (low) to 10 (high), except for + remove operation where 0 will also be accepted. + + This field is a member of `oneof`_ ``_lifetime_value_bucket``. + last_purchase_date_time (str): + Timestamp of the last purchase made by the user. The format + is YYYY-MM-DD HH:MM:SS[+/-HH:MM], where [+/-HH:MM] is an + optional timezone offset from UTC. If the offset is absent, + the API will use the account's timezone as default. + average_purchase_count (int): + Advertiser defined average number of + purchases that are made by the user in a 30 day + period. + average_purchase_value_micros (int): + Advertiser defined average purchase value in + micros for the user. + acquisition_date_time (str): + Timestamp when the user was acquired. The format is + YYYY-MM-DD HH:MM:SS[+/-HH:MM], where [+/-HH:MM] is an + optional timezone offset from UTC. If the offset is absent, + the API will use the account's timezone as default. + shopping_loyalty (google.ads.googleads.v24.common.types.ShoppingLoyalty): + The shopping loyalty related data. Shopping + utilizes this data to provide users with a + better experience. Accessible only to merchants + on the allow-list with the user's consent. + + This field is a member of `oneof`_ ``_shopping_loyalty``. + lifecycle_stage (str): + Optional. Advertiser defined lifecycle stage + for the user. The accepted values are "Lead", + "Active" and "Churned". + first_purchase_date_time (str): + Optional. Timestamp of the first purchase made by the user. + The format is YYYY-MM-DD HH:MM:SS[+/-HH:MM], where + [+/-HH:MM] is an optional timezone offset from UTC. If the + offset is absent, the API will use the account's timezone as + default. + event_attribute (MutableSequence[google.ads.googleads.v24.common.types.EventAttribute]): + Optional. Advertiser defined events and their + attributes. All the values in the nested fields + are required. Currently this field is in beta. + """ + + lifetime_value_micros: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + lifetime_value_bucket: int = proto.Field( + proto.INT32, + number=2, + optional=True, + ) + last_purchase_date_time: str = proto.Field( + proto.STRING, + number=3, + ) + average_purchase_count: int = proto.Field( + proto.INT32, + number=4, + ) + average_purchase_value_micros: int = proto.Field( + proto.INT64, + number=5, + ) + acquisition_date_time: str = proto.Field( + proto.STRING, + number=6, + ) + shopping_loyalty: "ShoppingLoyalty" = proto.Field( + proto.MESSAGE, + number=7, + optional=True, + message="ShoppingLoyalty", + ) + lifecycle_stage: str = proto.Field( + proto.STRING, + number=8, + ) + first_purchase_date_time: str = proto.Field( + proto.STRING, + number=9, + ) + event_attribute: MutableSequence["EventAttribute"] = proto.RepeatedField( + proto.MESSAGE, + number=10, + message="EventAttribute", + ) + + +class EventAttribute(proto.Message): + r"""Advertiser defined events and their attributes. All the + values in the nested fields are required. + + Attributes: + event (str): + Required. Advertiser defined event to be used + for remarketing. The accepted values are + "Viewed", "Cart", "Purchased" and "Recommended". + event_date_time (str): + Required. Timestamp at which the event happened. The format + is YYYY-MM-DD HH:MM:SS[+/-HH:MM], where [+/-HH:MM] is an + optional timezone offset from UTC. If the offset is absent, + the API will use the account's timezone as default. + item_attribute (MutableSequence[google.ads.googleads.v24.common.types.EventItemAttribute]): + Required. Item attributes of the event. + """ + + event: str = proto.Field( + proto.STRING, + number=1, + ) + event_date_time: str = proto.Field( + proto.STRING, + number=2, + ) + item_attribute: MutableSequence["EventItemAttribute"] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="EventItemAttribute", + ) + + +class EventItemAttribute(proto.Message): + r"""Event Item attributes of the Customer Match. + + Attributes: + item_id (str): + Optional. A unique identifier of a product. + It can be either the Merchant Center Item ID or + GTIN (Global Trade Item Number). + """ + + item_id: str = proto.Field( + proto.STRING, + number=1, + ) + + +class ShoppingLoyalty(proto.Message): + r"""The shopping loyalty related data. Shopping utilizes this + data to provide users with a better experience. + Accessible only to merchants on the allow-list. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + loyalty_tier (str): + The membership tier. It is a free-form string + as each merchant may have their own loyalty + system. For example, it could be a number from 1 + to 10, or a string such as "Golden" or "Silver", + or even empty string "". + + This field is a member of `oneof`_ ``_loyalty_tier``. + """ + + loyalty_tier: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class CustomerMatchUserListMetadata(proto.Message): + r"""Metadata for customer match user list. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + user_list (str): + The resource name of remarketing list to update data. + Required for job of CUSTOMER_MATCH_USER_LIST type. + + This field is a member of `oneof`_ ``_user_list``. + consent (google.ads.googleads.v24.common.types.Consent): + The consent setting for all the users in this + job. + + This field is a member of `oneof`_ ``_consent``. + """ + + user_list: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + consent: gagc_consent.Consent = proto.Field( + proto.MESSAGE, + number=3, + optional=True, + message=gagc_consent.Consent, + ) + + +class StoreSalesMetadata(proto.Message): + r"""Metadata for Store Sales Direct. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + loyalty_fraction (float): + This is the fraction of all transactions that + are identifiable (for example, associated with + any form of customer information). Required. The + fraction needs to be between 0 and 1 (excluding + 0). + + This field is a member of `oneof`_ ``_loyalty_fraction``. + transaction_upload_fraction (float): + This is the ratio of sales being uploaded + compared to the overall sales that can be + associated with a customer. Required. The + fraction needs to be between 0 and 1 (excluding + 0). For example, if you upload half the sales + that you are able to associate with a customer, + this would be 0.5. + + This field is a member of `oneof`_ ``_transaction_upload_fraction``. + custom_key (str): + Name of the store sales custom variable key. + A predefined key that can be applied to the + transaction and then later used for custom + segmentation in reporting. + Accessible only to customers on the allow-list. + + This field is a member of `oneof`_ ``_custom_key``. + third_party_metadata (google.ads.googleads.v24.common.types.StoreSalesThirdPartyMetadata): + Metadata for a third party Store Sales + upload. + """ + + loyalty_fraction: float = proto.Field( + proto.DOUBLE, + number=5, + optional=True, + ) + transaction_upload_fraction: float = proto.Field( + proto.DOUBLE, + number=6, + optional=True, + ) + custom_key: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + third_party_metadata: "StoreSalesThirdPartyMetadata" = proto.Field( + proto.MESSAGE, + number=3, + message="StoreSalesThirdPartyMetadata", + ) + + +class StoreSalesThirdPartyMetadata(proto.Message): + r"""Metadata for a third party Store Sales. + This product is only for customers on the allow-list. Contact + your Google business development representative for details on + the upload configuration. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + advertiser_upload_date_time (str): + Time the advertiser uploaded the data to the + partner. Required. The format is "YYYY-MM-DD + HH:MM:SS". Examples: "2018-03-05 09:15:00" or + "2018-02-01 14:34:30". + + This field is a member of `oneof`_ ``_advertiser_upload_date_time``. + valid_transaction_fraction (float): + The fraction of transactions that are valid. + Invalid transactions may include invalid formats + or values. Required. + The fraction needs to be between 0 and 1 + (excluding 0). + + This field is a member of `oneof`_ ``_valid_transaction_fraction``. + partner_match_fraction (float): + The fraction of valid transactions that are + matched to a third party assigned user ID on the + partner side. Required. + The fraction needs to be between 0 and 1 + (excluding 0). + + This field is a member of `oneof`_ ``_partner_match_fraction``. + partner_upload_fraction (float): + The fraction of valid transactions that are + uploaded by the partner to Google. + Required. + The fraction needs to be between 0 and 1 + (excluding 0). + + This field is a member of `oneof`_ ``_partner_upload_fraction``. + bridge_map_version_id (str): + Version of partner IDs to be used for + uploads. Required. + + This field is a member of `oneof`_ ``_bridge_map_version_id``. + partner_id (int): + ID of the third party partner updating the + transaction feed. + + This field is a member of `oneof`_ ``_partner_id``. + """ + + advertiser_upload_date_time: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + valid_transaction_fraction: float = proto.Field( + proto.DOUBLE, + number=8, + optional=True, + ) + partner_match_fraction: float = proto.Field( + proto.DOUBLE, + number=9, + optional=True, + ) + partner_upload_fraction: float = proto.Field( + proto.DOUBLE, + number=10, + optional=True, + ) + bridge_map_version_id: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + partner_id: int = proto.Field( + proto.INT64, + number=12, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/policy.py b/google/ads/googleads/v24/common/types/policy.py new file mode 100644 index 000000000..7b08ab2d8 --- /dev/null +++ b/google/ads/googleads/v24/common/types/policy.py @@ -0,0 +1,515 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import policy_topic_entry_type +from google.ads.googleads.v24.enums.types import ( + policy_topic_evidence_destination_mismatch_url_type, +) +from google.ads.googleads.v24.enums.types import ( + policy_topic_evidence_destination_not_working_device, +) +from google.ads.googleads.v24.enums.types import ( + policy_topic_evidence_destination_not_working_dns_error_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "PolicyViolationKey", + "PolicyValidationParameter", + "PolicyTopicEntry", + "PolicyTopicEvidence", + "PolicyTopicConstraint", + }, +) + + +class PolicyViolationKey(proto.Message): + r"""Key of the violation. The key is used for referring to a + violation when filing an exemption request. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + policy_name (str): + Unique ID of the violated policy. + + This field is a member of `oneof`_ ``_policy_name``. + violating_text (str): + The text that violates the policy if + specified. Otherwise, refers to the policy in + general (for example, when requesting to be + exempt from the whole policy). If not specified + for criterion exemptions, the whole policy is + implied. Must be specified for ad exemptions. + + This field is a member of `oneof`_ ``_violating_text``. + """ + + policy_name: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + violating_text: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + + +class PolicyValidationParameter(proto.Message): + r"""Parameter for controlling how policy exemption is done. + + Attributes: + ignorable_policy_topics (MutableSequence[str]): + The list of policy topics that should not cause a + ``PolicyFindingError`` to be reported. This field is used + for ad policy exemptions. It corresponds to the + ``PolicyTopicEntry.topic`` field. + + If this field is populated, then + ``exempt_policy_violation_keys`` must be empty. + + Resources that violate these policies will be saved, but + will not be eligible to serve. They may begin serving at a + later time due to a change in policies, re-review of the + resource, or a change in advertiser certificates. + exempt_policy_violation_keys (MutableSequence[google.ads.googleads.v24.common.types.PolicyViolationKey]): + The list of policy violation keys that should not cause a + ``PolicyViolationError`` to be reported. Not all policy + violations are exemptable. Refer to the ``is_exemptible`` + field in the returned ``PolicyViolationError``. This field + is used for keyword policy exemptions. + + If this field is populated, then ``ignorable_policy_topics`` + must be empty. + + Resources that violate these policies will be saved, but + will not be eligible to serve. They may begin serving at a + later time due to a change in policies, re-review of the + resource, or a change in advertiser certificates. + """ + + ignorable_policy_topics: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + exempt_policy_violation_keys: MutableSequence["PolicyViolationKey"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="PolicyViolationKey", + ) + ) + + +class PolicyTopicEntry(proto.Message): + r"""Policy finding attached to a resource (for example, alcohol + policy associated with a site that sells alcohol). + + Each PolicyTopicEntry has a topic that indicates the specific + ads policy the entry is about and a type to indicate the effect + that the entry will have on serving. It may optionally have one + or more evidences that indicate the reason for the finding. It + may also optionally have one or more constraints that provide + details about how serving may be restricted. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + topic (str): + Policy topic this finding refers to. For example, "ALCOHOL", + "TRADEMARKS_IN_AD_TEXT", or "DESTINATION_NOT_WORKING". The + set of possible policy topics is not fixed for a particular + API version and may change at any time. + + This field is a member of `oneof`_ ``_topic``. + type_ (google.ads.googleads.v24.enums.types.PolicyTopicEntryTypeEnum.PolicyTopicEntryType): + Describes the negative or positive effect + this policy will have on serving. + evidences (MutableSequence[google.ads.googleads.v24.common.types.PolicyTopicEvidence]): + Additional information that explains policy + finding (for example, the brand name for a + trademark finding). + constraints (MutableSequence[google.ads.googleads.v24.common.types.PolicyTopicConstraint]): + Indicates how serving of this resource may be + affected (for example, not serving in a + country). + """ + + topic: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + type_: ( + policy_topic_entry_type.PolicyTopicEntryTypeEnum.PolicyTopicEntryType + ) = proto.Field( + proto.ENUM, + number=2, + enum=policy_topic_entry_type.PolicyTopicEntryTypeEnum.PolicyTopicEntryType, + ) + evidences: MutableSequence["PolicyTopicEvidence"] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="PolicyTopicEvidence", + ) + constraints: MutableSequence["PolicyTopicConstraint"] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="PolicyTopicConstraint", + ) + + +class PolicyTopicEvidence(proto.Message): + r"""Additional information that explains a policy finding. + + 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: + website_list (google.ads.googleads.v24.common.types.PolicyTopicEvidence.WebsiteList): + List of websites linked with this resource. + + This field is a member of `oneof`_ ``value``. + text_list (google.ads.googleads.v24.common.types.PolicyTopicEvidence.TextList): + List of evidence found in the text of a + resource. + + This field is a member of `oneof`_ ``value``. + language_code (str): + The language the resource was detected to be + written in. This is an IETF language tag such as + "en-US". + + This field is a member of `oneof`_ ``value``. + destination_text_list (google.ads.googleads.v24.common.types.PolicyTopicEvidence.DestinationTextList): + The text in the destination of the resource + that is causing a policy finding. + + This field is a member of `oneof`_ ``value``. + destination_mismatch (google.ads.googleads.v24.common.types.PolicyTopicEvidence.DestinationMismatch): + Mismatch between the destinations of a + resource's URLs. + + This field is a member of `oneof`_ ``value``. + destination_not_working (google.ads.googleads.v24.common.types.PolicyTopicEvidence.DestinationNotWorking): + Details when the destination is returning an + HTTP error code or isn't functional in all + locations for commonly used devices. + + This field is a member of `oneof`_ ``value``. + """ + + class TextList(proto.Message): + r"""A list of fragments of text that violated a policy. + + Attributes: + texts (MutableSequence[str]): + The fragments of text from the resource that + caused the policy finding. + """ + + texts: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + + class WebsiteList(proto.Message): + r"""A list of websites that caused a policy finding. Used for + ONE_WEBSITE_PER_AD_GROUP policy topic, for example. In case there + are more than five websites, only the top five (those that appear in + resources the most) will be listed here. + + Attributes: + websites (MutableSequence[str]): + Websites that caused the policy finding. + """ + + websites: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + + class DestinationTextList(proto.Message): + r"""A list of strings found in a destination page that caused a + policy finding. + + Attributes: + destination_texts (MutableSequence[str]): + List of text found in the resource's + destination page. + """ + + destination_texts: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + + class DestinationMismatch(proto.Message): + r"""Evidence of mismatches between the URLs of a resource. + + Attributes: + url_types (MutableSequence[google.ads.googleads.v24.enums.types.PolicyTopicEvidenceDestinationMismatchUrlTypeEnum.PolicyTopicEvidenceDestinationMismatchUrlType]): + The set of URLs that did not match each + other. + """ + + url_types: MutableSequence[ + policy_topic_evidence_destination_mismatch_url_type.PolicyTopicEvidenceDestinationMismatchUrlTypeEnum.PolicyTopicEvidenceDestinationMismatchUrlType + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum=policy_topic_evidence_destination_mismatch_url_type.PolicyTopicEvidenceDestinationMismatchUrlTypeEnum.PolicyTopicEvidenceDestinationMismatchUrlType, + ) + + class DestinationNotWorking(proto.Message): + r"""Evidence details when the destination is returning an HTTP + error code or isn't functional in all locations for commonly + used devices. + + 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: + expanded_url (str): + The full URL that didn't work. + + This field is a member of `oneof`_ ``_expanded_url``. + device (google.ads.googleads.v24.enums.types.PolicyTopicEvidenceDestinationNotWorkingDeviceEnum.PolicyTopicEvidenceDestinationNotWorkingDevice): + The type of device that failed to load the + URL. + last_checked_date_time (str): + The time the URL was last checked. + The format is "YYYY-MM-DD HH:MM:SS". + Examples: "2018-03-05 09:15:00" or "2018-02-01 + 14:34:30". + + This field is a member of `oneof`_ ``_last_checked_date_time``. + dns_error_type (google.ads.googleads.v24.enums.types.PolicyTopicEvidenceDestinationNotWorkingDnsErrorTypeEnum.PolicyTopicEvidenceDestinationNotWorkingDnsErrorType): + The type of DNS error. + + This field is a member of `oneof`_ ``reason``. + http_error_code (int): + The HTTP error code. + + This field is a member of `oneof`_ ``reason``. + """ + + expanded_url: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + device: ( + policy_topic_evidence_destination_not_working_device.PolicyTopicEvidenceDestinationNotWorkingDeviceEnum.PolicyTopicEvidenceDestinationNotWorkingDevice + ) = proto.Field( + proto.ENUM, + number=4, + enum=policy_topic_evidence_destination_not_working_device.PolicyTopicEvidenceDestinationNotWorkingDeviceEnum.PolicyTopicEvidenceDestinationNotWorkingDevice, + ) + last_checked_date_time: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + dns_error_type: ( + policy_topic_evidence_destination_not_working_dns_error_type.PolicyTopicEvidenceDestinationNotWorkingDnsErrorTypeEnum.PolicyTopicEvidenceDestinationNotWorkingDnsErrorType + ) = proto.Field( + proto.ENUM, + number=1, + oneof="reason", + enum=policy_topic_evidence_destination_not_working_dns_error_type.PolicyTopicEvidenceDestinationNotWorkingDnsErrorTypeEnum.PolicyTopicEvidenceDestinationNotWorkingDnsErrorType, + ) + http_error_code: int = proto.Field( + proto.INT64, + number=6, + oneof="reason", + ) + + website_list: WebsiteList = proto.Field( + proto.MESSAGE, + number=3, + oneof="value", + message=WebsiteList, + ) + text_list: TextList = proto.Field( + proto.MESSAGE, + number=4, + oneof="value", + message=TextList, + ) + language_code: str = proto.Field( + proto.STRING, + number=9, + oneof="value", + ) + destination_text_list: DestinationTextList = proto.Field( + proto.MESSAGE, + number=6, + oneof="value", + message=DestinationTextList, + ) + destination_mismatch: DestinationMismatch = proto.Field( + proto.MESSAGE, + number=7, + oneof="value", + message=DestinationMismatch, + ) + destination_not_working: DestinationNotWorking = proto.Field( + proto.MESSAGE, + number=8, + oneof="value", + message=DestinationNotWorking, + ) + + +class PolicyTopicConstraint(proto.Message): + r"""Describes the effect on serving that a policy topic entry + will have. + + 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: + country_constraint_list (google.ads.googleads.v24.common.types.PolicyTopicConstraint.CountryConstraintList): + Countries where the resource cannot serve. + + This field is a member of `oneof`_ ``value``. + reseller_constraint (google.ads.googleads.v24.common.types.PolicyTopicConstraint.ResellerConstraint): + Reseller constraint. + + This field is a member of `oneof`_ ``value``. + certificate_missing_in_country_list (google.ads.googleads.v24.common.types.PolicyTopicConstraint.CountryConstraintList): + Countries where a certificate is required for + serving. + + This field is a member of `oneof`_ ``value``. + certificate_domain_mismatch_in_country_list (google.ads.googleads.v24.common.types.PolicyTopicConstraint.CountryConstraintList): + Countries where the resource's domain is not + covered by the certificates associated with it. + + This field is a member of `oneof`_ ``value``. + """ + + class CountryConstraintList(proto.Message): + r"""A list of countries where a resource's serving is + constrained. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + total_targeted_countries (int): + Total number of countries targeted by the + resource. + + This field is a member of `oneof`_ ``_total_targeted_countries``. + countries (MutableSequence[google.ads.googleads.v24.common.types.PolicyTopicConstraint.CountryConstraint]): + Countries in which serving is restricted. + """ + + total_targeted_countries: int = proto.Field( + proto.INT32, + number=3, + optional=True, + ) + countries: MutableSequence[ + "PolicyTopicConstraint.CountryConstraint" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="PolicyTopicConstraint.CountryConstraint", + ) + + class ResellerConstraint(proto.Message): + r"""Indicates that a policy topic was constrained due to + disapproval of the website for reseller purposes. + + """ + + class CountryConstraint(proto.Message): + r"""Indicates that a resource's ability to serve in a particular + country is constrained. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + country_criterion (str): + Geo target constant resource name of the + country in which serving is constrained. + + This field is a member of `oneof`_ ``_country_criterion``. + """ + + country_criterion: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + country_constraint_list: CountryConstraintList = proto.Field( + proto.MESSAGE, + number=1, + oneof="value", + message=CountryConstraintList, + ) + reseller_constraint: ResellerConstraint = proto.Field( + proto.MESSAGE, + number=2, + oneof="value", + message=ResellerConstraint, + ) + certificate_missing_in_country_list: CountryConstraintList = proto.Field( + proto.MESSAGE, + number=3, + oneof="value", + message=CountryConstraintList, + ) + certificate_domain_mismatch_in_country_list: CountryConstraintList = ( + proto.Field( + proto.MESSAGE, + number=4, + oneof="value", + message=CountryConstraintList, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/policy_summary.py b/google/ads/googleads/v24/common/types/policy_summary.py new file mode 100644 index 000000000..25b8bc968 --- /dev/null +++ b/google/ads/googleads/v24/common/types/policy_summary.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import policy +from google.ads.googleads.v24.enums.types import policy_approval_status +from google.ads.googleads.v24.enums.types import policy_review_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "PolicySummary", + }, +) + + +class PolicySummary(proto.Message): + r"""Contains policy summary information. + + Attributes: + policy_topic_entries (MutableSequence[google.ads.googleads.v24.common.types.PolicyTopicEntry]): + The list of policy findings. + review_status (google.ads.googleads.v24.enums.types.PolicyReviewStatusEnum.PolicyReviewStatus): + Where in the review process the resource is. + approval_status (google.ads.googleads.v24.enums.types.PolicyApprovalStatusEnum.PolicyApprovalStatus): + The overall approval status, which is + calculated based on the status of its individual + policy topic entries. + """ + + policy_topic_entries: MutableSequence[policy.PolicyTopicEntry] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=policy.PolicyTopicEntry, + ) + ) + review_status: ( + policy_review_status.PolicyReviewStatusEnum.PolicyReviewStatus + ) = proto.Field( + proto.ENUM, + number=2, + enum=policy_review_status.PolicyReviewStatusEnum.PolicyReviewStatus, + ) + approval_status: ( + policy_approval_status.PolicyApprovalStatusEnum.PolicyApprovalStatus + ) = proto.Field( + proto.ENUM, + number=3, + enum=policy_approval_status.PolicyApprovalStatusEnum.PolicyApprovalStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/real_time_bidding_setting.py b/google/ads/googleads/v24/common/types/real_time_bidding_setting.py new file mode 100644 index 000000000..775ce7323 --- /dev/null +++ b/google/ads/googleads/v24/common/types/real_time_bidding_setting.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "RealTimeBiddingSetting", + }, +) + + +class RealTimeBiddingSetting(proto.Message): + r"""Settings for Real-Time Bidding, a feature only available for + campaigns targeting the Ad Exchange network. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + opt_in (bool): + Whether the campaign is opted in to real-time + bidding. + + This field is a member of `oneof`_ ``_opt_in``. + """ + + opt_in: bool = proto.Field( + proto.BOOL, + number=2, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/segments.py b/google/ads/googleads/v24/common/types/segments.py new file mode 100644 index 000000000..fb38cc2ff --- /dev/null +++ b/google/ads/googleads/v24/common/types/segments.py @@ -0,0 +1,1704 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.enums.types import ( + ad_destination_type as gage_ad_destination_type, +) +from google.ads.googleads.v24.enums.types import ( + ad_format_type as gage_ad_format_type, +) +from google.ads.googleads.v24.enums.types import ( + ad_network_type as gage_ad_network_type, +) +from google.ads.googleads.v24.enums.types import ( + ad_sub_network_type as gage_ad_sub_network_type, +) +from google.ads.googleads.v24.enums.types import age_range_type +from google.ads.googleads.v24.enums.types import ( + budget_campaign_association_status as gage_budget_campaign_association_status, +) +from google.ads.googleads.v24.enums.types import click_type as gage_click_type +from google.ads.googleads.v24.enums.types import ( + conversion_action_category as gage_conversion_action_category, +) +from google.ads.googleads.v24.enums.types import ( + conversion_attribution_event_type as gage_conversion_attribution_event_type, +) +from google.ads.googleads.v24.enums.types import ( + conversion_lag_bucket as gage_conversion_lag_bucket, +) +from google.ads.googleads.v24.enums.types import ( + conversion_or_adjustment_lag_bucket as gage_conversion_or_adjustment_lag_bucket, +) +from google.ads.googleads.v24.enums.types import ( + conversion_value_rule_primary_dimension as gage_conversion_value_rule_primary_dimension, +) +from google.ads.googleads.v24.enums.types import ( + converting_user_prior_engagement_type_and_ltv_bucket, +) +from google.ads.googleads.v24.enums.types import day_of_week as gage_day_of_week +from google.ads.googleads.v24.enums.types import device as gage_device +from google.ads.googleads.v24.enums.types import ( + external_conversion_source as gage_external_conversion_source, +) +from google.ads.googleads.v24.enums.types import gender_type +from google.ads.googleads.v24.enums.types import ( + hotel_date_selection_type as gage_hotel_date_selection_type, +) +from google.ads.googleads.v24.enums.types import ( + hotel_price_bucket as gage_hotel_price_bucket, +) +from google.ads.googleads.v24.enums.types import ( + hotel_rate_type as gage_hotel_rate_type, +) +from google.ads.googleads.v24.enums.types import ( + landing_page_source as gage_landing_page_source, +) +from google.ads.googleads.v24.enums.types import match_type as gage_match_type +from google.ads.googleads.v24.enums.types import ( + month_of_year as gage_month_of_year, +) +from google.ads.googleads.v24.enums.types import ( + product_channel as gage_product_channel, +) +from google.ads.googleads.v24.enums.types import ( + product_channel_exclusivity as gage_product_channel_exclusivity, +) +from google.ads.googleads.v24.enums.types import ( + product_condition as gage_product_condition, +) +from google.ads.googleads.v24.enums.types import ( + recommendation_type as gage_recommendation_type, +) +from google.ads.googleads.v24.enums.types import ( + search_engine_results_page_type as gage_search_engine_results_page_type, +) +from google.ads.googleads.v24.enums.types import ( + search_term_match_source as gage_search_term_match_source, +) +from google.ads.googleads.v24.enums.types import ( + search_term_match_type as gage_search_term_match_type, +) +from google.ads.googleads.v24.enums.types import ( + search_term_targeting_status as gage_search_term_targeting_status, +) +from google.ads.googleads.v24.enums.types import ( + sk_ad_network_ad_event_type as gage_sk_ad_network_ad_event_type, +) +from google.ads.googleads.v24.enums.types import ( + sk_ad_network_attribution_credit as gage_sk_ad_network_attribution_credit, +) +from google.ads.googleads.v24.enums.types import ( + sk_ad_network_coarse_conversion_value as gage_sk_ad_network_coarse_conversion_value, +) +from google.ads.googleads.v24.enums.types import ( + sk_ad_network_source_type as gage_sk_ad_network_source_type, +) +from google.ads.googleads.v24.enums.types import ( + sk_ad_network_user_type as gage_sk_ad_network_user_type, +) +from google.ads.googleads.v24.enums.types import slot as gage_slot +from google.ads.googleads.v24.enums.types import vertical_ads_item_vertical_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "Segments", + "Keyword", + "BudgetCampaignAssociationStatus", + "AssetInteractionTarget", + "SkAdNetworkSourceApp", + }, +) + + +class Segments(proto.Message): + r"""Segment only fields. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + activity_account_id (int): + Activity account ID. + + This field is a member of `oneof`_ ``_activity_account_id``. + activity_city (str): + The city where the travel activity is + available. + + This field is a member of `oneof`_ ``_activity_city``. + activity_country (str): + The country where the travel activity is + available. + + This field is a member of `oneof`_ ``_activity_country``. + activity_rating (int): + Activity rating. + + This field is a member of `oneof`_ ``_activity_rating``. + activity_state (str): + The state where the travel activity is + available. + + This field is a member of `oneof`_ ``_activity_state``. + external_activity_id (str): + Advertiser supplied activity ID. + + This field is a member of `oneof`_ ``_external_activity_id``. + ad_destination_type (google.ads.googleads.v24.enums.types.AdDestinationTypeEnum.AdDestinationType): + Ad Destination type. + ad_format_type (google.ads.googleads.v24.enums.types.AdFormatTypeEnum.AdFormatType): + Ad Format type. + ad_network_type (google.ads.googleads.v24.enums.types.AdNetworkTypeEnum.AdNetworkType): + Ad network type. + ad_group (str): + Resource name of the ad group. + + This field is a member of `oneof`_ ``_ad_group``. + ad_sub_network_type (google.ads.googleads.v24.enums.types.AdSubNetworkTypeEnum.AdSubNetworkType): + Ad sub network type. Currently only available for ads + running as part of DemandGen campaigns on YouTube and has to + always be selected together with ad_network_type. + asset_group (str): + Resource name of the asset group. + + This field is a member of `oneof`_ ``_asset_group``. + auction_insight_domain (str): + Domain (visible URL) of a participant in the + Auction Insights report. + + This field is a member of `oneof`_ ``_auction_insight_domain``. + budget_campaign_association_status (google.ads.googleads.v24.common.types.BudgetCampaignAssociationStatus): + Budget campaign association status. + campaign (str): + Resource name of the campaign. + + This field is a member of `oneof`_ ``_campaign``. + click_type (google.ads.googleads.v24.enums.types.ClickTypeEnum.ClickType): + Click type. + conversion_action (str): + Resource name of the conversion action. + + This field is a member of `oneof`_ ``_conversion_action``. + conversion_action_category (google.ads.googleads.v24.enums.types.ConversionActionCategoryEnum.ConversionActionCategory): + Conversion action category. + conversion_action_name (str): + Conversion action name. + + This field is a member of `oneof`_ ``_conversion_action_name``. + conversion_adjustment (bool): + This segments your conversion columns by the + original conversion and conversion value versus + the delta if conversions were adjusted. False + row has the data as originally stated; While + true row has the delta between data now and the + data as originally stated. Summing the two + together results post-adjustment data. + + This field is a member of `oneof`_ ``_conversion_adjustment``. + conversion_attribution_event_type (google.ads.googleads.v24.enums.types.ConversionAttributionEventTypeEnum.ConversionAttributionEventType): + Conversion attribution event type. + conversion_lag_bucket (google.ads.googleads.v24.enums.types.ConversionLagBucketEnum.ConversionLagBucket): + An enum value representing the number of days + between the impression and the conversion. + conversion_or_adjustment_lag_bucket (google.ads.googleads.v24.enums.types.ConversionOrAdjustmentLagBucketEnum.ConversionOrAdjustmentLagBucket): + An enum value representing the number of days + between the impression and the conversion or + between the impression and adjustments to the + conversion. + date (str): + Date to which metrics apply. + yyyy-MM-dd format, for example, 2018-04-17. + + This field is a member of `oneof`_ ``_date``. + day_of_week (google.ads.googleads.v24.enums.types.DayOfWeekEnum.DayOfWeek): + Day of the week, for example, MONDAY. + device (google.ads.googleads.v24.enums.types.DeviceEnum.Device): + Device to which metrics apply. + external_conversion_source (google.ads.googleads.v24.enums.types.ExternalConversionSourceEnum.ExternalConversionSource): + External conversion source. + geo_target_airport (str): + Resource name of the geo target constant that + represents an airport. + + This field is a member of `oneof`_ ``_geo_target_airport``. + geo_target_canton (str): + Resource name of the geo target constant that + represents a canton. + + This field is a member of `oneof`_ ``_geo_target_canton``. + geo_target_city (str): + Resource name of the geo target constant that + represents a city. + + This field is a member of `oneof`_ ``_geo_target_city``. + geo_target_country (str): + Resource name of the geo target constant that + represents a country. + + This field is a member of `oneof`_ ``_geo_target_country``. + geo_target_county (str): + Resource name of the geo target constant that + represents a county. + + This field is a member of `oneof`_ ``_geo_target_county``. + geo_target_district (str): + Resource name of the geo target constant that + represents a district. + + This field is a member of `oneof`_ ``_geo_target_district``. + geo_target_metro (str): + Resource name of the geo target constant that + represents a metro. + + This field is a member of `oneof`_ ``_geo_target_metro``. + geo_target_most_specific_location (str): + Resource name of the geo target constant that + represents the most specific location. + + This field is a member of `oneof`_ ``_geo_target_most_specific_location``. + geo_target_postal_code (str): + Resource name of the geo target constant that + represents a postal code. + + This field is a member of `oneof`_ ``_geo_target_postal_code``. + geo_target_province (str): + Resource name of the geo target constant that + represents a province. + + This field is a member of `oneof`_ ``_geo_target_province``. + geo_target_region (str): + Resource name of the geo target constant that + represents a region. + + This field is a member of `oneof`_ ``_geo_target_region``. + geo_target_state (str): + Resource name of the geo target constant that + represents a state. + + This field is a member of `oneof`_ ``_geo_target_state``. + hotel_booking_window_days (int): + Hotel booking window in days. + + This field is a member of `oneof`_ ``_hotel_booking_window_days``. + hotel_center_id (int): + Hotel center ID. + + This field is a member of `oneof`_ ``_hotel_center_id``. + hotel_check_in_date (str): + Hotel check-in date. Formatted as yyyy-MM-dd. + + This field is a member of `oneof`_ ``_hotel_check_in_date``. + hotel_check_in_day_of_week (google.ads.googleads.v24.enums.types.DayOfWeekEnum.DayOfWeek): + Hotel check-in day of week. + hotel_city (str): + Hotel city. + + This field is a member of `oneof`_ ``_hotel_city``. + hotel_class (int): + Hotel class. + + This field is a member of `oneof`_ ``_hotel_class``. + hotel_country (str): + Hotel country. + + This field is a member of `oneof`_ ``_hotel_country``. + hotel_date_selection_type (google.ads.googleads.v24.enums.types.HotelDateSelectionTypeEnum.HotelDateSelectionType): + Hotel date selection type. + hotel_length_of_stay (int): + Hotel length of stay. + + This field is a member of `oneof`_ ``_hotel_length_of_stay``. + hotel_rate_rule_id (str): + Hotel rate rule ID. + + This field is a member of `oneof`_ ``_hotel_rate_rule_id``. + hotel_rate_type (google.ads.googleads.v24.enums.types.HotelRateTypeEnum.HotelRateType): + Hotel rate type. + hotel_price_bucket (google.ads.googleads.v24.enums.types.HotelPriceBucketEnum.HotelPriceBucket): + Hotel price bucket. + hotel_state (str): + Hotel state. + + This field is a member of `oneof`_ ``_hotel_state``. + hour (int): + Hour of day as a number between 0 and 23, + inclusive. + + This field is a member of `oneof`_ ``_hour``. + interaction_on_this_extension (bool): + Only used with feed item metrics. + Indicates whether the interaction metrics + occurred on the feed item itself or a different + extension or ad unit. + + This field is a member of `oneof`_ ``_interaction_on_this_extension``. + keyword (google.ads.googleads.v24.common.types.Keyword): + Keyword criterion. + landing_page_source (google.ads.googleads.v24.enums.types.LandingPageSourceEnum.LandingPageSource): + The source of a landing page in the landing + page report. + month (str): + Month as represented by the date of the first + day of a month. Formatted as yyyy-MM-dd. + + This field is a member of `oneof`_ ``_month``. + month_of_year (google.ads.googleads.v24.enums.types.MonthOfYearEnum.MonthOfYear): + Month of the year, for example, January. + partner_hotel_id (str): + Partner hotel ID. + + This field is a member of `oneof`_ ``_partner_hotel_id``. + product_aggregator_id (int): + Aggregator ID of the product. + + This field is a member of `oneof`_ ``_product_aggregator_id``. + product_category_level1 (str): + Category (level 1) of the product. + + This field is a member of `oneof`_ ``_product_category_level1``. + product_category_level2 (str): + Category (level 2) of the product. + + This field is a member of `oneof`_ ``_product_category_level2``. + product_category_level3 (str): + Category (level 3) of the product. + + This field is a member of `oneof`_ ``_product_category_level3``. + product_category_level4 (str): + Category (level 4) of the product. + + This field is a member of `oneof`_ ``_product_category_level4``. + product_category_level5 (str): + Category (level 5) of the product. + + This field is a member of `oneof`_ ``_product_category_level5``. + product_brand (str): + Brand of the product. + + This field is a member of `oneof`_ ``_product_brand``. + product_channel (google.ads.googleads.v24.enums.types.ProductChannelEnum.ProductChannel): + Channel of the product. + product_channel_exclusivity (google.ads.googleads.v24.enums.types.ProductChannelExclusivityEnum.ProductChannelExclusivity): + Channel exclusivity of the product. + product_condition (google.ads.googleads.v24.enums.types.ProductConditionEnum.ProductCondition): + Condition of the product. + product_country (str): + Resource name of the geo target constant for + the country of sale of the product. + + This field is a member of `oneof`_ ``_product_country``. + product_custom_attribute0 (str): + Custom attribute 0 of the product. + + This field is a member of `oneof`_ ``_product_custom_attribute0``. + product_custom_attribute1 (str): + Custom attribute 1 of the product. + + This field is a member of `oneof`_ ``_product_custom_attribute1``. + product_custom_attribute2 (str): + Custom attribute 2 of the product. + + This field is a member of `oneof`_ ``_product_custom_attribute2``. + product_custom_attribute3 (str): + Custom attribute 3 of the product. + + This field is a member of `oneof`_ ``_product_custom_attribute3``. + product_custom_attribute4 (str): + Custom attribute 4 of the product. + + This field is a member of `oneof`_ ``_product_custom_attribute4``. + product_feed_label (str): + Feed label of the product. + + This field is a member of `oneof`_ ``_product_feed_label``. + product_item_id (str): + Item ID of the product. + + This field is a member of `oneof`_ ``_product_item_id``. + product_language (str): + Resource name of the language constant for + the language of the product. + + This field is a member of `oneof`_ ``_product_language``. + product_merchant_id (int): + Merchant ID of the product. + + This field is a member of `oneof`_ ``_product_merchant_id``. + product_sold_category_level1 (str): + Category (level 1) of the product sold. + + This field is a member of `oneof`_ ``_product_sold_category_level1``. + product_sold_category_level2 (str): + Category (level 2) of the product sold. + + This field is a member of `oneof`_ ``_product_sold_category_level2``. + product_sold_category_level3 (str): + Category (level 3) of the product sold. + + This field is a member of `oneof`_ ``_product_sold_category_level3``. + product_sold_category_level4 (str): + Category (level 4) of the product sold. + + This field is a member of `oneof`_ ``_product_sold_category_level4``. + product_sold_category_level5 (str): + Category (level 5) of the product sold. + + This field is a member of `oneof`_ ``_product_sold_category_level5``. + product_sold_brand (str): + Brand of the product sold. + + This field is a member of `oneof`_ ``_product_sold_brand``. + product_sold_condition (google.ads.googleads.v24.enums.types.ProductConditionEnum.ProductCondition): + Condition of the product sold. + product_sold_custom_attribute0 (str): + Custom attribute 0 of the product sold. + + This field is a member of `oneof`_ ``_product_sold_custom_attribute0``. + product_sold_custom_attribute1 (str): + Custom attribute 1 of the product sold. + + This field is a member of `oneof`_ ``_product_sold_custom_attribute1``. + product_sold_custom_attribute2 (str): + Custom attribute 2 of the product sold. + + This field is a member of `oneof`_ ``_product_sold_custom_attribute2``. + product_sold_custom_attribute3 (str): + Custom attribute 3 of the product sold. + + This field is a member of `oneof`_ ``_product_sold_custom_attribute3``. + product_sold_custom_attribute4 (str): + Custom attribute 4 of the product sold. + + This field is a member of `oneof`_ ``_product_sold_custom_attribute4``. + product_sold_item_id (str): + Item ID of the product sold. + + This field is a member of `oneof`_ ``_product_sold_item_id``. + product_sold_title (str): + Title of the product sold. + + This field is a member of `oneof`_ ``_product_sold_title``. + product_sold_type_l1 (str): + Type (level 1) of the product sold. + + This field is a member of `oneof`_ ``_product_sold_type_l1``. + product_sold_type_l2 (str): + Type (level 2) of the product sold. + + This field is a member of `oneof`_ ``_product_sold_type_l2``. + product_sold_type_l3 (str): + Type (level 3) of the product sold. + + This field is a member of `oneof`_ ``_product_sold_type_l3``. + product_sold_type_l4 (str): + Type (level 4) of the product sold. + + This field is a member of `oneof`_ ``_product_sold_type_l4``. + product_sold_type_l5 (str): + Type (level 5) of the product sold. + + This field is a member of `oneof`_ ``_product_sold_type_l5``. + product_store_id (str): + Store ID of the product. + + This field is a member of `oneof`_ ``_product_store_id``. + product_title (str): + Title of the product. + + This field is a member of `oneof`_ ``_product_title``. + product_type_l1 (str): + Type (level 1) of the product. + + This field is a member of `oneof`_ ``_product_type_l1``. + product_type_l2 (str): + Type (level 2) of the product. + + This field is a member of `oneof`_ ``_product_type_l2``. + product_type_l3 (str): + Type (level 3) of the product. + + This field is a member of `oneof`_ ``_product_type_l3``. + product_type_l4 (str): + Type (level 4) of the product. + + This field is a member of `oneof`_ ``_product_type_l4``. + product_type_l5 (str): + Type (level 5) of the product. + + This field is a member of `oneof`_ ``_product_type_l5``. + quarter (str): + Quarter as represented by the date of the + first day of a quarter. Uses the calendar year + for quarters, for example, the second quarter of + 2018 starts on 2018-04-01. Formatted as + yyyy-MM-dd. + + This field is a member of `oneof`_ ``_quarter``. + travel_destination_city (str): + The city the user is searching for at query + time. + + This field is a member of `oneof`_ ``_travel_destination_city``. + travel_destination_country (str): + The country the user is searching for at + query time. + + This field is a member of `oneof`_ ``_travel_destination_country``. + travel_destination_region (str): + The region the user is searching for at query + time. + + This field is a member of `oneof`_ ``_travel_destination_region``. + vertical_ads_event_participant_display_names (str): + The display names of participants in an event + listing, like performers, speakers, or teams. + + This field is a member of `oneof`_ ``_vertical_ads_event_participant_display_names``. + vertical_ads_hotel_class (int): + The class of the hotel. Generally in the + range of 1 to 5 stars, but fully customizable in + the hotel feed. + + This field is a member of `oneof`_ ``_vertical_ads_hotel_class``. + vertical_ads_listing (str): + The listing associated with a listing + impression, click or conversion. + + This field is a member of `oneof`_ ``_vertical_ads_listing``. + vertical_ads_listing_brand (str): + The brand associated with a specific listing + within a Vertical Ads context, for example, the + brand of a car rental, a vacation home, or an + event. + + This field is a member of `oneof`_ ``_vertical_ads_listing_brand``. + vertical_ads_listing_city (str): + The city where the vertical ads listing is + located. + + This field is a member of `oneof`_ ``_vertical_ads_listing_city``. + vertical_ads_listing_country (str): + The country where the vertical ads listing is + located. + + This field is a member of `oneof`_ ``_vertical_ads_listing_country``. + vertical_ads_listing_region (str): + The region where the vertical ads listing is + located. + + This field is a member of `oneof`_ ``_vertical_ads_listing_region``. + vertical_ads_partner_account (int): + A specific partner account within a Partner + Center (for example, Hotel Center) that supplies + inventory feed data for Vertical Ads. + + This field is a member of `oneof`_ ``_vertical_ads_partner_account``. + vertical_ads_vertical (google.ads.googleads.v24.enums.types.VerticalAdsItemVerticalTypeEnum.VerticalAdsItemVerticalType): + Type of vertical ad, such as Vacation + Rentals, Car Rentals, or Events, used to + categorize and segment data in the context of + Vertical Ads. + + This field is a member of `oneof`_ ``_vertical_ads_vertical``. + recommendation_type (google.ads.googleads.v24.enums.types.RecommendationTypeEnum.RecommendationType): + Recommendation type. + search_engine_results_page_type (google.ads.googleads.v24.enums.types.SearchEngineResultsPageTypeEnum.SearchEngineResultsPageType): + Type of the search engine results page. + search_subcategory (str): + A search term subcategory. An empty string + denotes the catch-all subcategory for search + terms that didn't fit into another subcategory. + + This field is a member of `oneof`_ ``_search_subcategory``. + search_term (str): + A search term. + + This field is a member of `oneof`_ ``_search_term``. + search_term_match_type (google.ads.googleads.v24.enums.types.SearchTermMatchTypeEnum.SearchTermMatchType): + Match type of the keyword that triggered the ad. This + segment is for use with keyword_view. For other resources, + use match_type. While match_type is filtered to Broad, + Exact, Phrase and Ai Max, search_term_match_type includes + variants like Near Exact and Near Phrase. + match_type (google.ads.googleads.v24.enums.types.MatchTypeEnum.MatchType): + The match type of the keyword that triggered the ad. This + segment is for use with keyword_view. For other resources, + use search_term_match_type. While match_type is filtered to + Broad, Exact, Phrase and Ai Max, search_term_match_type + includes variants like Near Exact, Near Phrase. + slot (google.ads.googleads.v24.enums.types.SlotEnum.Slot): + Position of the ad. + conversion_value_rule_primary_dimension (google.ads.googleads.v24.enums.types.ConversionValueRulePrimaryDimensionEnum.ConversionValueRulePrimaryDimension): + Primary dimension of applied conversion value rules. + NO_RULE_APPLIED shows the total recorded value of + conversions that do not have a value rule applied. ORIGINAL + shows the original value of conversions to which a value + rule has been applied. GEO_LOCATION, DEVICE, AUDIENCE, + ITINERARY show the net adjustment after value rules were + applied. + webpage (str): + Resource name of the ad group criterion that + represents webpage criterion. + + This field is a member of `oneof`_ ``_webpage``. + week (str): + Week as defined as Monday through Sunday, and + represented by the date of Monday. Formatted as + yyyy-MM-dd. + + This field is a member of `oneof`_ ``_week``. + year (int): + Year, formatted as yyyy. + + This field is a member of `oneof`_ ``_year``. + sk_ad_network_fine_conversion_value (int): + iOS Store Kit Ad Network conversion value. + Null value means this segment is not applicable, + for example, non-iOS campaign. + + This field is a member of `oneof`_ ``_sk_ad_network_fine_conversion_value``. + sk_ad_network_redistributed_fine_conversion_value (int): + iOS Store Kit Ad Network redistributed fine + conversion value. + Google uses modeling on observed conversion + values(obtained from Apple) to calculate + conversions from SKAN postbacks where NULLs are + returned. This column represents the sum of the + modeled conversion values and the observed + conversion values. See + https://support.google.com/google-ads/answer/14892597 + to lean more. + + This field is a member of `oneof`_ ``_sk_ad_network_redistributed_fine_conversion_value``. + sk_ad_network_user_type (google.ads.googleads.v24.enums.types.SkAdNetworkUserTypeEnum.SkAdNetworkUserType): + iOS Store Kit Ad Network user type. + sk_ad_network_ad_event_type (google.ads.googleads.v24.enums.types.SkAdNetworkAdEventTypeEnum.SkAdNetworkAdEventType): + iOS Store Kit Ad Network ad event type. + sk_ad_network_source_app (google.ads.googleads.v24.common.types.SkAdNetworkSourceApp): + App where the ad that drove the iOS Store Kit + Ad Network install was shown. Null value means + this segment is not applicable, for example, + non-iOS campaign, or was not present in any + postbacks sent by Apple. + + This field is a member of `oneof`_ ``_sk_ad_network_source_app``. + sk_ad_network_attribution_credit (google.ads.googleads.v24.enums.types.SkAdNetworkAttributionCreditEnum.SkAdNetworkAttributionCredit): + iOS Store Kit Ad Network attribution credit + sk_ad_network_coarse_conversion_value (google.ads.googleads.v24.enums.types.SkAdNetworkCoarseConversionValueEnum.SkAdNetworkCoarseConversionValue): + iOS Store Kit Ad Network coarse conversion + value. + sk_ad_network_source_domain (str): + Website where the ad that drove the iOS Store + Kit Ad Network install was shown. Null value + means this segment is not applicable, for + example, non-iOS campaign, or was not present in + any postbacks sent by Apple. + + This field is a member of `oneof`_ ``_sk_ad_network_source_domain``. + sk_ad_network_source_type (google.ads.googleads.v24.enums.types.SkAdNetworkSourceTypeEnum.SkAdNetworkSourceType): + The source type where the ad that drove the + iOS Store Kit Ad Network install was shown. Null + value means this segment is not applicable, for + example, non-iOS campaign, or neither source + domain nor source app were present in any + postbacks sent by Apple. + sk_ad_network_postback_sequence_index (int): + iOS Store Kit Ad Network postback sequence + index. + + This field is a member of `oneof`_ ``_sk_ad_network_postback_sequence_index``. + sk_ad_network_version (str): + The version of the SKAdNetwork API used. + + This field is a member of `oneof`_ ``_sk_ad_network_version``. + asset_interaction_target (google.ads.googleads.v24.common.types.AssetInteractionTarget): + Only used with CustomerAsset, CampaignAsset and AdGroupAsset + metrics. Indicates whether the interaction metrics occurred + on the asset itself or a different asset or ad unit. + Interactions (for example, clicks) are counted across all + the parts of the served ad (for example, Ad itself and other + components like Sitelinks) when they are served together. + When interaction_on_this_asset is true, it means the + interactions are on this specific asset and when + interaction_on_this_asset is false, it means the + interactions is not on this specific asset but on other + parts of the served ad this asset is served with. + + This field is a member of `oneof`_ ``_asset_interaction_target``. + new_versus_returning_customers (google.ads.googleads.v24.enums.types.ConvertingUserPriorEngagementTypeAndLtvBucketEnum.ConvertingUserPriorEngagementTypeAndLtvBucket): + This is for segmenting conversions by whether + the user is a new customer or a returning + customer. This segmentation is typically used to + measure the impact of customer acquisition goal. + adjusted_age_range (google.ads.googleads.v24.enums.types.AgeRangeTypeEnum.AgeRangeType): + Adjusted age range. This is the age range of the user after + applying modeling to get more accurate age and gender + information. Currently, both adjusted_age_range and + adjusted_gender need to be selected together to get valid + reach stats. These segmentations are only available for + allowlisted customers. + adjusted_gender (google.ads.googleads.v24.enums.types.GenderTypeEnum.GenderType): + Adjusted gender. This is the gender of the user after + applying modeling to get more accurate age and gender + information. Currently, both adjusted_age_range and + adjusted_gender need to be selected together to get valid + reach stats. These segmentations are only available for + allowlisted customers. + search_term_match_source (google.ads.googleads.v24.enums.types.SearchTermMatchSourceEnum.SearchTermMatchSource): + Specifies the source for how the search term + was matched, which reveals the type of ad + campaign responsible. Use this to distinguish + between automated campaigns (like AI Max, + Dynamic Search Ads) and keyword-based campaigns + (Standard). + search_term_targeting_status (google.ads.googleads.v24.enums.types.SearchTermTargetingStatusEnum.SearchTermTargetingStatus): + Indicates whether the search term is + currently one of your targeted or excluded + keywords. + ad_using_product_data (bool): + Indicates whether an ad is using product data + from a Google Merchant Center feed. This segment + is only available for PMax campaigns and will + not return data when any other campaign type is + selected. + + This field is a member of `oneof`_ ``_ad_using_product_data``. + ad_using_video (bool): + Indicates whether an ad is using a video + asset. This segment is only available for PMax + campaigns and will not return data when any + other campaign type is selected. + + This field is a member of `oneof`_ ``_ad_using_video``. + """ + + activity_account_id: int = proto.Field( + proto.INT64, + number=148, + optional=True, + ) + activity_city: str = proto.Field( + proto.STRING, + number=185, + optional=True, + ) + activity_country: str = proto.Field( + proto.STRING, + number=186, + optional=True, + ) + activity_rating: int = proto.Field( + proto.INT64, + number=149, + optional=True, + ) + activity_state: str = proto.Field( + proto.STRING, + number=187, + optional=True, + ) + external_activity_id: str = proto.Field( + proto.STRING, + number=150, + optional=True, + ) + ad_destination_type: ( + gage_ad_destination_type.AdDestinationTypeEnum.AdDestinationType + ) = proto.Field( + proto.ENUM, + number=136, + enum=gage_ad_destination_type.AdDestinationTypeEnum.AdDestinationType, + ) + ad_format_type: gage_ad_format_type.AdFormatTypeEnum.AdFormatType = ( + proto.Field( + proto.ENUM, + number=191, + enum=gage_ad_format_type.AdFormatTypeEnum.AdFormatType, + ) + ) + ad_network_type: gage_ad_network_type.AdNetworkTypeEnum.AdNetworkType = ( + proto.Field( + proto.ENUM, + number=3, + enum=gage_ad_network_type.AdNetworkTypeEnum.AdNetworkType, + ) + ) + ad_group: str = proto.Field( + proto.STRING, + number=158, + optional=True, + ) + ad_sub_network_type: ( + gage_ad_sub_network_type.AdSubNetworkTypeEnum.AdSubNetworkType + ) = proto.Field( + proto.ENUM, + number=204, + enum=gage_ad_sub_network_type.AdSubNetworkTypeEnum.AdSubNetworkType, + ) + asset_group: str = proto.Field( + proto.STRING, + number=159, + optional=True, + ) + auction_insight_domain: str = proto.Field( + proto.STRING, + number=145, + optional=True, + ) + budget_campaign_association_status: "BudgetCampaignAssociationStatus" = ( + proto.Field( + proto.MESSAGE, + number=134, + message="BudgetCampaignAssociationStatus", + ) + ) + campaign: str = proto.Field( + proto.STRING, + number=157, + optional=True, + ) + click_type: gage_click_type.ClickTypeEnum.ClickType = proto.Field( + proto.ENUM, + number=26, + enum=gage_click_type.ClickTypeEnum.ClickType, + ) + conversion_action: str = proto.Field( + proto.STRING, + number=113, + optional=True, + ) + conversion_action_category: ( + gage_conversion_action_category.ConversionActionCategoryEnum.ConversionActionCategory + ) = proto.Field( + proto.ENUM, + number=53, + enum=gage_conversion_action_category.ConversionActionCategoryEnum.ConversionActionCategory, + ) + conversion_action_name: str = proto.Field( + proto.STRING, + number=114, + optional=True, + ) + conversion_adjustment: bool = proto.Field( + proto.BOOL, + number=115, + optional=True, + ) + conversion_attribution_event_type: ( + gage_conversion_attribution_event_type.ConversionAttributionEventTypeEnum.ConversionAttributionEventType + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_conversion_attribution_event_type.ConversionAttributionEventTypeEnum.ConversionAttributionEventType, + ) + conversion_lag_bucket: ( + gage_conversion_lag_bucket.ConversionLagBucketEnum.ConversionLagBucket + ) = proto.Field( + proto.ENUM, + number=50, + enum=gage_conversion_lag_bucket.ConversionLagBucketEnum.ConversionLagBucket, + ) + conversion_or_adjustment_lag_bucket: ( + gage_conversion_or_adjustment_lag_bucket.ConversionOrAdjustmentLagBucketEnum.ConversionOrAdjustmentLagBucket + ) = proto.Field( + proto.ENUM, + number=51, + enum=gage_conversion_or_adjustment_lag_bucket.ConversionOrAdjustmentLagBucketEnum.ConversionOrAdjustmentLagBucket, + ) + date: str = proto.Field( + proto.STRING, + number=79, + optional=True, + ) + day_of_week: gage_day_of_week.DayOfWeekEnum.DayOfWeek = proto.Field( + proto.ENUM, + number=5, + enum=gage_day_of_week.DayOfWeekEnum.DayOfWeek, + ) + device: gage_device.DeviceEnum.Device = proto.Field( + proto.ENUM, + number=1, + enum=gage_device.DeviceEnum.Device, + ) + external_conversion_source: ( + gage_external_conversion_source.ExternalConversionSourceEnum.ExternalConversionSource + ) = proto.Field( + proto.ENUM, + number=55, + enum=gage_external_conversion_source.ExternalConversionSourceEnum.ExternalConversionSource, + ) + geo_target_airport: str = proto.Field( + proto.STRING, + number=116, + optional=True, + ) + geo_target_canton: str = proto.Field( + proto.STRING, + number=117, + optional=True, + ) + geo_target_city: str = proto.Field( + proto.STRING, + number=118, + optional=True, + ) + geo_target_country: str = proto.Field( + proto.STRING, + number=119, + optional=True, + ) + geo_target_county: str = proto.Field( + proto.STRING, + number=120, + optional=True, + ) + geo_target_district: str = proto.Field( + proto.STRING, + number=121, + optional=True, + ) + geo_target_metro: str = proto.Field( + proto.STRING, + number=122, + optional=True, + ) + geo_target_most_specific_location: str = proto.Field( + proto.STRING, + number=123, + optional=True, + ) + geo_target_postal_code: str = proto.Field( + proto.STRING, + number=124, + optional=True, + ) + geo_target_province: str = proto.Field( + proto.STRING, + number=125, + optional=True, + ) + geo_target_region: str = proto.Field( + proto.STRING, + number=126, + optional=True, + ) + geo_target_state: str = proto.Field( + proto.STRING, + number=127, + optional=True, + ) + hotel_booking_window_days: int = proto.Field( + proto.INT64, + number=135, + optional=True, + ) + hotel_center_id: int = proto.Field( + proto.INT64, + number=80, + optional=True, + ) + hotel_check_in_date: str = proto.Field( + proto.STRING, + number=81, + optional=True, + ) + hotel_check_in_day_of_week: gage_day_of_week.DayOfWeekEnum.DayOfWeek = ( + proto.Field( + proto.ENUM, + number=9, + enum=gage_day_of_week.DayOfWeekEnum.DayOfWeek, + ) + ) + hotel_city: str = proto.Field( + proto.STRING, + number=82, + optional=True, + ) + hotel_class: int = proto.Field( + proto.INT32, + number=83, + optional=True, + ) + hotel_country: str = proto.Field( + proto.STRING, + number=84, + optional=True, + ) + hotel_date_selection_type: ( + gage_hotel_date_selection_type.HotelDateSelectionTypeEnum.HotelDateSelectionType + ) = proto.Field( + proto.ENUM, + number=13, + enum=gage_hotel_date_selection_type.HotelDateSelectionTypeEnum.HotelDateSelectionType, + ) + hotel_length_of_stay: int = proto.Field( + proto.INT32, + number=85, + optional=True, + ) + hotel_rate_rule_id: str = proto.Field( + proto.STRING, + number=86, + optional=True, + ) + hotel_rate_type: gage_hotel_rate_type.HotelRateTypeEnum.HotelRateType = ( + proto.Field( + proto.ENUM, + number=74, + enum=gage_hotel_rate_type.HotelRateTypeEnum.HotelRateType, + ) + ) + hotel_price_bucket: ( + gage_hotel_price_bucket.HotelPriceBucketEnum.HotelPriceBucket + ) = proto.Field( + proto.ENUM, + number=78, + enum=gage_hotel_price_bucket.HotelPriceBucketEnum.HotelPriceBucket, + ) + hotel_state: str = proto.Field( + proto.STRING, + number=87, + optional=True, + ) + hour: int = proto.Field( + proto.INT32, + number=88, + optional=True, + ) + interaction_on_this_extension: bool = proto.Field( + proto.BOOL, + number=89, + optional=True, + ) + keyword: "Keyword" = proto.Field( + proto.MESSAGE, + number=61, + message="Keyword", + ) + landing_page_source: ( + gage_landing_page_source.LandingPageSourceEnum.LandingPageSource + ) = proto.Field( + proto.ENUM, + number=200, + enum=gage_landing_page_source.LandingPageSourceEnum.LandingPageSource, + ) + month: str = proto.Field( + proto.STRING, + number=90, + optional=True, + ) + month_of_year: gage_month_of_year.MonthOfYearEnum.MonthOfYear = proto.Field( + proto.ENUM, + number=18, + enum=gage_month_of_year.MonthOfYearEnum.MonthOfYear, + ) + partner_hotel_id: str = proto.Field( + proto.STRING, + number=91, + optional=True, + ) + product_aggregator_id: int = proto.Field( + proto.INT64, + number=132, + optional=True, + ) + product_category_level1: str = proto.Field( + proto.STRING, + number=161, + optional=True, + ) + product_category_level2: str = proto.Field( + proto.STRING, + number=162, + optional=True, + ) + product_category_level3: str = proto.Field( + proto.STRING, + number=163, + optional=True, + ) + product_category_level4: str = proto.Field( + proto.STRING, + number=164, + optional=True, + ) + product_category_level5: str = proto.Field( + proto.STRING, + number=165, + optional=True, + ) + product_brand: str = proto.Field( + proto.STRING, + number=97, + optional=True, + ) + product_channel: gage_product_channel.ProductChannelEnum.ProductChannel = ( + proto.Field( + proto.ENUM, + number=30, + enum=gage_product_channel.ProductChannelEnum.ProductChannel, + ) + ) + product_channel_exclusivity: ( + gage_product_channel_exclusivity.ProductChannelExclusivityEnum.ProductChannelExclusivity + ) = proto.Field( + proto.ENUM, + number=31, + enum=gage_product_channel_exclusivity.ProductChannelExclusivityEnum.ProductChannelExclusivity, + ) + product_condition: ( + gage_product_condition.ProductConditionEnum.ProductCondition + ) = proto.Field( + proto.ENUM, + number=32, + enum=gage_product_condition.ProductConditionEnum.ProductCondition, + ) + product_country: str = proto.Field( + proto.STRING, + number=98, + optional=True, + ) + product_custom_attribute0: str = proto.Field( + proto.STRING, + number=99, + optional=True, + ) + product_custom_attribute1: str = proto.Field( + proto.STRING, + number=100, + optional=True, + ) + product_custom_attribute2: str = proto.Field( + proto.STRING, + number=101, + optional=True, + ) + product_custom_attribute3: str = proto.Field( + proto.STRING, + number=102, + optional=True, + ) + product_custom_attribute4: str = proto.Field( + proto.STRING, + number=103, + optional=True, + ) + product_feed_label: str = proto.Field( + proto.STRING, + number=147, + optional=True, + ) + product_item_id: str = proto.Field( + proto.STRING, + number=104, + optional=True, + ) + product_language: str = proto.Field( + proto.STRING, + number=105, + optional=True, + ) + product_merchant_id: int = proto.Field( + proto.INT64, + number=133, + optional=True, + ) + product_sold_category_level1: str = proto.Field( + proto.STRING, + number=214, + optional=True, + ) + product_sold_category_level2: str = proto.Field( + proto.STRING, + number=215, + optional=True, + ) + product_sold_category_level3: str = proto.Field( + proto.STRING, + number=216, + optional=True, + ) + product_sold_category_level4: str = proto.Field( + proto.STRING, + number=217, + optional=True, + ) + product_sold_category_level5: str = proto.Field( + proto.STRING, + number=218, + optional=True, + ) + product_sold_brand: str = proto.Field( + proto.STRING, + number=171, + optional=True, + ) + product_sold_condition: ( + gage_product_condition.ProductConditionEnum.ProductCondition + ) = proto.Field( + proto.ENUM, + number=172, + enum=gage_product_condition.ProductConditionEnum.ProductCondition, + ) + product_sold_custom_attribute0: str = proto.Field( + proto.STRING, + number=173, + optional=True, + ) + product_sold_custom_attribute1: str = proto.Field( + proto.STRING, + number=174, + optional=True, + ) + product_sold_custom_attribute2: str = proto.Field( + proto.STRING, + number=175, + optional=True, + ) + product_sold_custom_attribute3: str = proto.Field( + proto.STRING, + number=176, + optional=True, + ) + product_sold_custom_attribute4: str = proto.Field( + proto.STRING, + number=177, + optional=True, + ) + product_sold_item_id: str = proto.Field( + proto.STRING, + number=178, + optional=True, + ) + product_sold_title: str = proto.Field( + proto.STRING, + number=179, + optional=True, + ) + product_sold_type_l1: str = proto.Field( + proto.STRING, + number=180, + optional=True, + ) + product_sold_type_l2: str = proto.Field( + proto.STRING, + number=181, + optional=True, + ) + product_sold_type_l3: str = proto.Field( + proto.STRING, + number=182, + optional=True, + ) + product_sold_type_l4: str = proto.Field( + proto.STRING, + number=183, + optional=True, + ) + product_sold_type_l5: str = proto.Field( + proto.STRING, + number=184, + optional=True, + ) + product_store_id: str = proto.Field( + proto.STRING, + number=106, + optional=True, + ) + product_title: str = proto.Field( + proto.STRING, + number=107, + optional=True, + ) + product_type_l1: str = proto.Field( + proto.STRING, + number=108, + optional=True, + ) + product_type_l2: str = proto.Field( + proto.STRING, + number=109, + optional=True, + ) + product_type_l3: str = proto.Field( + proto.STRING, + number=110, + optional=True, + ) + product_type_l4: str = proto.Field( + proto.STRING, + number=111, + optional=True, + ) + product_type_l5: str = proto.Field( + proto.STRING, + number=112, + optional=True, + ) + quarter: str = proto.Field( + proto.STRING, + number=128, + optional=True, + ) + travel_destination_city: str = proto.Field( + proto.STRING, + number=193, + optional=True, + ) + travel_destination_country: str = proto.Field( + proto.STRING, + number=194, + optional=True, + ) + travel_destination_region: str = proto.Field( + proto.STRING, + number=195, + optional=True, + ) + vertical_ads_event_participant_display_names: str = proto.Field( + proto.STRING, + number=205, + optional=True, + ) + vertical_ads_hotel_class: int = proto.Field( + proto.INT64, + number=206, + optional=True, + ) + vertical_ads_listing: str = proto.Field( + proto.STRING, + number=207, + optional=True, + ) + vertical_ads_listing_brand: str = proto.Field( + proto.STRING, + number=208, + optional=True, + ) + vertical_ads_listing_city: str = proto.Field( + proto.STRING, + number=209, + optional=True, + ) + vertical_ads_listing_country: str = proto.Field( + proto.STRING, + number=210, + optional=True, + ) + vertical_ads_listing_region: str = proto.Field( + proto.STRING, + number=211, + optional=True, + ) + vertical_ads_partner_account: int = proto.Field( + proto.INT64, + number=212, + optional=True, + ) + vertical_ads_vertical: ( + vertical_ads_item_vertical_type.VerticalAdsItemVerticalTypeEnum.VerticalAdsItemVerticalType + ) = proto.Field( + proto.ENUM, + number=213, + optional=True, + enum=vertical_ads_item_vertical_type.VerticalAdsItemVerticalTypeEnum.VerticalAdsItemVerticalType, + ) + recommendation_type: ( + gage_recommendation_type.RecommendationTypeEnum.RecommendationType + ) = proto.Field( + proto.ENUM, + number=140, + enum=gage_recommendation_type.RecommendationTypeEnum.RecommendationType, + ) + search_engine_results_page_type: ( + gage_search_engine_results_page_type.SearchEngineResultsPageTypeEnum.SearchEngineResultsPageType + ) = proto.Field( + proto.ENUM, + number=70, + enum=gage_search_engine_results_page_type.SearchEngineResultsPageTypeEnum.SearchEngineResultsPageType, + ) + search_subcategory: str = proto.Field( + proto.STRING, + number=155, + optional=True, + ) + search_term: str = proto.Field( + proto.STRING, + number=156, + optional=True, + ) + search_term_match_type: ( + gage_search_term_match_type.SearchTermMatchTypeEnum.SearchTermMatchType + ) = proto.Field( + proto.ENUM, + number=22, + enum=gage_search_term_match_type.SearchTermMatchTypeEnum.SearchTermMatchType, + ) + match_type: gage_match_type.MatchTypeEnum.MatchType = proto.Field( + proto.ENUM, + number=199, + enum=gage_match_type.MatchTypeEnum.MatchType, + ) + slot: gage_slot.SlotEnum.Slot = proto.Field( + proto.ENUM, + number=23, + enum=gage_slot.SlotEnum.Slot, + ) + conversion_value_rule_primary_dimension: ( + gage_conversion_value_rule_primary_dimension.ConversionValueRulePrimaryDimensionEnum.ConversionValueRulePrimaryDimension + ) = proto.Field( + proto.ENUM, + number=138, + enum=gage_conversion_value_rule_primary_dimension.ConversionValueRulePrimaryDimensionEnum.ConversionValueRulePrimaryDimension, + ) + webpage: str = proto.Field( + proto.STRING, + number=129, + optional=True, + ) + week: str = proto.Field( + proto.STRING, + number=130, + optional=True, + ) + year: int = proto.Field( + proto.INT32, + number=131, + optional=True, + ) + sk_ad_network_fine_conversion_value: int = proto.Field( + proto.INT64, + number=137, + optional=True, + ) + sk_ad_network_redistributed_fine_conversion_value: int = proto.Field( + proto.INT64, + number=190, + optional=True, + ) + sk_ad_network_user_type: ( + gage_sk_ad_network_user_type.SkAdNetworkUserTypeEnum.SkAdNetworkUserType + ) = proto.Field( + proto.ENUM, + number=141, + enum=gage_sk_ad_network_user_type.SkAdNetworkUserTypeEnum.SkAdNetworkUserType, + ) + sk_ad_network_ad_event_type: ( + gage_sk_ad_network_ad_event_type.SkAdNetworkAdEventTypeEnum.SkAdNetworkAdEventType + ) = proto.Field( + proto.ENUM, + number=142, + enum=gage_sk_ad_network_ad_event_type.SkAdNetworkAdEventTypeEnum.SkAdNetworkAdEventType, + ) + sk_ad_network_source_app: "SkAdNetworkSourceApp" = proto.Field( + proto.MESSAGE, + number=143, + optional=True, + message="SkAdNetworkSourceApp", + ) + sk_ad_network_attribution_credit: ( + gage_sk_ad_network_attribution_credit.SkAdNetworkAttributionCreditEnum.SkAdNetworkAttributionCredit + ) = proto.Field( + proto.ENUM, + number=144, + enum=gage_sk_ad_network_attribution_credit.SkAdNetworkAttributionCreditEnum.SkAdNetworkAttributionCredit, + ) + sk_ad_network_coarse_conversion_value: ( + gage_sk_ad_network_coarse_conversion_value.SkAdNetworkCoarseConversionValueEnum.SkAdNetworkCoarseConversionValue + ) = proto.Field( + proto.ENUM, + number=151, + enum=gage_sk_ad_network_coarse_conversion_value.SkAdNetworkCoarseConversionValueEnum.SkAdNetworkCoarseConversionValue, + ) + sk_ad_network_source_domain: str = proto.Field( + proto.STRING, + number=152, + optional=True, + ) + sk_ad_network_source_type: ( + gage_sk_ad_network_source_type.SkAdNetworkSourceTypeEnum.SkAdNetworkSourceType + ) = proto.Field( + proto.ENUM, + number=153, + enum=gage_sk_ad_network_source_type.SkAdNetworkSourceTypeEnum.SkAdNetworkSourceType, + ) + sk_ad_network_postback_sequence_index: int = proto.Field( + proto.INT64, + number=154, + optional=True, + ) + sk_ad_network_version: str = proto.Field( + proto.STRING, + number=192, + optional=True, + ) + asset_interaction_target: "AssetInteractionTarget" = proto.Field( + proto.MESSAGE, + number=139, + optional=True, + message="AssetInteractionTarget", + ) + new_versus_returning_customers: ( + converting_user_prior_engagement_type_and_ltv_bucket.ConvertingUserPriorEngagementTypeAndLtvBucketEnum.ConvertingUserPriorEngagementTypeAndLtvBucket + ) = proto.Field( + proto.ENUM, + number=160, + enum=converting_user_prior_engagement_type_and_ltv_bucket.ConvertingUserPriorEngagementTypeAndLtvBucketEnum.ConvertingUserPriorEngagementTypeAndLtvBucket, + ) + adjusted_age_range: age_range_type.AgeRangeTypeEnum.AgeRangeType = ( + proto.Field( + proto.ENUM, + number=196, + enum=age_range_type.AgeRangeTypeEnum.AgeRangeType, + ) + ) + adjusted_gender: gender_type.GenderTypeEnum.GenderType = proto.Field( + proto.ENUM, + number=197, + enum=gender_type.GenderTypeEnum.GenderType, + ) + search_term_match_source: ( + gage_search_term_match_source.SearchTermMatchSourceEnum.SearchTermMatchSource + ) = proto.Field( + proto.ENUM, + number=198, + enum=gage_search_term_match_source.SearchTermMatchSourceEnum.SearchTermMatchSource, + ) + search_term_targeting_status: ( + gage_search_term_targeting_status.SearchTermTargetingStatusEnum.SearchTermTargetingStatus + ) = proto.Field( + proto.ENUM, + number=201, + enum=gage_search_term_targeting_status.SearchTermTargetingStatusEnum.SearchTermTargetingStatus, + ) + ad_using_product_data: bool = proto.Field( + proto.BOOL, + number=202, + optional=True, + ) + ad_using_video: bool = proto.Field( + proto.BOOL, + number=203, + optional=True, + ) + + +class Keyword(proto.Message): + r"""A Keyword criterion segment. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + ad_group_criterion (str): + The AdGroupCriterion resource name. + + This field is a member of `oneof`_ ``_ad_group_criterion``. + info (google.ads.googleads.v24.common.types.KeywordInfo): + Keyword info. + """ + + ad_group_criterion: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + info: criteria.KeywordInfo = proto.Field( + proto.MESSAGE, + number=2, + message=criteria.KeywordInfo, + ) + + +class BudgetCampaignAssociationStatus(proto.Message): + r"""A BudgetCampaignAssociationStatus segment. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + campaign (str): + The campaign resource name. + + This field is a member of `oneof`_ ``_campaign``. + status (google.ads.googleads.v24.enums.types.BudgetCampaignAssociationStatusEnum.BudgetCampaignAssociationStatus): + Budget campaign association status. + """ + + campaign: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + status: ( + gage_budget_campaign_association_status.BudgetCampaignAssociationStatusEnum.BudgetCampaignAssociationStatus + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_budget_campaign_association_status.BudgetCampaignAssociationStatusEnum.BudgetCampaignAssociationStatus, + ) + + +class AssetInteractionTarget(proto.Message): + r"""An AssetInteractionTarget segment. + + Attributes: + asset (str): + The asset resource name. + interaction_on_this_asset (bool): + Only used with CustomerAsset, CampaignAsset + and AdGroupAsset metrics. Indicates whether the + interaction metrics occurred on the asset itself + or a different asset or ad unit. + """ + + asset: str = proto.Field( + proto.STRING, + number=1, + ) + interaction_on_this_asset: bool = proto.Field( + proto.BOOL, + number=2, + ) + + +class SkAdNetworkSourceApp(proto.Message): + r"""A SkAdNetworkSourceApp segment. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + sk_ad_network_source_app_id (str): + App id where the ad that drove the iOS Store + Kit Ad Network install was shown. + + This field is a member of `oneof`_ ``_sk_ad_network_source_app_id``. + """ + + sk_ad_network_source_app_id: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/simulation.py b/google/ads/googleads/v24/common/types/simulation.py new file mode 100644 index 000000000..9d21932ab --- /dev/null +++ b/google/ads/googleads/v24/common/types/simulation.py @@ -0,0 +1,763 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "CpcBidSimulationPointList", + "CpvBidSimulationPointList", + "TargetCpaSimulationPointList", + "TargetRoasSimulationPointList", + "PercentCpcBidSimulationPointList", + "BudgetSimulationPointList", + "TargetImpressionShareSimulationPointList", + "CpcBidSimulationPoint", + "CpvBidSimulationPoint", + "TargetCpaSimulationPoint", + "TargetRoasSimulationPoint", + "PercentCpcBidSimulationPoint", + "BudgetSimulationPoint", + "TargetImpressionShareSimulationPoint", + }, +) + + +class CpcBidSimulationPointList(proto.Message): + r"""A container for simulation points for simulations of type CPC_BID. + + Attributes: + points (MutableSequence[google.ads.googleads.v24.common.types.CpcBidSimulationPoint]): + Projected metrics for a series of CPC bid + amounts. + """ + + points: MutableSequence["CpcBidSimulationPoint"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="CpcBidSimulationPoint", + ) + + +class CpvBidSimulationPointList(proto.Message): + r"""A container for simulation points for simulations of type CPV_BID. + + Attributes: + points (MutableSequence[google.ads.googleads.v24.common.types.CpvBidSimulationPoint]): + Projected metrics for a series of CPV bid + amounts. + """ + + points: MutableSequence["CpvBidSimulationPoint"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="CpvBidSimulationPoint", + ) + + +class TargetCpaSimulationPointList(proto.Message): + r"""A container for simulation points for simulations of type + TARGET_CPA. + + Attributes: + points (MutableSequence[google.ads.googleads.v24.common.types.TargetCpaSimulationPoint]): + Projected metrics for a series of target CPA + amounts. + """ + + points: MutableSequence["TargetCpaSimulationPoint"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="TargetCpaSimulationPoint", + ) + + +class TargetRoasSimulationPointList(proto.Message): + r"""A container for simulation points for simulations of type + TARGET_ROAS. + + Attributes: + points (MutableSequence[google.ads.googleads.v24.common.types.TargetRoasSimulationPoint]): + Projected metrics for a series of target ROAS + amounts. + """ + + points: MutableSequence["TargetRoasSimulationPoint"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="TargetRoasSimulationPoint", + ) + + +class PercentCpcBidSimulationPointList(proto.Message): + r"""A container for simulation points for simulations of type + PERCENT_CPC_BID. + + Attributes: + points (MutableSequence[google.ads.googleads.v24.common.types.PercentCpcBidSimulationPoint]): + Projected metrics for a series of percent CPC + bid amounts. + """ + + points: MutableSequence["PercentCpcBidSimulationPoint"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="PercentCpcBidSimulationPoint", + ) + ) + + +class BudgetSimulationPointList(proto.Message): + r"""A container for simulation points for simulations of type + BUDGET. + + Attributes: + points (MutableSequence[google.ads.googleads.v24.common.types.BudgetSimulationPoint]): + Projected metrics for a series of budget + amounts. + """ + + points: MutableSequence["BudgetSimulationPoint"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="BudgetSimulationPoint", + ) + + +class TargetImpressionShareSimulationPointList(proto.Message): + r"""A container for simulation points for simulations of type + TARGET_IMPRESSION_SHARE. + + Attributes: + points (MutableSequence[google.ads.googleads.v24.common.types.TargetImpressionShareSimulationPoint]): + Projected metrics for a specific target + impression share value. + """ + + points: MutableSequence["TargetImpressionShareSimulationPoint"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="TargetImpressionShareSimulationPoint", + ) + ) + + +class CpcBidSimulationPoint(proto.Message): + r"""Projected metrics for a specific CPC bid amount. + + 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: + required_budget_amount_micros (int): + Projected required daily budget that the + advertiser must set in order to receive the + estimated traffic, in micros of advertiser + currency. + biddable_conversions (float): + Projected number of biddable conversions. + + This field is a member of `oneof`_ ``_biddable_conversions``. + biddable_conversions_value (float): + Projected total value of biddable + conversions. + + This field is a member of `oneof`_ ``_biddable_conversions_value``. + clicks (int): + Projected number of clicks. + + This field is a member of `oneof`_ ``_clicks``. + cost_micros (int): + Projected cost in micros. + + This field is a member of `oneof`_ ``_cost_micros``. + impressions (int): + Projected number of impressions. + + This field is a member of `oneof`_ ``_impressions``. + top_slot_impressions (int): + Projected number of top slot impressions. + Only search advertising channel type supports + this field. + + This field is a member of `oneof`_ ``_top_slot_impressions``. + cpc_bid_micros (int): + The simulated CPC bid upon which projected + metrics are based. + + This field is a member of `oneof`_ ``cpc_simulation_key_value``. + cpc_bid_scaling_modifier (float): + The simulated scaling modifier upon which + projected metrics are based. All CPC bids + relevant to the simulated entity are scaled by + this modifier. + + This field is a member of `oneof`_ ``cpc_simulation_key_value``. + """ + + required_budget_amount_micros: int = proto.Field( + proto.INT64, + number=17, + ) + biddable_conversions: float = proto.Field( + proto.DOUBLE, + number=9, + optional=True, + ) + biddable_conversions_value: float = proto.Field( + proto.DOUBLE, + number=10, + optional=True, + ) + clicks: int = proto.Field( + proto.INT64, + number=11, + optional=True, + ) + cost_micros: int = proto.Field( + proto.INT64, + number=12, + optional=True, + ) + impressions: int = proto.Field( + proto.INT64, + number=13, + optional=True, + ) + top_slot_impressions: int = proto.Field( + proto.INT64, + number=14, + optional=True, + ) + cpc_bid_micros: int = proto.Field( + proto.INT64, + number=15, + oneof="cpc_simulation_key_value", + ) + cpc_bid_scaling_modifier: float = proto.Field( + proto.DOUBLE, + number=16, + oneof="cpc_simulation_key_value", + ) + + +class CpvBidSimulationPoint(proto.Message): + r"""Projected metrics for a specific CPV bid amount. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + cpv_bid_micros (int): + The simulated CPV bid upon which projected + metrics are based. + + This field is a member of `oneof`_ ``_cpv_bid_micros``. + cost_micros (int): + Projected cost in micros. + + This field is a member of `oneof`_ ``_cost_micros``. + impressions (int): + Projected number of impressions. + + This field is a member of `oneof`_ ``_impressions``. + views (int): + Projected number of views. + + This field is a member of `oneof`_ ``_views``. + """ + + cpv_bid_micros: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + cost_micros: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + impressions: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + views: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + + +class TargetCpaSimulationPoint(proto.Message): + r"""Projected metrics for a specific target CPA amount. + + 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: + required_budget_amount_micros (int): + Projected required daily budget that the + advertiser must set in order to receive the + estimated traffic, in micros of advertiser + currency. + biddable_conversions (float): + Projected number of biddable conversions. + + This field is a member of `oneof`_ ``_biddable_conversions``. + biddable_conversions_value (float): + Projected total value of biddable + conversions. + + This field is a member of `oneof`_ ``_biddable_conversions_value``. + app_installs (float): + Projected number of app installs. + in_app_actions (float): + Projected number of in-app actions. + clicks (int): + Projected number of clicks. + + This field is a member of `oneof`_ ``_clicks``. + cost_micros (int): + Projected cost in micros. + + This field is a member of `oneof`_ ``_cost_micros``. + impressions (int): + Projected number of impressions. + + This field is a member of `oneof`_ ``_impressions``. + top_slot_impressions (int): + Projected number of top slot impressions. + Only search advertising channel type supports + this field. + + This field is a member of `oneof`_ ``_top_slot_impressions``. + interactions (int): + Projected number of interactions. + Only discovery advertising channel type supports + this field. + + This field is a member of `oneof`_ ``_interactions``. + target_cpa_micros (int): + The simulated target CPA upon which projected + metrics are based. + + This field is a member of `oneof`_ ``target_cpa_simulation_key_value``. + target_cpa_scaling_modifier (float): + The simulated scaling modifier upon which + projected metrics are based. All CPA targets + relevant to the simulated entity are scaled by + this modifier. + + This field is a member of `oneof`_ ``target_cpa_simulation_key_value``. + """ + + required_budget_amount_micros: int = proto.Field( + proto.INT64, + number=19, + ) + biddable_conversions: float = proto.Field( + proto.DOUBLE, + number=9, + optional=True, + ) + biddable_conversions_value: float = proto.Field( + proto.DOUBLE, + number=10, + optional=True, + ) + app_installs: float = proto.Field( + proto.DOUBLE, + number=15, + ) + in_app_actions: float = proto.Field( + proto.DOUBLE, + number=16, + ) + clicks: int = proto.Field( + proto.INT64, + number=11, + optional=True, + ) + cost_micros: int = proto.Field( + proto.INT64, + number=12, + optional=True, + ) + impressions: int = proto.Field( + proto.INT64, + number=13, + optional=True, + ) + top_slot_impressions: int = proto.Field( + proto.INT64, + number=14, + optional=True, + ) + interactions: int = proto.Field( + proto.INT64, + number=20, + optional=True, + ) + target_cpa_micros: int = proto.Field( + proto.INT64, + number=17, + oneof="target_cpa_simulation_key_value", + ) + target_cpa_scaling_modifier: float = proto.Field( + proto.DOUBLE, + number=18, + oneof="target_cpa_simulation_key_value", + ) + + +class TargetRoasSimulationPoint(proto.Message): + r"""Projected metrics for a specific target ROAS amount. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_roas (float): + The simulated target ROAS upon which + projected metrics are based. + + This field is a member of `oneof`_ ``_target_roas``. + required_budget_amount_micros (int): + Projected required daily budget that the + advertiser must set in order to receive the + estimated traffic, in micros of advertiser + currency. + biddable_conversions (float): + Projected number of biddable conversions. + + This field is a member of `oneof`_ ``_biddable_conversions``. + biddable_conversions_value (float): + Projected total value of biddable + conversions. + + This field is a member of `oneof`_ ``_biddable_conversions_value``. + clicks (int): + Projected number of clicks. + + This field is a member of `oneof`_ ``_clicks``. + cost_micros (int): + Projected cost in micros. + + This field is a member of `oneof`_ ``_cost_micros``. + impressions (int): + Projected number of impressions. + + This field is a member of `oneof`_ ``_impressions``. + top_slot_impressions (int): + Projected number of top slot impressions. + Only Search advertising channel type supports + this field. + + This field is a member of `oneof`_ ``_top_slot_impressions``. + """ + + target_roas: float = proto.Field( + proto.DOUBLE, + number=8, + optional=True, + ) + required_budget_amount_micros: int = proto.Field( + proto.INT64, + number=15, + ) + biddable_conversions: float = proto.Field( + proto.DOUBLE, + number=9, + optional=True, + ) + biddable_conversions_value: float = proto.Field( + proto.DOUBLE, + number=10, + optional=True, + ) + clicks: int = proto.Field( + proto.INT64, + number=11, + optional=True, + ) + cost_micros: int = proto.Field( + proto.INT64, + number=12, + optional=True, + ) + impressions: int = proto.Field( + proto.INT64, + number=13, + optional=True, + ) + top_slot_impressions: int = proto.Field( + proto.INT64, + number=14, + optional=True, + ) + + +class PercentCpcBidSimulationPoint(proto.Message): + r"""Projected metrics for a specific percent CPC amount. Only + Hotel advertising channel type supports this field. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + percent_cpc_bid_micros (int): + The simulated percent CPC upon which projected metrics are + based. Percent CPC expressed as fraction of the advertised + price for some good or service. The value stored here is + 1,000,000 \* [fraction]. + + This field is a member of `oneof`_ ``_percent_cpc_bid_micros``. + biddable_conversions (float): + Projected number of biddable conversions. + + This field is a member of `oneof`_ ``_biddable_conversions``. + biddable_conversions_value (float): + Projected total value of biddable conversions + in local currency. + + This field is a member of `oneof`_ ``_biddable_conversions_value``. + clicks (int): + Projected number of clicks. + + This field is a member of `oneof`_ ``_clicks``. + cost_micros (int): + Projected cost in micros. + + This field is a member of `oneof`_ ``_cost_micros``. + impressions (int): + Projected number of impressions. + + This field is a member of `oneof`_ ``_impressions``. + top_slot_impressions (int): + Projected number of top slot impressions. + + This field is a member of `oneof`_ ``_top_slot_impressions``. + """ + + percent_cpc_bid_micros: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + biddable_conversions: float = proto.Field( + proto.DOUBLE, + number=2, + optional=True, + ) + biddable_conversions_value: float = proto.Field( + proto.DOUBLE, + number=3, + optional=True, + ) + clicks: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + cost_micros: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + impressions: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + top_slot_impressions: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + + +class BudgetSimulationPoint(proto.Message): + r"""Projected metrics for a specific budget amount. + + Attributes: + budget_amount_micros (int): + The simulated budget upon which projected + metrics are based. + required_cpc_bid_ceiling_micros (int): + Projected required daily cpc bid ceiling that + the advertiser must set to realize this + simulation, in micros of the advertiser + currency. Only campaigns with the Target Spend + bidding strategy support this field. + biddable_conversions (float): + Projected number of biddable conversions. + biddable_conversions_value (float): + Projected total value of biddable + conversions. + clicks (int): + Projected number of clicks. + cost_micros (int): + Projected cost in micros. + impressions (int): + Projected number of impressions. + top_slot_impressions (int): + Projected number of top slot impressions. + Only search advertising channel type supports + this field. + interactions (int): + Projected number of interactions. + Only discovery advertising channel type supports + this field. + """ + + budget_amount_micros: int = proto.Field( + proto.INT64, + number=1, + ) + required_cpc_bid_ceiling_micros: int = proto.Field( + proto.INT64, + number=2, + ) + biddable_conversions: float = proto.Field( + proto.DOUBLE, + number=3, + ) + biddable_conversions_value: float = proto.Field( + proto.DOUBLE, + number=4, + ) + clicks: int = proto.Field( + proto.INT64, + number=5, + ) + cost_micros: int = proto.Field( + proto.INT64, + number=6, + ) + impressions: int = proto.Field( + proto.INT64, + number=7, + ) + top_slot_impressions: int = proto.Field( + proto.INT64, + number=8, + ) + interactions: int = proto.Field( + proto.INT64, + number=9, + ) + + +class TargetImpressionShareSimulationPoint(proto.Message): + r"""Projected metrics for a specific target impression share + value. + + Attributes: + target_impression_share_micros (int): + The simulated target impression share value (in micros) upon + which projected metrics are based. For example, 10% + impression share, which is equal to 0.1, is stored as + 100_000. This value is validated and will not exceed 1M + (100%). + required_cpc_bid_ceiling_micros (int): + Projected required daily cpc bid ceiling that + the advertiser must set to realize this + simulation, in micros of the advertiser + currency. + required_budget_amount_micros (int): + Projected required daily budget that the + advertiser must set in order to receive the + estimated traffic, in micros of advertiser + currency. + biddable_conversions (float): + Projected number of biddable conversions. + biddable_conversions_value (float): + Projected total value of biddable + conversions. + clicks (int): + Projected number of clicks. + cost_micros (int): + Projected cost in micros. + impressions (int): + Projected number of impressions. + top_slot_impressions (int): + Projected number of top slot impressions. + Only search advertising channel type supports + this field. + absolute_top_impressions (int): + Projected number of absolute top impressions. + Only search advertising channel type supports + this field. + """ + + target_impression_share_micros: int = proto.Field( + proto.INT64, + number=1, + ) + required_cpc_bid_ceiling_micros: int = proto.Field( + proto.INT64, + number=2, + ) + required_budget_amount_micros: int = proto.Field( + proto.INT64, + number=3, + ) + biddable_conversions: float = proto.Field( + proto.DOUBLE, + number=4, + ) + biddable_conversions_value: float = proto.Field( + proto.DOUBLE, + number=5, + ) + clicks: int = proto.Field( + proto.INT64, + number=6, + ) + cost_micros: int = proto.Field( + proto.INT64, + number=7, + ) + impressions: int = proto.Field( + proto.INT64, + number=8, + ) + top_slot_impressions: int = proto.Field( + proto.INT64, + number=9, + ) + absolute_top_impressions: int = proto.Field( + proto.INT64, + number=10, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/tag_snippet.py b/google/ads/googleads/v24/common/types/tag_snippet.py new file mode 100644 index 000000000..1148998d5 --- /dev/null +++ b/google/ads/googleads/v24/common/types/tag_snippet.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import tracking_code_page_format +from google.ads.googleads.v24.enums.types import tracking_code_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "TagSnippet", + }, +) + + +class TagSnippet(proto.Message): + r"""The site tag and event snippet pair for a TrackingCodeType. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + type_ (google.ads.googleads.v24.enums.types.TrackingCodeTypeEnum.TrackingCodeType): + The type of the generated tag snippets for + tracking conversions. + page_format (google.ads.googleads.v24.enums.types.TrackingCodePageFormatEnum.TrackingCodePageFormat): + The format of the web page where the tracking + tag and snippet will be installed, for example, + HTML. + global_site_tag (str): + The site tag that adds visitors to your basic + remarketing lists and sets new cookies on your + domain. + + This field is a member of `oneof`_ ``_global_site_tag``. + event_snippet (str): + The event snippet that works with the site + tag to track actions that should be counted as + conversions. + + This field is a member of `oneof`_ ``_event_snippet``. + """ + + type_: tracking_code_type.TrackingCodeTypeEnum.TrackingCodeType = ( + proto.Field( + proto.ENUM, + number=1, + enum=tracking_code_type.TrackingCodeTypeEnum.TrackingCodeType, + ) + ) + page_format: ( + tracking_code_page_format.TrackingCodePageFormatEnum.TrackingCodePageFormat + ) = proto.Field( + proto.ENUM, + number=2, + enum=tracking_code_page_format.TrackingCodePageFormatEnum.TrackingCodePageFormat, + ) + global_site_tag: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + event_snippet: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/targeting_setting.py b/google/ads/googleads/v24/common/types/targeting_setting.py new file mode 100644 index 000000000..23cce9bda --- /dev/null +++ b/google/ads/googleads/v24/common/types/targeting_setting.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + targeting_dimension as gage_targeting_dimension, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "TargetingSetting", + "TargetRestriction", + "TargetRestrictionOperation", + }, +) + + +class TargetingSetting(proto.Message): + r"""Settings for the targeting-related features, at the campaign + and ad group levels. For more details about the targeting + setting, visit + https://support.google.com/google-ads/answer/7365594 + + Attributes: + target_restrictions (MutableSequence[google.ads.googleads.v24.common.types.TargetRestriction]): + The per-targeting-dimension setting to + restrict the reach of your campaign or ad group. + target_restriction_operations (MutableSequence[google.ads.googleads.v24.common.types.TargetRestrictionOperation]): + The list of operations changing the target + restrictions. + Adding a target restriction with a targeting + dimension that already exists causes the + existing target restriction to be replaced with + the new value. + """ + + target_restrictions: MutableSequence["TargetRestriction"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="TargetRestriction", + ) + ) + target_restriction_operations: MutableSequence[ + "TargetRestrictionOperation" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="TargetRestrictionOperation", + ) + + +class TargetRestriction(proto.Message): + r"""The list of per-targeting-dimension targeting settings. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + targeting_dimension (google.ads.googleads.v24.enums.types.TargetingDimensionEnum.TargetingDimension): + The targeting dimension that these settings + apply to. + bid_only (bool): + Indicates whether to restrict your ads to show only for the + criteria you have selected for this targeting_dimension, or + to target all values for this targeting_dimension and show + ads based on your targeting in other TargetingDimensions. A + value of ``true`` means that these criteria will only apply + bid modifiers, and not affect targeting. A value of + ``false`` means that these criteria will restrict targeting + as well as applying bid modifiers. + + This field is a member of `oneof`_ ``_bid_only``. + """ + + targeting_dimension: ( + gage_targeting_dimension.TargetingDimensionEnum.TargetingDimension + ) = proto.Field( + proto.ENUM, + number=1, + enum=gage_targeting_dimension.TargetingDimensionEnum.TargetingDimension, + ) + bid_only: bool = proto.Field( + proto.BOOL, + number=3, + optional=True, + ) + + +class TargetRestrictionOperation(proto.Message): + r"""Operation to be performed on a target restriction list in a + mutate. + + Attributes: + operator (google.ads.googleads.v24.common.types.TargetRestrictionOperation.Operator): + Type of list operation to perform. + value (google.ads.googleads.v24.common.types.TargetRestriction): + The target restriction being added to or + removed from the list. + """ + + class Operator(proto.Enum): + r"""The operator. + + Values: + UNSPECIFIED (0): + Unspecified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ADD (2): + Add the restriction to the existing + restrictions. + REMOVE (3): + Remove the restriction from the existing + restrictions. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ADD = 2 + REMOVE = 3 + + operator: Operator = proto.Field( + proto.ENUM, + number=1, + enum=Operator, + ) + value: "TargetRestriction" = proto.Field( + proto.MESSAGE, + number=2, + message="TargetRestriction", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/text_label.py b/google/ads/googleads/v24/common/types/text_label.py new file mode 100644 index 000000000..eaf7b2e0d --- /dev/null +++ b/google/ads/googleads/v24/common/types/text_label.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "TextLabel", + }, +) + + +class TextLabel(proto.Message): + r"""A type of label displaying text on a colored background. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + background_color (str): + Background color of the label in HEX format. This string + must match the regular expression + '^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$'. Note: The background + color may not be visible for manager accounts. + + This field is a member of `oneof`_ ``_background_color``. + description (str): + A short description of the label. The length + must be no more than 200 characters. + + This field is a member of `oneof`_ ``_description``. + """ + + background_color: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + description: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/third_party_integration_partners.py b/google/ads/googleads/v24/common/types/third_party_integration_partners.py new file mode 100644 index 000000000..491af221a --- /dev/null +++ b/google/ads/googleads/v24/common/types/third_party_integration_partners.py @@ -0,0 +1,420 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + third_party_brand_lift_integration_partner, +) +from google.ads.googleads.v24.enums.types import ( + third_party_brand_safety_integration_partner, +) +from google.ads.googleads.v24.enums.types import ( + third_party_reach_integration_partner, +) +from google.ads.googleads.v24.enums.types import ( + third_party_viewability_integration_partner, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerThirdPartyIntegrationPartners", + "CustomerThirdPartyViewabilityIntegrationPartner", + "CustomerThirdPartyBrandSafetyIntegrationPartner", + "CustomerThirdPartyBrandLiftIntegrationPartner", + "CustomerThirdPartyReachIntegrationPartner", + "CampaignThirdPartyIntegrationPartners", + "CampaignThirdPartyViewabilityIntegrationPartner", + "CampaignThirdPartyBrandSafetyIntegrationPartner", + "CampaignThirdPartyBrandLiftIntegrationPartner", + "CampaignThirdPartyReachIntegrationPartner", + "ThirdPartyIntegrationPartnerData", + }, +) + + +class CustomerThirdPartyIntegrationPartners(proto.Message): + r"""Container for Customer level third party integration + partners. + + Attributes: + viewability_integration_partners (MutableSequence[google.ads.googleads.v24.common.types.CustomerThirdPartyViewabilityIntegrationPartner]): + Allowed third party integration partners for + YouTube viewability verification. + brand_lift_integration_partners (MutableSequence[google.ads.googleads.v24.common.types.CustomerThirdPartyBrandLiftIntegrationPartner]): + Allowed third party integration partners for + Brand Lift verification. + brand_safety_integration_partners (MutableSequence[google.ads.googleads.v24.common.types.CustomerThirdPartyBrandSafetyIntegrationPartner]): + Allowed third party integration partners for + brand safety verification. + reach_integration_partners (MutableSequence[google.ads.googleads.v24.common.types.CustomerThirdPartyReachIntegrationPartner]): + Allowed third party integration partners for + reach verification. + """ + + viewability_integration_partners: MutableSequence[ + "CustomerThirdPartyViewabilityIntegrationPartner" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="CustomerThirdPartyViewabilityIntegrationPartner", + ) + brand_lift_integration_partners: MutableSequence[ + "CustomerThirdPartyBrandLiftIntegrationPartner" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CustomerThirdPartyBrandLiftIntegrationPartner", + ) + brand_safety_integration_partners: MutableSequence[ + "CustomerThirdPartyBrandSafetyIntegrationPartner" + ] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="CustomerThirdPartyBrandSafetyIntegrationPartner", + ) + reach_integration_partners: MutableSequence[ + "CustomerThirdPartyReachIntegrationPartner" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="CustomerThirdPartyReachIntegrationPartner", + ) + + +class CustomerThirdPartyViewabilityIntegrationPartner(proto.Message): + r"""Container for third party viewability integration data for + Customer. + + Attributes: + viewability_integration_partner (google.ads.googleads.v24.enums.types.ThirdPartyViewabilityIntegrationPartnerEnum.ThirdPartyViewabilityIntegrationPartner): + Allowed third party integration partners for + YouTube viewability verification. + allow_share_cost (bool): + If true, cost data can be shared with this + vendor. + """ + + viewability_integration_partner: ( + third_party_viewability_integration_partner.ThirdPartyViewabilityIntegrationPartnerEnum.ThirdPartyViewabilityIntegrationPartner + ) = proto.Field( + proto.ENUM, + number=1, + enum=third_party_viewability_integration_partner.ThirdPartyViewabilityIntegrationPartnerEnum.ThirdPartyViewabilityIntegrationPartner, + ) + allow_share_cost: bool = proto.Field( + proto.BOOL, + number=2, + ) + + +class CustomerThirdPartyBrandSafetyIntegrationPartner(proto.Message): + r"""Container for third party brand safety integration data for + Customer. + + Attributes: + brand_safety_integration_partner (google.ads.googleads.v24.enums.types.ThirdPartyBrandSafetyIntegrationPartnerEnum.ThirdPartyBrandSafetyIntegrationPartner): + Allowed third party integration partners for + brand safety verification. + """ + + brand_safety_integration_partner: ( + third_party_brand_safety_integration_partner.ThirdPartyBrandSafetyIntegrationPartnerEnum.ThirdPartyBrandSafetyIntegrationPartner + ) = proto.Field( + proto.ENUM, + number=1, + enum=third_party_brand_safety_integration_partner.ThirdPartyBrandSafetyIntegrationPartnerEnum.ThirdPartyBrandSafetyIntegrationPartner, + ) + + +class CustomerThirdPartyBrandLiftIntegrationPartner(proto.Message): + r"""Container for third party Brand Lift integration data for + Customer. + + Attributes: + brand_lift_integration_partner (google.ads.googleads.v24.enums.types.ThirdPartyBrandLiftIntegrationPartnerEnum.ThirdPartyBrandLiftIntegrationPartner): + Allowed Third Party integration partners for + Brand Lift verification. + allow_share_cost (bool): + If true, cost data can be shared with this + vendor. + """ + + brand_lift_integration_partner: ( + third_party_brand_lift_integration_partner.ThirdPartyBrandLiftIntegrationPartnerEnum.ThirdPartyBrandLiftIntegrationPartner + ) = proto.Field( + proto.ENUM, + number=1, + enum=third_party_brand_lift_integration_partner.ThirdPartyBrandLiftIntegrationPartnerEnum.ThirdPartyBrandLiftIntegrationPartner, + ) + allow_share_cost: bool = proto.Field( + proto.BOOL, + number=2, + ) + + +class CustomerThirdPartyReachIntegrationPartner(proto.Message): + r"""Container for third party reach integration data for + Customer. + + Attributes: + reach_integration_partner (google.ads.googleads.v24.enums.types.ThirdPartyReachIntegrationPartnerEnum.ThirdPartyReachIntegrationPartner): + Allowed Third Party integration partners for + reach verification. + allow_share_cost (bool): + If true, cost data can be shared with this + vendor. + """ + + reach_integration_partner: ( + third_party_reach_integration_partner.ThirdPartyReachIntegrationPartnerEnum.ThirdPartyReachIntegrationPartner + ) = proto.Field( + proto.ENUM, + number=1, + enum=third_party_reach_integration_partner.ThirdPartyReachIntegrationPartnerEnum.ThirdPartyReachIntegrationPartner, + ) + allow_share_cost: bool = proto.Field( + proto.BOOL, + number=2, + ) + + +class CampaignThirdPartyIntegrationPartners(proto.Message): + r"""Container for Campaign level third party integration + partners. + + Attributes: + viewability_integration_partners (MutableSequence[google.ads.googleads.v24.common.types.CampaignThirdPartyViewabilityIntegrationPartner]): + Third party integration partners for YouTube + viewability verification for this Campaign. + brand_lift_integration_partners (MutableSequence[google.ads.googleads.v24.common.types.CampaignThirdPartyBrandLiftIntegrationPartner]): + Third party integration partners for Brand + Lift verification for this Campaign. + brand_safety_integration_partners (MutableSequence[google.ads.googleads.v24.common.types.CampaignThirdPartyBrandSafetyIntegrationPartner]): + Third party integration partners for brand + safety verification for this Campaign. + reach_integration_partners (MutableSequence[google.ads.googleads.v24.common.types.CampaignThirdPartyReachIntegrationPartner]): + Third party integration partners for reach + verification for this Campaign. + """ + + viewability_integration_partners: MutableSequence[ + "CampaignThirdPartyViewabilityIntegrationPartner" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="CampaignThirdPartyViewabilityIntegrationPartner", + ) + brand_lift_integration_partners: MutableSequence[ + "CampaignThirdPartyBrandLiftIntegrationPartner" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignThirdPartyBrandLiftIntegrationPartner", + ) + brand_safety_integration_partners: MutableSequence[ + "CampaignThirdPartyBrandSafetyIntegrationPartner" + ] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="CampaignThirdPartyBrandSafetyIntegrationPartner", + ) + reach_integration_partners: MutableSequence[ + "CampaignThirdPartyReachIntegrationPartner" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="CampaignThirdPartyReachIntegrationPartner", + ) + + +class CampaignThirdPartyViewabilityIntegrationPartner(proto.Message): + r"""Container for third party viewability integration data for + Campaign. + + Attributes: + viewability_integration_partner (google.ads.googleads.v24.enums.types.ThirdPartyViewabilityIntegrationPartnerEnum.ThirdPartyViewabilityIntegrationPartner): + Allowed third party integration partners for + YouTube viewability verification. + viewability_integration_partner_data (google.ads.googleads.v24.common.types.ThirdPartyIntegrationPartnerData): + Third party partner data for YouTube + viewability verification. This is optional + metadata for partners to join or attach data to + Ads campaigns. + share_cost (bool): + If true, then cost data will be shared with + this vendor. + """ + + viewability_integration_partner: ( + third_party_viewability_integration_partner.ThirdPartyViewabilityIntegrationPartnerEnum.ThirdPartyViewabilityIntegrationPartner + ) = proto.Field( + proto.ENUM, + number=1, + enum=third_party_viewability_integration_partner.ThirdPartyViewabilityIntegrationPartnerEnum.ThirdPartyViewabilityIntegrationPartner, + ) + viewability_integration_partner_data: "ThirdPartyIntegrationPartnerData" = ( + proto.Field( + proto.MESSAGE, + number=2, + message="ThirdPartyIntegrationPartnerData", + ) + ) + share_cost: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class CampaignThirdPartyBrandSafetyIntegrationPartner(proto.Message): + r"""Container for third party brand safety integration data for + Campaign. + + Attributes: + brand_safety_integration_partner (google.ads.googleads.v24.enums.types.ThirdPartyBrandSafetyIntegrationPartnerEnum.ThirdPartyBrandSafetyIntegrationPartner): + Allowed third party integration partners for + brand safety verification. + brand_safety_integration_partner_data (google.ads.googleads.v24.common.types.ThirdPartyIntegrationPartnerData): + Third party partner data for YouTube brand + safety verification. This is optional metadata + for partners to join or attach data to Ads + campaigns. + """ + + brand_safety_integration_partner: ( + third_party_brand_safety_integration_partner.ThirdPartyBrandSafetyIntegrationPartnerEnum.ThirdPartyBrandSafetyIntegrationPartner + ) = proto.Field( + proto.ENUM, + number=1, + enum=third_party_brand_safety_integration_partner.ThirdPartyBrandSafetyIntegrationPartnerEnum.ThirdPartyBrandSafetyIntegrationPartner, + ) + brand_safety_integration_partner_data: ( + "ThirdPartyIntegrationPartnerData" + ) = proto.Field( + proto.MESSAGE, + number=2, + message="ThirdPartyIntegrationPartnerData", + ) + + +class CampaignThirdPartyBrandLiftIntegrationPartner(proto.Message): + r"""Container for third party Brand Lift integration data for + Campaign. + + Attributes: + brand_lift_integration_partner (google.ads.googleads.v24.enums.types.ThirdPartyBrandLiftIntegrationPartnerEnum.ThirdPartyBrandLiftIntegrationPartner): + Allowed third party integration partners for + Brand Lift verification. + brand_lift_integration_partner_data (google.ads.googleads.v24.common.types.ThirdPartyIntegrationPartnerData): + Third party partner data for YouTube Brand + Lift verification. This is optional metadata for + partners to join or attach data to Ads + campaigns. + share_cost (bool): + If true, then cost data will be shared with + this vendor. + """ + + brand_lift_integration_partner: ( + third_party_brand_lift_integration_partner.ThirdPartyBrandLiftIntegrationPartnerEnum.ThirdPartyBrandLiftIntegrationPartner + ) = proto.Field( + proto.ENUM, + number=1, + enum=third_party_brand_lift_integration_partner.ThirdPartyBrandLiftIntegrationPartnerEnum.ThirdPartyBrandLiftIntegrationPartner, + ) + brand_lift_integration_partner_data: "ThirdPartyIntegrationPartnerData" = ( + proto.Field( + proto.MESSAGE, + number=2, + message="ThirdPartyIntegrationPartnerData", + ) + ) + share_cost: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class CampaignThirdPartyReachIntegrationPartner(proto.Message): + r"""Container for third party reach integration data for + Campaign. + + Attributes: + reach_integration_partner (google.ads.googleads.v24.enums.types.ThirdPartyReachIntegrationPartnerEnum.ThirdPartyReachIntegrationPartner): + Allowed third party integration partners for + reach verification. + reach_integration_partner_data (google.ads.googleads.v24.common.types.ThirdPartyIntegrationPartnerData): + Third party partner data for YouTube Reach + verification. This is optional metadata for + partners to join or attach data to Ads + campaigns. + share_cost (bool): + If true, then cost data will be shared with + this vendor. + """ + + reach_integration_partner: ( + third_party_reach_integration_partner.ThirdPartyReachIntegrationPartnerEnum.ThirdPartyReachIntegrationPartner + ) = proto.Field( + proto.ENUM, + number=1, + enum=third_party_reach_integration_partner.ThirdPartyReachIntegrationPartnerEnum.ThirdPartyReachIntegrationPartner, + ) + reach_integration_partner_data: "ThirdPartyIntegrationPartnerData" = ( + proto.Field( + proto.MESSAGE, + number=2, + message="ThirdPartyIntegrationPartnerData", + ) + ) + share_cost: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class ThirdPartyIntegrationPartnerData(proto.Message): + r"""Contains third party measurement partner related data for + video campaigns. + + Attributes: + client_id (str): + The client ID that allows the measurement + partner to join multiple campaigns for a + particular advertiser. + third_party_placement_id (str): + The third party placement ID that maps the + measurement partner data with a campaign (or a + group of related campaigns) specific data. + """ + + client_id: str = proto.Field( + proto.STRING, + number=1, + ) + third_party_placement_id: str = proto.Field( + proto.STRING, + number=2, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/url_collection.py b/google/ads/googleads/v24/common/types/url_collection.py new file mode 100644 index 000000000..91eba20ae --- /dev/null +++ b/google/ads/googleads/v24/common/types/url_collection.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "UrlCollection", + }, +) + + +class UrlCollection(proto.Message): + r"""Collection of urls that is tagged with a unique identifier. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + url_collection_id (str): + Unique identifier for this UrlCollection + instance. + + This field is a member of `oneof`_ ``_url_collection_id``. + final_urls (MutableSequence[str]): + A list of possible final URLs. + final_mobile_urls (MutableSequence[str]): + A list of possible final mobile URLs. + tracking_url_template (str): + URL template for constructing a tracking URL. + + This field is a member of `oneof`_ ``_tracking_url_template``. + """ + + url_collection_id: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + final_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=6, + ) + final_mobile_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=7, + ) + tracking_url_template: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/user_lists.py b/google/ads/googleads/v24/common/types/user_lists.py new file mode 100644 index 000000000..6c9fba4b0 --- /dev/null +++ b/google/ads/googleads/v24/common/types/user_lists.py @@ -0,0 +1,644 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import customer_match_upload_key_type +from google.ads.googleads.v24.enums.types import lookalike_expansion_level +from google.ads.googleads.v24.enums.types import user_list_crm_data_source_type +from google.ads.googleads.v24.enums.types import ( + user_list_date_rule_item_operator, +) +from google.ads.googleads.v24.enums.types import ( + user_list_flexible_rule_operator, +) +from google.ads.googleads.v24.enums.types import user_list_logical_rule_operator +from google.ads.googleads.v24.enums.types import ( + user_list_number_rule_item_operator, +) +from google.ads.googleads.v24.enums.types import user_list_prepopulation_status +from google.ads.googleads.v24.enums.types import user_list_rule_type +from google.ads.googleads.v24.enums.types import ( + user_list_string_rule_item_operator, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "LookalikeUserListInfo", + "SimilarUserListInfo", + "CrmBasedUserListInfo", + "UserListRuleInfo", + "UserListRuleItemGroupInfo", + "UserListRuleItemInfo", + "UserListDateRuleItemInfo", + "UserListNumberRuleItemInfo", + "UserListStringRuleItemInfo", + "FlexibleRuleOperandInfo", + "FlexibleRuleUserListInfo", + "RuleBasedUserListInfo", + "LogicalUserListInfo", + "UserListLogicalRuleInfo", + "LogicalUserListOperandInfo", + "BasicUserListInfo", + "UserListActionInfo", + }, +) + + +class LookalikeUserListInfo(proto.Message): + r"""LookalikeUserlist, composed of users similar to those + of a configurable seed (set of UserLists) + + Attributes: + seed_user_list_ids (MutableSequence[int]): + Seed UserList ID from which this list is + derived, provided by user. + expansion_level (google.ads.googleads.v24.enums.types.LookalikeExpansionLevelEnum.LookalikeExpansionLevel): + Expansion level, reflecting the size of the + lookalike audience + country_codes (MutableSequence[str]): + Countries targeted by the Lookalike. + Two-letter country code as defined by ISO-3166 + """ + + seed_user_list_ids: MutableSequence[int] = proto.RepeatedField( + proto.INT64, + number=1, + ) + expansion_level: ( + lookalike_expansion_level.LookalikeExpansionLevelEnum.LookalikeExpansionLevel + ) = proto.Field( + proto.ENUM, + number=2, + enum=lookalike_expansion_level.LookalikeExpansionLevelEnum.LookalikeExpansionLevel, + ) + country_codes: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + + +class SimilarUserListInfo(proto.Message): + r"""SimilarUserList is a list of users which are similar to users + from another UserList. These lists are read-only and + automatically created by Google. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + seed_user_list (str): + Seed UserList from which this list is + derived. + + This field is a member of `oneof`_ ``_seed_user_list``. + """ + + seed_user_list: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class CrmBasedUserListInfo(proto.Message): + r"""UserList of CRM users provided by the advertiser. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + app_id (str): + A string that uniquely identifies a mobile + application from which the data was collected. + For iOS, the ID string is the 9 digit string + that appears at the end of an App Store URL (for + example, "476943146" for "Flood-It! 2" whose App + Store link is + http://itunes.apple.com/us/app/flood-it!-2/id476943146). + For Android, the ID string is the application's + package name (for example, + "com.labpixies.colordrips" for "Color Drips" + given Google Play link + https://play.google.com/store/apps/details?id=com.labpixies.colordrips). + Required when creating CrmBasedUserList for + uploading mobile advertising IDs. + + This field is a member of `oneof`_ ``_app_id``. + upload_key_type (google.ads.googleads.v24.enums.types.CustomerMatchUploadKeyTypeEnum.CustomerMatchUploadKeyType): + Matching key type of the list. + Mixed data types are not allowed on the same + list. This field is required for an ADD + operation. + data_source_type (google.ads.googleads.v24.enums.types.UserListCrmDataSourceTypeEnum.UserListCrmDataSourceType): + Data source of the list. Default value is FIRST_PARTY. Only + customers on the allow-list can create third-party sourced + CRM lists. + """ + + app_id: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + upload_key_type: ( + customer_match_upload_key_type.CustomerMatchUploadKeyTypeEnum.CustomerMatchUploadKeyType + ) = proto.Field( + proto.ENUM, + number=2, + enum=customer_match_upload_key_type.CustomerMatchUploadKeyTypeEnum.CustomerMatchUploadKeyType, + ) + data_source_type: ( + user_list_crm_data_source_type.UserListCrmDataSourceTypeEnum.UserListCrmDataSourceType + ) = proto.Field( + proto.ENUM, + number=3, + enum=user_list_crm_data_source_type.UserListCrmDataSourceTypeEnum.UserListCrmDataSourceType, + ) + + +class UserListRuleInfo(proto.Message): + r"""A client defined rule based on custom parameters sent by web + sites or uploaded by the advertiser. + + Attributes: + rule_type (google.ads.googleads.v24.enums.types.UserListRuleTypeEnum.UserListRuleType): + Rule type is used to determine how to group + rule items. + The default is OR of ANDs (disjunctive normal + form). That is, rule items will be ANDed + together within rule item groups and the groups + themselves will be ORed together. + + OR of ANDs is the only supported type for + FlexibleRuleUserList. + rule_item_groups (MutableSequence[google.ads.googleads.v24.common.types.UserListRuleItemGroupInfo]): + List of rule item groups that defines this rule. Rule item + groups are grouped together based on rule_type. + """ + + rule_type: user_list_rule_type.UserListRuleTypeEnum.UserListRuleType = ( + proto.Field( + proto.ENUM, + number=1, + enum=user_list_rule_type.UserListRuleTypeEnum.UserListRuleType, + ) + ) + rule_item_groups: MutableSequence["UserListRuleItemGroupInfo"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="UserListRuleItemGroupInfo", + ) + ) + + +class UserListRuleItemGroupInfo(proto.Message): + r"""A group of rule items. + + Attributes: + rule_items (MutableSequence[google.ads.googleads.v24.common.types.UserListRuleItemInfo]): + Rule items that will be grouped together based on rule_type. + """ + + rule_items: MutableSequence["UserListRuleItemInfo"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="UserListRuleItemInfo", + ) + + +class UserListRuleItemInfo(proto.Message): + r"""An atomic rule item. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + name (str): + Rule variable name. It should match the corresponding key + name fired by the pixel. A name must begin with US-ascii + letters or underscore or UTF8 code that is greater than 127 + and consist of US-ascii letters or digits or underscore or + UTF8 code that is greater than 127. For websites, there are + two built-in variable URL (name = 'url\_\_') and referrer + URL (name = 'ref_url\_\_'). This field must be populated + when creating a new rule item. + + This field is a member of `oneof`_ ``_name``. + number_rule_item (google.ads.googleads.v24.common.types.UserListNumberRuleItemInfo): + An atomic rule item composed of a number + operation. + + This field is a member of `oneof`_ ``rule_item``. + string_rule_item (google.ads.googleads.v24.common.types.UserListStringRuleItemInfo): + An atomic rule item composed of a string + operation. + + This field is a member of `oneof`_ ``rule_item``. + date_rule_item (google.ads.googleads.v24.common.types.UserListDateRuleItemInfo): + An atomic rule item composed of a date + operation. + + This field is a member of `oneof`_ ``rule_item``. + """ + + name: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + number_rule_item: "UserListNumberRuleItemInfo" = proto.Field( + proto.MESSAGE, + number=2, + oneof="rule_item", + message="UserListNumberRuleItemInfo", + ) + string_rule_item: "UserListStringRuleItemInfo" = proto.Field( + proto.MESSAGE, + number=3, + oneof="rule_item", + message="UserListStringRuleItemInfo", + ) + date_rule_item: "UserListDateRuleItemInfo" = proto.Field( + proto.MESSAGE, + number=4, + oneof="rule_item", + message="UserListDateRuleItemInfo", + ) + + +class UserListDateRuleItemInfo(proto.Message): + r"""A rule item composed of a date operation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + operator (google.ads.googleads.v24.enums.types.UserListDateRuleItemOperatorEnum.UserListDateRuleItemOperator): + Date comparison operator. + This field is required and must be populated + when creating new date rule item. + value (str): + String representing date value to be compared + with the rule variable. Supported date format is + YYYY-MM-DD. Times are reported in the customer's + time zone. + + This field is a member of `oneof`_ ``_value``. + offset_in_days (int): + The relative date value of the right hand + side denoted by number of days offset from now. + The value field will override this field when + both are present. + + This field is a member of `oneof`_ ``_offset_in_days``. + """ + + operator: ( + user_list_date_rule_item_operator.UserListDateRuleItemOperatorEnum.UserListDateRuleItemOperator + ) = proto.Field( + proto.ENUM, + number=1, + enum=user_list_date_rule_item_operator.UserListDateRuleItemOperatorEnum.UserListDateRuleItemOperator, + ) + value: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + offset_in_days: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + + +class UserListNumberRuleItemInfo(proto.Message): + r"""A rule item composed of a number operation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + operator (google.ads.googleads.v24.enums.types.UserListNumberRuleItemOperatorEnum.UserListNumberRuleItemOperator): + Number comparison operator. + This field is required and must be populated + when creating a new number rule item. + value (float): + Number value to be compared with the + variable. This field is required and must be + populated when creating a new number rule item. + + This field is a member of `oneof`_ ``_value``. + """ + + operator: ( + user_list_number_rule_item_operator.UserListNumberRuleItemOperatorEnum.UserListNumberRuleItemOperator + ) = proto.Field( + proto.ENUM, + number=1, + enum=user_list_number_rule_item_operator.UserListNumberRuleItemOperatorEnum.UserListNumberRuleItemOperator, + ) + value: float = proto.Field( + proto.DOUBLE, + number=3, + optional=True, + ) + + +class UserListStringRuleItemInfo(proto.Message): + r"""A rule item composed of a string operation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + operator (google.ads.googleads.v24.enums.types.UserListStringRuleItemOperatorEnum.UserListStringRuleItemOperator): + String comparison operator. + This field is required and must be populated + when creating a new string rule item. + value (str): + The right hand side of the string rule item. + For URLs or referrer URLs, the value can not + contain illegal URL chars such as newlines, + quotes, tabs, or parentheses. This field is + required and must be populated when creating a + new string rule item. + + This field is a member of `oneof`_ ``_value``. + """ + + operator: ( + user_list_string_rule_item_operator.UserListStringRuleItemOperatorEnum.UserListStringRuleItemOperator + ) = proto.Field( + proto.ENUM, + number=1, + enum=user_list_string_rule_item_operator.UserListStringRuleItemOperatorEnum.UserListStringRuleItemOperator, + ) + value: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + + +class FlexibleRuleOperandInfo(proto.Message): + r"""Flexible rule that wraps the common rule and a lookback + window. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + rule (google.ads.googleads.v24.common.types.UserListRuleInfo): + List of rule item groups that defines this + rule. Rule item groups are grouped together. + lookback_window_days (int): + Lookback window for this rule in days. From + now until X days ago. + + This field is a member of `oneof`_ ``_lookback_window_days``. + """ + + rule: "UserListRuleInfo" = proto.Field( + proto.MESSAGE, + number=1, + message="UserListRuleInfo", + ) + lookback_window_days: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + +class FlexibleRuleUserListInfo(proto.Message): + r"""Flexible rule representation of visitors with one or multiple + actions. The flexible user list is defined by two lists of operands + – inclusive_operands and exclusive_operands; each operand represents + a set of users based on actions they took in a given timeframe. + These lists of operands are combined with the AND_NOT operator, so + that users represented by the inclusive operands are included in the + user list, minus the users represented by the exclusive operands. + + Attributes: + inclusive_rule_operator (google.ads.googleads.v24.enums.types.UserListFlexibleRuleOperatorEnum.UserListFlexibleRuleOperator): + Operator that defines how the inclusive + operands are combined. + inclusive_operands (MutableSequence[google.ads.googleads.v24.common.types.FlexibleRuleOperandInfo]): + Rules representing users that should be included in the user + list. These are located on the left side of the AND_NOT + operator, and joined together by either AND/OR as specified + by the inclusive_rule_operator. + exclusive_operands (MutableSequence[google.ads.googleads.v24.common.types.FlexibleRuleOperandInfo]): + Rules representing users that should be excluded from the + user list. These are located on the right side of the + AND_NOT operator, and joined together by OR. + """ + + inclusive_rule_operator: ( + user_list_flexible_rule_operator.UserListFlexibleRuleOperatorEnum.UserListFlexibleRuleOperator + ) = proto.Field( + proto.ENUM, + number=1, + enum=user_list_flexible_rule_operator.UserListFlexibleRuleOperatorEnum.UserListFlexibleRuleOperator, + ) + inclusive_operands: MutableSequence["FlexibleRuleOperandInfo"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="FlexibleRuleOperandInfo", + ) + ) + exclusive_operands: MutableSequence["FlexibleRuleOperandInfo"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=3, + message="FlexibleRuleOperandInfo", + ) + ) + + +class RuleBasedUserListInfo(proto.Message): + r"""Representation of a userlist that is generated by a rule. + + Attributes: + prepopulation_status (google.ads.googleads.v24.enums.types.UserListPrepopulationStatusEnum.UserListPrepopulationStatus): + The status of pre-population. The field is + default to NONE if not set which means the + previous users will not be considered. If set to + REQUESTED, past site visitors or app users who + match the list definition will be included in + the list (works on the Display Network only). + This will only add past users from within the + last 30 days, depending on the list's membership + duration and the date when the remarketing tag + is added. The status will be updated to FINISHED + once request is processed, or FAILED if the + request fails. + flexible_rule_user_list (google.ads.googleads.v24.common.types.FlexibleRuleUserListInfo): + Flexible rule representation of visitors with one or + multiple actions. The flexible user list is defined by two + lists of operands – inclusive_operands and + exclusive_operands; each operand represents a set of users + based on actions they took in a given timeframe. These lists + of operands are combined with the AND_NOT operator, so that + users represented by the inclusive operands are included in + the user list, minus the users represented by the exclusive + operands. + """ + + prepopulation_status: ( + user_list_prepopulation_status.UserListPrepopulationStatusEnum.UserListPrepopulationStatus + ) = proto.Field( + proto.ENUM, + number=1, + enum=user_list_prepopulation_status.UserListPrepopulationStatusEnum.UserListPrepopulationStatus, + ) + flexible_rule_user_list: "FlexibleRuleUserListInfo" = proto.Field( + proto.MESSAGE, + number=5, + message="FlexibleRuleUserListInfo", + ) + + +class LogicalUserListInfo(proto.Message): + r"""Represents a user list that is a custom combination of user + lists. + + Attributes: + rules (MutableSequence[google.ads.googleads.v24.common.types.UserListLogicalRuleInfo]): + Logical list rules that define this user + list. The rules are defined as a logical + operator (ALL/ANY/NONE) and a list of user + lists. All the rules are ANDed when they are + evaluated. + + Required for creating a logical user list. + """ + + rules: MutableSequence["UserListLogicalRuleInfo"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="UserListLogicalRuleInfo", + ) + + +class UserListLogicalRuleInfo(proto.Message): + r"""A user list logical rule. A rule has a logical operator + (and/or/not) and a list of user lists as operands. + + Attributes: + operator (google.ads.googleads.v24.enums.types.UserListLogicalRuleOperatorEnum.UserListLogicalRuleOperator): + The logical operator of the rule. + rule_operands (MutableSequence[google.ads.googleads.v24.common.types.LogicalUserListOperandInfo]): + The list of operands of the rule. + """ + + operator: ( + user_list_logical_rule_operator.UserListLogicalRuleOperatorEnum.UserListLogicalRuleOperator + ) = proto.Field( + proto.ENUM, + number=1, + enum=user_list_logical_rule_operator.UserListLogicalRuleOperatorEnum.UserListLogicalRuleOperator, + ) + rule_operands: MutableSequence["LogicalUserListOperandInfo"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="LogicalUserListOperandInfo", + ) + ) + + +class LogicalUserListOperandInfo(proto.Message): + r"""Operand of logical user list that consists of a user list. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + user_list (str): + Resource name of a user list as an operand. + + This field is a member of `oneof`_ ``_user_list``. + """ + + user_list: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class BasicUserListInfo(proto.Message): + r"""User list targeting as a collection of conversions or + remarketing actions. + + Attributes: + actions (MutableSequence[google.ads.googleads.v24.common.types.UserListActionInfo]): + Actions associated with this user list. + """ + + actions: MutableSequence["UserListActionInfo"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="UserListActionInfo", + ) + + +class UserListActionInfo(proto.Message): + r"""Represents an action type used for building remarketing user + lists. + + 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: + conversion_action (str): + A conversion action that's not generated from + remarketing. + + This field is a member of `oneof`_ ``user_list_action``. + remarketing_action (str): + A remarketing action. + + This field is a member of `oneof`_ ``user_list_action``. + """ + + conversion_action: str = proto.Field( + proto.STRING, + number=3, + oneof="user_list_action", + ) + remarketing_action: str = proto.Field( + proto.STRING, + number=4, + oneof="user_list_action", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/common/types/value.py b/google/ads/googleads/v24/common/types/value.py new file mode 100644 index 000000000..594ccdb05 --- /dev/null +++ b/google/ads/googleads/v24/common/types/value.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.common", + marshal="google.ads.googleads.v24", + manifest={ + "Value", + }, +) + + +class Value(proto.Message): + r"""A generic data container. + + 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: + boolean_value (bool): + A boolean. + + This field is a member of `oneof`_ ``value``. + int64_value (int): + An int64. + + This field is a member of `oneof`_ ``value``. + float_value (float): + A float. + + This field is a member of `oneof`_ ``value``. + double_value (float): + A double. + + This field is a member of `oneof`_ ``value``. + string_value (str): + A string. + + This field is a member of `oneof`_ ``value``. + """ + + boolean_value: bool = proto.Field( + proto.BOOL, + number=1, + oneof="value", + ) + int64_value: int = proto.Field( + proto.INT64, + number=2, + oneof="value", + ) + float_value: float = proto.Field( + proto.FLOAT, + number=3, + oneof="value", + ) + double_value: float = proto.Field( + proto.DOUBLE, + number=4, + oneof="value", + ) + string_value: str = proto.Field( + proto.STRING, + number=5, + oneof="value", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/__init__.py b/google/ads/googleads/v24/enums/__init__.py new file mode 100644 index 000000000..806c0aea8 --- /dev/null +++ b/google/ads/googleads/v24/enums/__init__.py @@ -0,0 +1,1085 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 google.ads.googleads.v24 import gapic_version as package_version + +import google.api_core as api_core +import sys + +__version__ = package_version.__version__ + +if sys.version_info >= (3, 8): # pragma: NO COVER + from importlib import metadata +else: # pragma: NO COVER + # TODO(https://github.com/googleapis/python-api-core/issues/835): Remove + # this code path once we drop support for Python 3.7 + import importlib_metadata as metadata + + +from .types.access_invitation_status import AccessInvitationStatusEnum +from .types.access_reason import AccessReasonEnum +from .types.access_role import AccessRoleEnum +from .types.account_budget_proposal_status import ( + AccountBudgetProposalStatusEnum, +) +from .types.account_budget_proposal_type import AccountBudgetProposalTypeEnum +from .types.account_budget_status import AccountBudgetStatusEnum +from .types.account_link_status import AccountLinkStatusEnum +from .types.ad_destination_type import AdDestinationTypeEnum +from .types.ad_format_type import AdFormatTypeEnum +from .types.ad_group_ad_primary_status import AdGroupAdPrimaryStatusEnum +from .types.ad_group_ad_primary_status_reason import ( + AdGroupAdPrimaryStatusReasonEnum, +) +from .types.ad_group_ad_rotation_mode import AdGroupAdRotationModeEnum +from .types.ad_group_ad_status import AdGroupAdStatusEnum +from .types.ad_group_criterion_approval_status import ( + AdGroupCriterionApprovalStatusEnum, +) +from .types.ad_group_criterion_primary_status import ( + AdGroupCriterionPrimaryStatusEnum, +) +from .types.ad_group_criterion_primary_status_reason import ( + AdGroupCriterionPrimaryStatusReasonEnum, +) +from .types.ad_group_criterion_status import AdGroupCriterionStatusEnum +from .types.ad_group_primary_status import AdGroupPrimaryStatusEnum +from .types.ad_group_primary_status_reason import AdGroupPrimaryStatusReasonEnum +from .types.ad_group_status import AdGroupStatusEnum +from .types.ad_group_type import AdGroupTypeEnum +from .types.ad_network_type import AdNetworkTypeEnum +from .types.ad_serving_optimization_status import ( + AdServingOptimizationStatusEnum, +) +from .types.ad_strength import AdStrengthEnum +from .types.ad_strength_action_item_type import AdStrengthActionItemTypeEnum +from .types.ad_sub_network_type import AdSubNetworkTypeEnum +from .types.ad_type import AdTypeEnum +from .types.advertising_channel_sub_type import AdvertisingChannelSubTypeEnum +from .types.advertising_channel_type import AdvertisingChannelTypeEnum +from .types.age_range_type import AgeRangeTypeEnum +from .types.android_privacy_interaction_type import ( + AndroidPrivacyInteractionTypeEnum, +) +from .types.android_privacy_network_type import AndroidPrivacyNetworkTypeEnum +from .types.app_bidding_goal import AppBiddingGoalEnum +from .types.app_campaign_app_store import AppCampaignAppStoreEnum +from .types.app_campaign_bidding_strategy_goal_type import ( + AppCampaignBiddingStrategyGoalTypeEnum, +) +from .types.app_payment_model_type import AppPaymentModelTypeEnum +from .types.app_url_operating_system_type import AppUrlOperatingSystemTypeEnum +from .types.application_instance import ApplicationInstanceEnum +from .types.asset_automation_status import AssetAutomationStatusEnum +from .types.asset_automation_type import AssetAutomationTypeEnum +from .types.asset_coverage_video_aspect_ratio_requirement import ( + AssetCoverageVideoAspectRatioRequirementEnum, +) +from .types.asset_field_type import AssetFieldTypeEnum +from .types.asset_group_primary_status import AssetGroupPrimaryStatusEnum +from .types.asset_group_primary_status_reason import ( + AssetGroupPrimaryStatusReasonEnum, +) +from .types.asset_group_signal_approval_status import ( + AssetGroupSignalApprovalStatusEnum, +) +from .types.asset_group_status import AssetGroupStatusEnum +from .types.asset_link_primary_status import AssetLinkPrimaryStatusEnum +from .types.asset_link_primary_status_reason import ( + AssetLinkPrimaryStatusReasonEnum, +) +from .types.asset_link_status import AssetLinkStatusEnum +from .types.asset_offline_evaluation_error_reasons import ( + AssetOfflineEvaluationErrorReasonsEnum, +) +from .types.asset_orientation import AssetOrientationEnum +from .types.asset_performance_label import AssetPerformanceLabelEnum +from .types.asset_set_asset_status import AssetSetAssetStatusEnum +from .types.asset_set_link_status import AssetSetLinkStatusEnum +from .types.asset_set_status import AssetSetStatusEnum +from .types.asset_set_type import AssetSetTypeEnum +from .types.asset_source import AssetSourceEnum +from .types.asset_type import AssetTypeEnum +from .types.async_action_status import AsyncActionStatusEnum +from .types.attribution_model import AttributionModelEnum +from .types.audience_insights_dimension import AudienceInsightsDimensionEnum +from .types.audience_insights_marketing_objective import ( + AudienceInsightsMarketingObjectiveEnum, +) +from .types.audience_scope import AudienceScopeEnum +from .types.audience_status import AudienceStatusEnum +from .types.batch_job_status import BatchJobStatusEnum +from .types.benchmarks_marketing_objective import ( + BenchmarksMarketingObjectiveEnum, +) +from .types.benchmarks_source_type import BenchmarksSourceTypeEnum +from .types.benchmarks_time_granularity import BenchmarksTimeGranularityEnum +from .types.bid_modifier_source import BidModifierSourceEnum +from .types.bidding_source import BiddingSourceEnum +from .types.bidding_strategy_status import BiddingStrategyStatusEnum +from .types.bidding_strategy_system_status import ( + BiddingStrategySystemStatusEnum, +) +from .types.bidding_strategy_type import BiddingStrategyTypeEnum +from .types.billing_setup_status import BillingSetupStatusEnum +from .types.booking_status import BookingStatusEnum +from .types.brand_request_rejection_reason import ( + BrandRequestRejectionReasonEnum, +) +from .types.brand_safety_suitability import BrandSafetySuitabilityEnum +from .types.brand_state import BrandStateEnum +from .types.budget_campaign_association_status import ( + BudgetCampaignAssociationStatusEnum, +) +from .types.budget_delivery_method import BudgetDeliveryMethodEnum +from .types.budget_period import BudgetPeriodEnum +from .types.budget_status import BudgetStatusEnum +from .types.budget_type import BudgetTypeEnum +from .types.business_message_call_to_action_type import ( + BusinessMessageCallToActionTypeEnum, +) +from .types.business_message_provider import BusinessMessageProviderEnum +from .types.call_conversion_reporting_state import ( + CallConversionReportingStateEnum, +) +from .types.call_to_action_type import CallToActionTypeEnum +from .types.call_tracking_display_location import ( + CallTrackingDisplayLocationEnum, +) +from .types.call_type import CallTypeEnum +from .types.campaign_criterion_status import CampaignCriterionStatusEnum +from .types.campaign_draft_status import CampaignDraftStatusEnum +from .types.campaign_experiment_type import CampaignExperimentTypeEnum +from .types.campaign_group_status import CampaignGroupStatusEnum +from .types.campaign_keyword_match_type import CampaignKeywordMatchTypeEnum +from .types.campaign_primary_status import CampaignPrimaryStatusEnum +from .types.campaign_primary_status_reason import ( + CampaignPrimaryStatusReasonEnum, +) +from .types.campaign_serving_status import CampaignServingStatusEnum +from .types.campaign_shared_set_status import CampaignSharedSetStatusEnum +from .types.campaign_status import CampaignStatusEnum +from .types.chain_relationship_type import ChainRelationshipTypeEnum +from .types.change_client_type import ChangeClientTypeEnum +from .types.change_event_resource_type import ChangeEventResourceTypeEnum +from .types.change_status_operation import ChangeStatusOperationEnum +from .types.change_status_resource_type import ChangeStatusResourceTypeEnum +from .types.click_type import ClickTypeEnum +from .types.combined_audience_status import CombinedAudienceStatusEnum +from .types.consent_status import ConsentStatusEnum +from .types.content_label_type import ContentLabelTypeEnum +from .types.conversion_action_category import ConversionActionCategoryEnum +from .types.conversion_action_counting_type import ( + ConversionActionCountingTypeEnum, +) +from .types.conversion_action_status import ConversionActionStatusEnum +from .types.conversion_action_type import ConversionActionTypeEnum +from .types.conversion_adjustment_type import ConversionAdjustmentTypeEnum +from .types.conversion_attribution_event_type import ( + ConversionAttributionEventTypeEnum, +) +from .types.conversion_custom_variable_status import ( + ConversionCustomVariableStatusEnum, +) +from .types.conversion_customer_type import ConversionCustomerTypeEnum +from .types.conversion_environment_enum import ConversionEnvironmentEnum +from .types.conversion_lag_bucket import ConversionLagBucketEnum +from .types.conversion_or_adjustment_lag_bucket import ( + ConversionOrAdjustmentLagBucketEnum, +) +from .types.conversion_origin import ConversionOriginEnum +from .types.conversion_tracking_status_enum import ConversionTrackingStatusEnum +from .types.conversion_value_rule_primary_dimension import ( + ConversionValueRulePrimaryDimensionEnum, +) +from .types.conversion_value_rule_set_status import ( + ConversionValueRuleSetStatusEnum, +) +from .types.conversion_value_rule_status import ConversionValueRuleStatusEnum +from .types.converting_user_prior_engagement_type_and_ltv_bucket import ( + ConvertingUserPriorEngagementTypeAndLtvBucketEnum, +) +from .types.criterion_category_channel_availability_mode import ( + CriterionCategoryChannelAvailabilityModeEnum, +) +from .types.criterion_category_locale_availability_mode import ( + CriterionCategoryLocaleAvailabilityModeEnum, +) +from .types.criterion_system_serving_status import ( + CriterionSystemServingStatusEnum, +) +from .types.criterion_type import CriterionTypeEnum +from .types.custom_audience_member_type import CustomAudienceMemberTypeEnum +from .types.custom_audience_status import CustomAudienceStatusEnum +from .types.custom_audience_type import CustomAudienceTypeEnum +from .types.custom_conversion_goal_status import CustomConversionGoalStatusEnum +from .types.custom_interest_member_type import CustomInterestMemberTypeEnum +from .types.custom_interest_status import CustomInterestStatusEnum +from .types.custom_interest_type import CustomInterestTypeEnum +from .types.customer_acquisition_optimization_mode import ( + CustomerAcquisitionOptimizationModeEnum, +) +from .types.customer_lifecycle_optimization_mode import ( + CustomerLifecycleOptimizationModeEnum, +) +from .types.customer_match_upload_key_type import CustomerMatchUploadKeyTypeEnum +from .types.customer_pay_per_conversion_eligibility_failure_reason import ( + CustomerPayPerConversionEligibilityFailureReasonEnum, +) +from .types.customer_status import CustomerStatusEnum +from .types.customizer_attribute_status import CustomizerAttributeStatusEnum +from .types.customizer_attribute_type import CustomizerAttributeTypeEnum +from .types.customizer_value_status import CustomizerValueStatusEnum +from .types.data_driven_model_status import DataDrivenModelStatusEnum +from .types.data_link_status import DataLinkStatusEnum +from .types.data_link_type import DataLinkTypeEnum +from .types.day_of_week import DayOfWeekEnum +from .types.demand_gen_channel_config import DemandGenChannelConfigEnum +from .types.demand_gen_channel_strategy import DemandGenChannelStrategyEnum +from .types.device import DeviceEnum +from .types.display_ad_format_setting import DisplayAdFormatSettingEnum +from .types.display_upload_product_type import DisplayUploadProductTypeEnum +from .types.distance_bucket import DistanceBucketEnum +from .types.eu_political_advertising_status import ( + EuPoliticalAdvertisingStatusEnum, +) +from .types.experiment_metric import ExperimentMetricEnum +from .types.experiment_metric_direction import ExperimentMetricDirectionEnum +from .types.experiment_status import ExperimentStatusEnum +from .types.experiment_type import ExperimentTypeEnum +from .types.external_conversion_source import ExternalConversionSourceEnum +from .types.fixed_cpm_goal import FixedCpmGoalEnum +from .types.fixed_cpm_target_frequency_time_unit import ( + FixedCpmTargetFrequencyTimeUnitEnum, +) +from .types.frequency_cap_event_type import FrequencyCapEventTypeEnum +from .types.frequency_cap_level import FrequencyCapLevelEnum +from .types.frequency_cap_time_unit import FrequencyCapTimeUnitEnum +from .types.gender_type import GenderTypeEnum +from .types.geo_target_constant_status import GeoTargetConstantStatusEnum +from .types.geo_targeting_type import GeoTargetingTypeEnum +from .types.goal_config_level import GoalConfigLevelEnum +from .types.goal_optimization_eligibility import GoalOptimizationEligibilityEnum +from .types.goal_type import GoalTypeEnum +from .types.google_ads_field_category import GoogleAdsFieldCategoryEnum +from .types.google_ads_field_data_type import GoogleAdsFieldDataTypeEnum +from .types.google_voice_call_status import GoogleVoiceCallStatusEnum +from .types.hotel_asset_suggestion_status import HotelAssetSuggestionStatusEnum +from .types.hotel_date_selection_type import HotelDateSelectionTypeEnum +from .types.hotel_price_bucket import HotelPriceBucketEnum +from .types.hotel_rate_type import HotelRateTypeEnum +from .types.hotel_reconciliation_status import HotelReconciliationStatusEnum +from .types.identity_verification_program import IdentityVerificationProgramEnum +from .types.identity_verification_program_status import ( + IdentityVerificationProgramStatusEnum, +) +from .types.incentive_state import IncentiveStateEnum +from .types.income_range_type import IncomeRangeTypeEnum +from .types.insights_knowledge_graph_entity_capabilities import ( + InsightsKnowledgeGraphEntityCapabilitiesEnum, +) +from .types.insights_trend import InsightsTrendEnum +from .types.interaction_event_type import InteractionEventTypeEnum +from .types.interaction_type import InteractionTypeEnum +from .types.invoice_type import InvoiceTypeEnum +from .types.keyword_match_type import KeywordMatchTypeEnum +from .types.keyword_plan_aggregate_metric_type import ( + KeywordPlanAggregateMetricTypeEnum, +) +from .types.keyword_plan_competition_level import ( + KeywordPlanCompetitionLevelEnum, +) +from .types.keyword_plan_concept_group_type import ( + KeywordPlanConceptGroupTypeEnum, +) +from .types.keyword_plan_forecast_interval import ( + KeywordPlanForecastIntervalEnum, +) +from .types.keyword_plan_keyword_annotation import ( + KeywordPlanKeywordAnnotationEnum, +) +from .types.keyword_plan_network import KeywordPlanNetworkEnum +from .types.label_status import LabelStatusEnum +from .types.landing_page_source import LandingPageSourceEnum +from .types.lead_form_call_to_action_type import LeadFormCallToActionTypeEnum +from .types.lead_form_desired_intent import LeadFormDesiredIntentEnum +from .types.lead_form_field_user_input_type import ( + LeadFormFieldUserInputTypeEnum, +) +from .types.lead_form_post_submit_call_to_action_type import ( + LeadFormPostSubmitCallToActionTypeEnum, +) +from .types.legacy_app_install_ad_app_store import ( + LegacyAppInstallAdAppStoreEnum, +) +from .types.linked_account_type import LinkedAccountTypeEnum +from .types.linked_product_type import LinkedProductTypeEnum +from .types.listing_group_filter_custom_attribute_index import ( + ListingGroupFilterCustomAttributeIndexEnum, +) +from .types.listing_group_filter_listing_source import ( + ListingGroupFilterListingSourceEnum, +) +from .types.listing_group_filter_product_category_level import ( + ListingGroupFilterProductCategoryLevelEnum, +) +from .types.listing_group_filter_product_channel import ( + ListingGroupFilterProductChannelEnum, +) +from .types.listing_group_filter_product_condition import ( + ListingGroupFilterProductConditionEnum, +) +from .types.listing_group_filter_product_type_level import ( + ListingGroupFilterProductTypeLevelEnum, +) +from .types.listing_group_filter_type_enum import ListingGroupFilterTypeEnum +from .types.listing_group_type import ListingGroupTypeEnum +from .types.listing_type import ListingTypeEnum +from .types.local_services_business_registration_check_rejection_reason import ( + LocalServicesBusinessRegistrationCheckRejectionReasonEnum, +) +from .types.local_services_business_registration_type import ( + LocalServicesBusinessRegistrationTypeEnum, +) +from .types.local_services_conversation_type import ( + LocalServicesLeadConversationTypeEnum, +) +from .types.local_services_employee_status import ( + LocalServicesEmployeeStatusEnum, +) +from .types.local_services_employee_type import LocalServicesEmployeeTypeEnum +from .types.local_services_insurance_rejection_reason import ( + LocalServicesInsuranceRejectionReasonEnum, +) +from .types.local_services_lead_credit_issuance_decision import ( + LocalServicesLeadCreditIssuanceDecisionEnum, +) +from .types.local_services_lead_credit_state import LocalServicesCreditStateEnum +from .types.local_services_lead_status import LocalServicesLeadStatusEnum +from .types.local_services_lead_survey_answer import ( + LocalServicesLeadSurveyAnswerEnum, +) +from .types.local_services_lead_survey_dissatisfied_reason import ( + LocalServicesLeadSurveyDissatisfiedReasonEnum, +) +from .types.local_services_lead_survey_satisfied_reason import ( + LocalServicesLeadSurveySatisfiedReasonEnum, +) +from .types.local_services_lead_type import LocalServicesLeadTypeEnum +from .types.local_services_license_rejection_reason import ( + LocalServicesLicenseRejectionReasonEnum, +) +from .types.local_services_participant_type import ( + LocalServicesParticipantTypeEnum, +) +from .types.local_services_verification_artifact_status import ( + LocalServicesVerificationArtifactStatusEnum, +) +from .types.local_services_verification_artifact_type import ( + LocalServicesVerificationArtifactTypeEnum, +) +from .types.local_services_verification_status import ( + LocalServicesVerificationStatusEnum, +) +from .types.location_group_radius_units import LocationGroupRadiusUnitsEnum +from .types.location_ownership_type import LocationOwnershipTypeEnum +from .types.location_source_type import LocationSourceTypeEnum +from .types.location_string_filter_type import LocationStringFilterTypeEnum +from .types.lookalike_expansion_level import LookalikeExpansionLevelEnum +from .types.manager_link_status import ManagerLinkStatusEnum +from .types.match_type import MatchTypeEnum +from .types.media_type import MediaTypeEnum +from .types.messaging_restriction_type import MessagingRestrictionTypeEnum +from .types.mime_type import MimeTypeEnum +from .types.minute_of_hour import MinuteOfHourEnum +from .types.mobile_app_vendor import MobileAppVendorEnum +from .types.mobile_device_type import MobileDeviceTypeEnum +from .types.month_of_year import MonthOfYearEnum +from .types.negative_geo_target_type import NegativeGeoTargetTypeEnum +from .types.non_skippable_max_duration import NonSkippableMaxDurationEnum +from .types.non_skippable_min_duration import NonSkippableMinDurationEnum +from .types.offline_conversion_diagnostic_status_enum import ( + OfflineConversionDiagnosticStatusEnum, +) +from .types.offline_event_upload_client_enum import OfflineEventUploadClientEnum +from .types.offline_user_data_job_failure_reason import ( + OfflineUserDataJobFailureReasonEnum, +) +from .types.offline_user_data_job_match_rate_range import ( + OfflineUserDataJobMatchRateRangeEnum, +) +from .types.offline_user_data_job_status import OfflineUserDataJobStatusEnum +from .types.offline_user_data_job_type import OfflineUserDataJobTypeEnum +from .types.operating_system_version_operator_type import ( + OperatingSystemVersionOperatorTypeEnum, +) +from .types.optimization_goal_type import OptimizationGoalTypeEnum +from .types.parental_status_type import ParentalStatusTypeEnum +from .types.partnership_opportunity import PartnershipOpportunityEnum +from .types.payment_mode import PaymentModeEnum +from .types.performance_max_upgrade_status import ( + PerformanceMaxUpgradeStatusEnum, +) +from .types.placement_type import PlacementTypeEnum +from .types.policy_approval_status import PolicyApprovalStatusEnum +from .types.policy_review_status import PolicyReviewStatusEnum +from .types.policy_topic_entry_type import PolicyTopicEntryTypeEnum +from .types.policy_topic_evidence_destination_mismatch_url_type import ( + PolicyTopicEvidenceDestinationMismatchUrlTypeEnum, +) +from .types.policy_topic_evidence_destination_not_working_device import ( + PolicyTopicEvidenceDestinationNotWorkingDeviceEnum, +) +from .types.policy_topic_evidence_destination_not_working_dns_error_type import ( + PolicyTopicEvidenceDestinationNotWorkingDnsErrorTypeEnum, +) +from .types.positive_geo_target_type import PositiveGeoTargetTypeEnum +from .types.preview_type import PreviewTypeEnum +from .types.price_extension_price_qualifier import ( + PriceExtensionPriceQualifierEnum, +) +from .types.price_extension_price_unit import PriceExtensionPriceUnitEnum +from .types.price_extension_type import PriceExtensionTypeEnum +from .types.product_availability import ProductAvailabilityEnum +from .types.product_category_level import ProductCategoryLevelEnum +from .types.product_category_state import ProductCategoryStateEnum +from .types.product_channel import ProductChannelEnum +from .types.product_channel_exclusivity import ProductChannelExclusivityEnum +from .types.product_condition import ProductConditionEnum +from .types.product_custom_attribute_index import ( + ProductCustomAttributeIndexEnum, +) +from .types.product_issue_severity import ProductIssueSeverityEnum +from .types.product_link_invitation_status import ( + ProductLinkInvitationStatusEnum, +) +from .types.product_status import ProductStatusEnum +from .types.product_type_level import ProductTypeLevelEnum +from .types.promotion_barcode_type import PromotionBarcodeTypeEnum +from .types.promotion_extension_discount_modifier import ( + PromotionExtensionDiscountModifierEnum, +) +from .types.promotion_extension_occasion import PromotionExtensionOccasionEnum +from .types.proximity_radius_units import ProximityRadiusUnitsEnum +from .types.quality_score_bucket import QualityScoreBucketEnum +from .types.reach_plan_age_range import ReachPlanAgeRangeEnum +from .types.reach_plan_buying_method import ReachPlanBuyingMethodEnum +from .types.reach_plan_conversion_rate_model import ( + ReachPlanConversionRateModelEnum, +) +from .types.reach_plan_cost_model import ReachPlanCostModelEnum +from .types.reach_plan_marketing_objective import ( + ReachPlanMarketingObjectiveEnum, +) +from .types.reach_plan_network import ReachPlanNetworkEnum +from .types.reach_plan_plannable_user_list_status import ( + ReachPlanPlannableUserListStatusEnum, +) +from .types.reach_plan_surface import ReachPlanSurfaceEnum +from .types.recommendation_subscription_status import ( + RecommendationSubscriptionStatusEnum, +) +from .types.recommendation_type import RecommendationTypeEnum +from .types.regulatory_fee_type import RegulatoryFeeTypeEnum +from .types.reservation_request_type import ReservationRequestTypeEnum +from .types.resource_change_operation import ResourceChangeOperationEnum +from .types.resource_limit_type import ResourceLimitTypeEnum +from .types.response_content_type import ResponseContentTypeEnum +from .types.search_engine_results_page_type import ( + SearchEngineResultsPageTypeEnum, +) +from .types.search_term_match_source import SearchTermMatchSourceEnum +from .types.search_term_match_type import SearchTermMatchTypeEnum +from .types.search_term_targeting_status import SearchTermTargetingStatusEnum +from .types.seasonality_event_scope import SeasonalityEventScopeEnum +from .types.seasonality_event_status import SeasonalityEventStatusEnum +from .types.served_asset_field_type import ServedAssetFieldTypeEnum +from .types.shared_set_status import SharedSetStatusEnum +from .types.shared_set_type import SharedSetTypeEnum +from .types.shopping_add_products_to_campaign_recommendation_enum import ( + ShoppingAddProductsToCampaignRecommendationEnum, +) +from .types.simulation_modification_method import ( + SimulationModificationMethodEnum, +) +from .types.simulation_type import SimulationTypeEnum +from .types.sk_ad_network_ad_event_type import SkAdNetworkAdEventTypeEnum +from .types.sk_ad_network_attribution_credit import ( + SkAdNetworkAttributionCreditEnum, +) +from .types.sk_ad_network_coarse_conversion_value import ( + SkAdNetworkCoarseConversionValueEnum, +) +from .types.sk_ad_network_source_type import SkAdNetworkSourceTypeEnum +from .types.sk_ad_network_user_type import SkAdNetworkUserTypeEnum +from .types.slot import SlotEnum +from .types.smart_campaign_not_eligible_reason import ( + SmartCampaignNotEligibleReasonEnum, +) +from .types.smart_campaign_status import SmartCampaignStatusEnum +from .types.spending_limit_type import SpendingLimitTypeEnum +from .types.summary_row_setting import SummaryRowSettingEnum +from .types.system_managed_entity_source import SystemManagedResourceSourceEnum +from .types.target_cpa_opt_in_recommendation_goal import ( + TargetCpaOptInRecommendationGoalEnum, +) +from .types.target_frequency_time_unit import TargetFrequencyTimeUnitEnum +from .types.target_impression_share_location import ( + TargetImpressionShareLocationEnum, +) +from .types.targeting_dimension import TargetingDimensionEnum +from .types.third_party_brand_lift_integration_partner import ( + ThirdPartyBrandLiftIntegrationPartnerEnum, +) +from .types.third_party_brand_safety_integration_partner import ( + ThirdPartyBrandSafetyIntegrationPartnerEnum, +) +from .types.third_party_reach_integration_partner import ( + ThirdPartyReachIntegrationPartnerEnum, +) +from .types.third_party_viewability_integration_partner import ( + ThirdPartyViewabilityIntegrationPartnerEnum, +) +from .types.time_type import TimeTypeEnum +from .types.tracking_code_page_format import TrackingCodePageFormatEnum +from .types.tracking_code_type import TrackingCodeTypeEnum +from .types.unit_of_measure import UnitOfMeasureEnum +from .types.user_identifier_source import UserIdentifierSourceEnum +from .types.user_interest_taxonomy_type import UserInterestTaxonomyTypeEnum +from .types.user_list_access_status import UserListAccessStatusEnum +from .types.user_list_closing_reason import UserListClosingReasonEnum +from .types.user_list_crm_data_source_type import UserListCrmDataSourceTypeEnum +from .types.user_list_customer_type_category import ( + UserListCustomerTypeCategoryEnum, +) +from .types.user_list_date_rule_item_operator import ( + UserListDateRuleItemOperatorEnum, +) +from .types.user_list_flexible_rule_operator import ( + UserListFlexibleRuleOperatorEnum, +) +from .types.user_list_logical_rule_operator import ( + UserListLogicalRuleOperatorEnum, +) +from .types.user_list_membership_status import UserListMembershipStatusEnum +from .types.user_list_number_rule_item_operator import ( + UserListNumberRuleItemOperatorEnum, +) +from .types.user_list_prepopulation_status import ( + UserListPrepopulationStatusEnum, +) +from .types.user_list_rule_type import UserListRuleTypeEnum +from .types.user_list_size_range import UserListSizeRangeEnum +from .types.user_list_string_rule_item_operator import ( + UserListStringRuleItemOperatorEnum, +) +from .types.user_list_type import UserListTypeEnum +from .types.value_rule_device_type import ValueRuleDeviceTypeEnum +from .types.value_rule_geo_location_match_type import ( + ValueRuleGeoLocationMatchTypeEnum, +) +from .types.value_rule_operation import ValueRuleOperationEnum +from .types.value_rule_set_attachment_type import ValueRuleSetAttachmentTypeEnum +from .types.value_rule_set_dimension import ValueRuleSetDimensionEnum +from .types.vanity_pharma_display_url_mode import VanityPharmaDisplayUrlModeEnum +from .types.vanity_pharma_text import VanityPharmaTextEnum +from .types.vertical_ads_item_vertical_type import ( + VerticalAdsItemVerticalTypeEnum, +) +from .types.video_ad_format_restriction import VideoAdFormatRestrictionEnum +from .types.video_ad_sequence_interaction_type import ( + VideoAdSequenceInteractionTypeEnum, +) +from .types.video_ad_sequence_minimum_duration import ( + VideoAdSequenceMinimumDurationEnum, +) +from .types.video_enhancement_source import VideoEnhancementSourceEnum +from .types.video_thumbnail import VideoThumbnailEnum +from .types.webpage_condition_operand import WebpageConditionOperandEnum +from .types.webpage_condition_operator import WebpageConditionOperatorEnum +from .types.youtube_video_privacy import YouTubeVideoPrivacyEnum +from .types.youtube_video_property import YouTubeVideoPropertyEnum +from .types.youtube_video_upload_state import YouTubeVideoUploadStateEnum + +if hasattr(api_core, "check_python_version") and hasattr( + api_core, "check_dependency_versions" +): # pragma: NO COVER + api_core.check_python_version("google.ads.googleads.v24") # type: ignore + api_core.check_dependency_versions("google.ads.googleads.v24") # type: ignore +else: # pragma: NO COVER + # An older version of api_core is installed which does not define the + # functions above. We do equivalent checks manually. + try: + import warnings + import sys + + _py_version_str = sys.version.split()[0] + _package_label = "google.ads.googleads.v24" + if sys.version_info < (3, 9): + warnings.warn( + "You are using a non-supported Python version " + + f"({_py_version_str}). Google will not post any further " + + f"updates to {_package_label} supporting this Python version. " + + "Please upgrade to the latest Python version, or at " + + f"least to Python 3.9, and then update {_package_label}.", + FutureWarning, + ) + if sys.version_info[:2] == (3, 9): + warnings.warn( + f"You are using a Python version ({_py_version_str}) " + + f"which Google will stop supporting in {_package_label} in " + + "January 2026. Please " + + "upgrade to the latest Python version, or at " + + "least to Python 3.10, before then, and " + + f"then update {_package_label}.", + FutureWarning, + ) + + def parse_version_to_tuple(version_string: str): + """Safely converts a semantic version string to a comparable tuple of integers. + Example: "4.25.8" -> (4, 25, 8) + Ignores non-numeric parts and handles common version formats. + Args: + version_string: Version string in the format "x.y.z" or "x.y.z" + Returns: + Tuple of integers for the parsed version string. + """ + parts = [] + for part in version_string.split("."): + try: + parts.append(int(part)) + except ValueError: + # If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here. + # This is a simplification compared to 'packaging.parse_version', but sufficient + # for comparing strictly numeric semantic versions. + break + return tuple(parts) + + def _get_version(dependency_name): + try: + version_string: str = metadata.version(dependency_name) + parsed_version = parse_version_to_tuple(version_string) + return (parsed_version, version_string) + except Exception: + # Catch exceptions from metadata.version() (e.g., PackageNotFoundError) + # or errors during parse_version_to_tuple + return (None, "--") + + _dependency_package = "google.protobuf" + _next_supported_version = "4.25.8" + _next_supported_version_tuple = (4, 25, 8) + _recommendation = " (we recommend 6.x)" + (_version_used, _version_used_string) = _get_version( + _dependency_package + ) + if _version_used and _version_used < _next_supported_version_tuple: + warnings.warn( + f"Package {_package_label} depends on " + + f"{_dependency_package}, currently installed at version " + + f"{_version_used_string}. Future updates to " + + f"{_package_label} will require {_dependency_package} at " + + f"version {_next_supported_version} or higher{_recommendation}." + + " Please ensure " + + "that either (a) your Python environment doesn't pin the " + + f"version of {_dependency_package}, so that updates to " + + f"{_package_label} can require the higher version, or " + + "(b) you manually update your Python environment to use at " + + f"least version {_next_supported_version} of " + + f"{_dependency_package}.", + FutureWarning, + ) + except Exception: + warnings.warn( + "Could not determine the version of Python " + + "currently being used. To continue receiving " + + "updates for {_package_label}, ensure you are " + + "using a supported version of Python; see " + + "https://devguide.python.org/versions/" + ) + +__all__ = ( + "AccessInvitationStatusEnum", + "AccessReasonEnum", + "AccessRoleEnum", + "AccountBudgetProposalStatusEnum", + "AccountBudgetProposalTypeEnum", + "AccountBudgetStatusEnum", + "AccountLinkStatusEnum", + "AdDestinationTypeEnum", + "AdFormatTypeEnum", + "AdGroupAdPrimaryStatusEnum", + "AdGroupAdPrimaryStatusReasonEnum", + "AdGroupAdRotationModeEnum", + "AdGroupAdStatusEnum", + "AdGroupCriterionApprovalStatusEnum", + "AdGroupCriterionPrimaryStatusEnum", + "AdGroupCriterionPrimaryStatusReasonEnum", + "AdGroupCriterionStatusEnum", + "AdGroupPrimaryStatusEnum", + "AdGroupPrimaryStatusReasonEnum", + "AdGroupStatusEnum", + "AdGroupTypeEnum", + "AdNetworkTypeEnum", + "AdServingOptimizationStatusEnum", + "AdStrengthActionItemTypeEnum", + "AdStrengthEnum", + "AdSubNetworkTypeEnum", + "AdTypeEnum", + "AdvertisingChannelSubTypeEnum", + "AdvertisingChannelTypeEnum", + "AgeRangeTypeEnum", + "AndroidPrivacyInteractionTypeEnum", + "AndroidPrivacyNetworkTypeEnum", + "AppBiddingGoalEnum", + "AppCampaignAppStoreEnum", + "AppCampaignBiddingStrategyGoalTypeEnum", + "AppPaymentModelTypeEnum", + "AppUrlOperatingSystemTypeEnum", + "ApplicationInstanceEnum", + "AssetAutomationStatusEnum", + "AssetAutomationTypeEnum", + "AssetCoverageVideoAspectRatioRequirementEnum", + "AssetFieldTypeEnum", + "AssetGroupPrimaryStatusEnum", + "AssetGroupPrimaryStatusReasonEnum", + "AssetGroupSignalApprovalStatusEnum", + "AssetGroupStatusEnum", + "AssetLinkPrimaryStatusEnum", + "AssetLinkPrimaryStatusReasonEnum", + "AssetLinkStatusEnum", + "AssetOfflineEvaluationErrorReasonsEnum", + "AssetOrientationEnum", + "AssetPerformanceLabelEnum", + "AssetSetAssetStatusEnum", + "AssetSetLinkStatusEnum", + "AssetSetStatusEnum", + "AssetSetTypeEnum", + "AssetSourceEnum", + "AssetTypeEnum", + "AsyncActionStatusEnum", + "AttributionModelEnum", + "AudienceInsightsDimensionEnum", + "AudienceInsightsMarketingObjectiveEnum", + "AudienceScopeEnum", + "AudienceStatusEnum", + "BatchJobStatusEnum", + "BenchmarksMarketingObjectiveEnum", + "BenchmarksSourceTypeEnum", + "BenchmarksTimeGranularityEnum", + "BidModifierSourceEnum", + "BiddingSourceEnum", + "BiddingStrategyStatusEnum", + "BiddingStrategySystemStatusEnum", + "BiddingStrategyTypeEnum", + "BillingSetupStatusEnum", + "BookingStatusEnum", + "BrandRequestRejectionReasonEnum", + "BrandSafetySuitabilityEnum", + "BrandStateEnum", + "BudgetCampaignAssociationStatusEnum", + "BudgetDeliveryMethodEnum", + "BudgetPeriodEnum", + "BudgetStatusEnum", + "BudgetTypeEnum", + "BusinessMessageCallToActionTypeEnum", + "BusinessMessageProviderEnum", + "CallConversionReportingStateEnum", + "CallToActionTypeEnum", + "CallTrackingDisplayLocationEnum", + "CallTypeEnum", + "CampaignCriterionStatusEnum", + "CampaignDraftStatusEnum", + "CampaignExperimentTypeEnum", + "CampaignGroupStatusEnum", + "CampaignKeywordMatchTypeEnum", + "CampaignPrimaryStatusEnum", + "CampaignPrimaryStatusReasonEnum", + "CampaignServingStatusEnum", + "CampaignSharedSetStatusEnum", + "CampaignStatusEnum", + "ChainRelationshipTypeEnum", + "ChangeClientTypeEnum", + "ChangeEventResourceTypeEnum", + "ChangeStatusOperationEnum", + "ChangeStatusResourceTypeEnum", + "ClickTypeEnum", + "CombinedAudienceStatusEnum", + "ConsentStatusEnum", + "ContentLabelTypeEnum", + "ConversionActionCategoryEnum", + "ConversionActionCountingTypeEnum", + "ConversionActionStatusEnum", + "ConversionActionTypeEnum", + "ConversionAdjustmentTypeEnum", + "ConversionAttributionEventTypeEnum", + "ConversionCustomVariableStatusEnum", + "ConversionCustomerTypeEnum", + "ConversionEnvironmentEnum", + "ConversionLagBucketEnum", + "ConversionOrAdjustmentLagBucketEnum", + "ConversionOriginEnum", + "ConversionTrackingStatusEnum", + "ConversionValueRulePrimaryDimensionEnum", + "ConversionValueRuleSetStatusEnum", + "ConversionValueRuleStatusEnum", + "ConvertingUserPriorEngagementTypeAndLtvBucketEnum", + "CriterionCategoryChannelAvailabilityModeEnum", + "CriterionCategoryLocaleAvailabilityModeEnum", + "CriterionSystemServingStatusEnum", + "CriterionTypeEnum", + "CustomAudienceMemberTypeEnum", + "CustomAudienceStatusEnum", + "CustomAudienceTypeEnum", + "CustomConversionGoalStatusEnum", + "CustomInterestMemberTypeEnum", + "CustomInterestStatusEnum", + "CustomInterestTypeEnum", + "CustomerAcquisitionOptimizationModeEnum", + "CustomerLifecycleOptimizationModeEnum", + "CustomerMatchUploadKeyTypeEnum", + "CustomerPayPerConversionEligibilityFailureReasonEnum", + "CustomerStatusEnum", + "CustomizerAttributeStatusEnum", + "CustomizerAttributeTypeEnum", + "CustomizerValueStatusEnum", + "DataDrivenModelStatusEnum", + "DataLinkStatusEnum", + "DataLinkTypeEnum", + "DayOfWeekEnum", + "DemandGenChannelConfigEnum", + "DemandGenChannelStrategyEnum", + "DeviceEnum", + "DisplayAdFormatSettingEnum", + "DisplayUploadProductTypeEnum", + "DistanceBucketEnum", + "EuPoliticalAdvertisingStatusEnum", + "ExperimentMetricDirectionEnum", + "ExperimentMetricEnum", + "ExperimentStatusEnum", + "ExperimentTypeEnum", + "ExternalConversionSourceEnum", + "FixedCpmGoalEnum", + "FixedCpmTargetFrequencyTimeUnitEnum", + "FrequencyCapEventTypeEnum", + "FrequencyCapLevelEnum", + "FrequencyCapTimeUnitEnum", + "GenderTypeEnum", + "GeoTargetConstantStatusEnum", + "GeoTargetingTypeEnum", + "GoalConfigLevelEnum", + "GoalOptimizationEligibilityEnum", + "GoalTypeEnum", + "GoogleAdsFieldCategoryEnum", + "GoogleAdsFieldDataTypeEnum", + "GoogleVoiceCallStatusEnum", + "HotelAssetSuggestionStatusEnum", + "HotelDateSelectionTypeEnum", + "HotelPriceBucketEnum", + "HotelRateTypeEnum", + "HotelReconciliationStatusEnum", + "IdentityVerificationProgramEnum", + "IdentityVerificationProgramStatusEnum", + "IncentiveStateEnum", + "IncomeRangeTypeEnum", + "InsightsKnowledgeGraphEntityCapabilitiesEnum", + "InsightsTrendEnum", + "InteractionEventTypeEnum", + "InteractionTypeEnum", + "InvoiceTypeEnum", + "KeywordMatchTypeEnum", + "KeywordPlanAggregateMetricTypeEnum", + "KeywordPlanCompetitionLevelEnum", + "KeywordPlanConceptGroupTypeEnum", + "KeywordPlanForecastIntervalEnum", + "KeywordPlanKeywordAnnotationEnum", + "KeywordPlanNetworkEnum", + "LabelStatusEnum", + "LandingPageSourceEnum", + "LeadFormCallToActionTypeEnum", + "LeadFormDesiredIntentEnum", + "LeadFormFieldUserInputTypeEnum", + "LeadFormPostSubmitCallToActionTypeEnum", + "LegacyAppInstallAdAppStoreEnum", + "LinkedAccountTypeEnum", + "LinkedProductTypeEnum", + "ListingGroupFilterCustomAttributeIndexEnum", + "ListingGroupFilterListingSourceEnum", + "ListingGroupFilterProductCategoryLevelEnum", + "ListingGroupFilterProductChannelEnum", + "ListingGroupFilterProductConditionEnum", + "ListingGroupFilterProductTypeLevelEnum", + "ListingGroupFilterTypeEnum", + "ListingGroupTypeEnum", + "ListingTypeEnum", + "LocalServicesBusinessRegistrationCheckRejectionReasonEnum", + "LocalServicesBusinessRegistrationTypeEnum", + "LocalServicesCreditStateEnum", + "LocalServicesEmployeeStatusEnum", + "LocalServicesEmployeeTypeEnum", + "LocalServicesInsuranceRejectionReasonEnum", + "LocalServicesLeadConversationTypeEnum", + "LocalServicesLeadCreditIssuanceDecisionEnum", + "LocalServicesLeadStatusEnum", + "LocalServicesLeadSurveyAnswerEnum", + "LocalServicesLeadSurveyDissatisfiedReasonEnum", + "LocalServicesLeadSurveySatisfiedReasonEnum", + "LocalServicesLeadTypeEnum", + "LocalServicesLicenseRejectionReasonEnum", + "LocalServicesParticipantTypeEnum", + "LocalServicesVerificationArtifactStatusEnum", + "LocalServicesVerificationArtifactTypeEnum", + "LocalServicesVerificationStatusEnum", + "LocationGroupRadiusUnitsEnum", + "LocationOwnershipTypeEnum", + "LocationSourceTypeEnum", + "LocationStringFilterTypeEnum", + "LookalikeExpansionLevelEnum", + "ManagerLinkStatusEnum", + "MatchTypeEnum", + "MediaTypeEnum", + "MessagingRestrictionTypeEnum", + "MimeTypeEnum", + "MinuteOfHourEnum", + "MobileAppVendorEnum", + "MobileDeviceTypeEnum", + "MonthOfYearEnum", + "NegativeGeoTargetTypeEnum", + "NonSkippableMaxDurationEnum", + "NonSkippableMinDurationEnum", + "OfflineConversionDiagnosticStatusEnum", + "OfflineEventUploadClientEnum", + "OfflineUserDataJobFailureReasonEnum", + "OfflineUserDataJobMatchRateRangeEnum", + "OfflineUserDataJobStatusEnum", + "OfflineUserDataJobTypeEnum", + "OperatingSystemVersionOperatorTypeEnum", + "OptimizationGoalTypeEnum", + "ParentalStatusTypeEnum", + "PartnershipOpportunityEnum", + "PaymentModeEnum", + "PerformanceMaxUpgradeStatusEnum", + "PlacementTypeEnum", + "PolicyApprovalStatusEnum", + "PolicyReviewStatusEnum", + "PolicyTopicEntryTypeEnum", + "PolicyTopicEvidenceDestinationMismatchUrlTypeEnum", + "PolicyTopicEvidenceDestinationNotWorkingDeviceEnum", + "PolicyTopicEvidenceDestinationNotWorkingDnsErrorTypeEnum", + "PositiveGeoTargetTypeEnum", + "PreviewTypeEnum", + "PriceExtensionPriceQualifierEnum", + "PriceExtensionPriceUnitEnum", + "PriceExtensionTypeEnum", + "ProductAvailabilityEnum", + "ProductCategoryLevelEnum", + "ProductCategoryStateEnum", + "ProductChannelEnum", + "ProductChannelExclusivityEnum", + "ProductConditionEnum", + "ProductCustomAttributeIndexEnum", + "ProductIssueSeverityEnum", + "ProductLinkInvitationStatusEnum", + "ProductStatusEnum", + "ProductTypeLevelEnum", + "PromotionBarcodeTypeEnum", + "PromotionExtensionDiscountModifierEnum", + "PromotionExtensionOccasionEnum", + "ProximityRadiusUnitsEnum", + "QualityScoreBucketEnum", + "ReachPlanAgeRangeEnum", + "ReachPlanBuyingMethodEnum", + "ReachPlanConversionRateModelEnum", + "ReachPlanCostModelEnum", + "ReachPlanMarketingObjectiveEnum", + "ReachPlanNetworkEnum", + "ReachPlanPlannableUserListStatusEnum", + "ReachPlanSurfaceEnum", + "RecommendationSubscriptionStatusEnum", + "RecommendationTypeEnum", + "RegulatoryFeeTypeEnum", + "ReservationRequestTypeEnum", + "ResourceChangeOperationEnum", + "ResourceLimitTypeEnum", + "ResponseContentTypeEnum", + "SearchEngineResultsPageTypeEnum", + "SearchTermMatchSourceEnum", + "SearchTermMatchTypeEnum", + "SearchTermTargetingStatusEnum", + "SeasonalityEventScopeEnum", + "SeasonalityEventStatusEnum", + "ServedAssetFieldTypeEnum", + "SharedSetStatusEnum", + "SharedSetTypeEnum", + "ShoppingAddProductsToCampaignRecommendationEnum", + "SimulationModificationMethodEnum", + "SimulationTypeEnum", + "SkAdNetworkAdEventTypeEnum", + "SkAdNetworkAttributionCreditEnum", + "SkAdNetworkCoarseConversionValueEnum", + "SkAdNetworkSourceTypeEnum", + "SkAdNetworkUserTypeEnum", + "SlotEnum", + "SmartCampaignNotEligibleReasonEnum", + "SmartCampaignStatusEnum", + "SpendingLimitTypeEnum", + "SummaryRowSettingEnum", + "SystemManagedResourceSourceEnum", + "TargetCpaOptInRecommendationGoalEnum", + "TargetFrequencyTimeUnitEnum", + "TargetImpressionShareLocationEnum", + "TargetingDimensionEnum", + "ThirdPartyBrandLiftIntegrationPartnerEnum", + "ThirdPartyBrandSafetyIntegrationPartnerEnum", + "ThirdPartyReachIntegrationPartnerEnum", + "ThirdPartyViewabilityIntegrationPartnerEnum", + "TimeTypeEnum", + "TrackingCodePageFormatEnum", + "TrackingCodeTypeEnum", + "UnitOfMeasureEnum", + "UserIdentifierSourceEnum", + "UserInterestTaxonomyTypeEnum", + "UserListAccessStatusEnum", + "UserListClosingReasonEnum", + "UserListCrmDataSourceTypeEnum", + "UserListCustomerTypeCategoryEnum", + "UserListDateRuleItemOperatorEnum", + "UserListFlexibleRuleOperatorEnum", + "UserListLogicalRuleOperatorEnum", + "UserListMembershipStatusEnum", + "UserListNumberRuleItemOperatorEnum", + "UserListPrepopulationStatusEnum", + "UserListRuleTypeEnum", + "UserListSizeRangeEnum", + "UserListStringRuleItemOperatorEnum", + "UserListTypeEnum", + "ValueRuleDeviceTypeEnum", + "ValueRuleGeoLocationMatchTypeEnum", + "ValueRuleOperationEnum", + "ValueRuleSetAttachmentTypeEnum", + "ValueRuleSetDimensionEnum", + "VanityPharmaDisplayUrlModeEnum", + "VanityPharmaTextEnum", + "VerticalAdsItemVerticalTypeEnum", + "VideoAdFormatRestrictionEnum", + "VideoAdSequenceInteractionTypeEnum", + "VideoAdSequenceMinimumDurationEnum", + "VideoEnhancementSourceEnum", + "VideoThumbnailEnum", + "WebpageConditionOperandEnum", + "WebpageConditionOperatorEnum", + "YouTubeVideoPrivacyEnum", + "YouTubeVideoPropertyEnum", + "YouTubeVideoUploadStateEnum", +) diff --git a/google/ads/googleads/v24/enums/services/__init__.py b/google/ads/googleads/v24/enums/services/__init__.py new file mode 100644 index 000000000..cbf94b283 --- /dev/null +++ b/google/ads/googleads/v24/enums/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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. +# diff --git a/google/ads/googleads/v24/enums/types/__init__.py b/google/ads/googleads/v24/enums/types/__init__.py new file mode 100644 index 000000000..36929882d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/__init__.py @@ -0,0 +1,1506 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .access_invitation_status import ( + AccessInvitationStatusEnum, +) +from .access_reason import ( + AccessReasonEnum, +) +from .access_role import ( + AccessRoleEnum, +) +from .account_budget_proposal_status import ( + AccountBudgetProposalStatusEnum, +) +from .account_budget_proposal_type import ( + AccountBudgetProposalTypeEnum, +) +from .account_budget_status import ( + AccountBudgetStatusEnum, +) +from .account_link_status import ( + AccountLinkStatusEnum, +) +from .ad_destination_type import ( + AdDestinationTypeEnum, +) +from .ad_format_type import ( + AdFormatTypeEnum, +) +from .ad_group_ad_primary_status import ( + AdGroupAdPrimaryStatusEnum, +) +from .ad_group_ad_primary_status_reason import ( + AdGroupAdPrimaryStatusReasonEnum, +) +from .ad_group_ad_rotation_mode import ( + AdGroupAdRotationModeEnum, +) +from .ad_group_ad_status import ( + AdGroupAdStatusEnum, +) +from .ad_group_criterion_approval_status import ( + AdGroupCriterionApprovalStatusEnum, +) +from .ad_group_criterion_primary_status import ( + AdGroupCriterionPrimaryStatusEnum, +) +from .ad_group_criterion_primary_status_reason import ( + AdGroupCriterionPrimaryStatusReasonEnum, +) +from .ad_group_criterion_status import ( + AdGroupCriterionStatusEnum, +) +from .ad_group_primary_status import ( + AdGroupPrimaryStatusEnum, +) +from .ad_group_primary_status_reason import ( + AdGroupPrimaryStatusReasonEnum, +) +from .ad_group_status import ( + AdGroupStatusEnum, +) +from .ad_group_type import ( + AdGroupTypeEnum, +) +from .ad_network_type import ( + AdNetworkTypeEnum, +) +from .ad_serving_optimization_status import ( + AdServingOptimizationStatusEnum, +) +from .ad_strength import ( + AdStrengthEnum, +) +from .ad_strength_action_item_type import ( + AdStrengthActionItemTypeEnum, +) +from .ad_sub_network_type import ( + AdSubNetworkTypeEnum, +) +from .ad_type import ( + AdTypeEnum, +) +from .advertising_channel_sub_type import ( + AdvertisingChannelSubTypeEnum, +) +from .advertising_channel_type import ( + AdvertisingChannelTypeEnum, +) +from .age_range_type import ( + AgeRangeTypeEnum, +) +from .android_privacy_interaction_type import ( + AndroidPrivacyInteractionTypeEnum, +) +from .android_privacy_network_type import ( + AndroidPrivacyNetworkTypeEnum, +) +from .app_bidding_goal import ( + AppBiddingGoalEnum, +) +from .app_campaign_app_store import ( + AppCampaignAppStoreEnum, +) +from .app_campaign_bidding_strategy_goal_type import ( + AppCampaignBiddingStrategyGoalTypeEnum, +) +from .app_payment_model_type import ( + AppPaymentModelTypeEnum, +) +from .app_url_operating_system_type import ( + AppUrlOperatingSystemTypeEnum, +) +from .application_instance import ( + ApplicationInstanceEnum, +) +from .asset_automation_status import ( + AssetAutomationStatusEnum, +) +from .asset_automation_type import ( + AssetAutomationTypeEnum, +) +from .asset_coverage_video_aspect_ratio_requirement import ( + AssetCoverageVideoAspectRatioRequirementEnum, +) +from .asset_field_type import ( + AssetFieldTypeEnum, +) +from .asset_group_primary_status import ( + AssetGroupPrimaryStatusEnum, +) +from .asset_group_primary_status_reason import ( + AssetGroupPrimaryStatusReasonEnum, +) +from .asset_group_signal_approval_status import ( + AssetGroupSignalApprovalStatusEnum, +) +from .asset_group_status import ( + AssetGroupStatusEnum, +) +from .asset_link_primary_status import ( + AssetLinkPrimaryStatusEnum, +) +from .asset_link_primary_status_reason import ( + AssetLinkPrimaryStatusReasonEnum, +) +from .asset_link_status import ( + AssetLinkStatusEnum, +) +from .asset_offline_evaluation_error_reasons import ( + AssetOfflineEvaluationErrorReasonsEnum, +) +from .asset_orientation import ( + AssetOrientationEnum, +) +from .asset_performance_label import ( + AssetPerformanceLabelEnum, +) +from .asset_set_asset_status import ( + AssetSetAssetStatusEnum, +) +from .asset_set_link_status import ( + AssetSetLinkStatusEnum, +) +from .asset_set_status import ( + AssetSetStatusEnum, +) +from .asset_set_type import ( + AssetSetTypeEnum, +) +from .asset_source import ( + AssetSourceEnum, +) +from .asset_type import ( + AssetTypeEnum, +) +from .async_action_status import ( + AsyncActionStatusEnum, +) +from .attribution_model import ( + AttributionModelEnum, +) +from .audience_insights_dimension import ( + AudienceInsightsDimensionEnum, +) +from .audience_insights_marketing_objective import ( + AudienceInsightsMarketingObjectiveEnum, +) +from .audience_scope import ( + AudienceScopeEnum, +) +from .audience_status import ( + AudienceStatusEnum, +) +from .batch_job_status import ( + BatchJobStatusEnum, +) +from .benchmarks_marketing_objective import ( + BenchmarksMarketingObjectiveEnum, +) +from .benchmarks_source_type import ( + BenchmarksSourceTypeEnum, +) +from .benchmarks_time_granularity import ( + BenchmarksTimeGranularityEnum, +) +from .bid_modifier_source import ( + BidModifierSourceEnum, +) +from .bidding_source import ( + BiddingSourceEnum, +) +from .bidding_strategy_status import ( + BiddingStrategyStatusEnum, +) +from .bidding_strategy_system_status import ( + BiddingStrategySystemStatusEnum, +) +from .bidding_strategy_type import ( + BiddingStrategyTypeEnum, +) +from .billing_setup_status import ( + BillingSetupStatusEnum, +) +from .booking_status import ( + BookingStatusEnum, +) +from .brand_request_rejection_reason import ( + BrandRequestRejectionReasonEnum, +) +from .brand_safety_suitability import ( + BrandSafetySuitabilityEnum, +) +from .brand_state import ( + BrandStateEnum, +) +from .budget_campaign_association_status import ( + BudgetCampaignAssociationStatusEnum, +) +from .budget_delivery_method import ( + BudgetDeliveryMethodEnum, +) +from .budget_period import ( + BudgetPeriodEnum, +) +from .budget_status import ( + BudgetStatusEnum, +) +from .budget_type import ( + BudgetTypeEnum, +) +from .business_message_call_to_action_type import ( + BusinessMessageCallToActionTypeEnum, +) +from .business_message_provider import ( + BusinessMessageProviderEnum, +) +from .call_conversion_reporting_state import ( + CallConversionReportingStateEnum, +) +from .call_to_action_type import ( + CallToActionTypeEnum, +) +from .call_tracking_display_location import ( + CallTrackingDisplayLocationEnum, +) +from .call_type import ( + CallTypeEnum, +) +from .campaign_criterion_status import ( + CampaignCriterionStatusEnum, +) +from .campaign_draft_status import ( + CampaignDraftStatusEnum, +) +from .campaign_experiment_type import ( + CampaignExperimentTypeEnum, +) +from .campaign_group_status import ( + CampaignGroupStatusEnum, +) +from .campaign_keyword_match_type import ( + CampaignKeywordMatchTypeEnum, +) +from .campaign_primary_status import ( + CampaignPrimaryStatusEnum, +) +from .campaign_primary_status_reason import ( + CampaignPrimaryStatusReasonEnum, +) +from .campaign_serving_status import ( + CampaignServingStatusEnum, +) +from .campaign_shared_set_status import ( + CampaignSharedSetStatusEnum, +) +from .campaign_status import ( + CampaignStatusEnum, +) +from .chain_relationship_type import ( + ChainRelationshipTypeEnum, +) +from .change_client_type import ( + ChangeClientTypeEnum, +) +from .change_event_resource_type import ( + ChangeEventResourceTypeEnum, +) +from .change_status_operation import ( + ChangeStatusOperationEnum, +) +from .change_status_resource_type import ( + ChangeStatusResourceTypeEnum, +) +from .click_type import ( + ClickTypeEnum, +) +from .combined_audience_status import ( + CombinedAudienceStatusEnum, +) +from .consent_status import ( + ConsentStatusEnum, +) +from .content_label_type import ( + ContentLabelTypeEnum, +) +from .conversion_action_category import ( + ConversionActionCategoryEnum, +) +from .conversion_action_counting_type import ( + ConversionActionCountingTypeEnum, +) +from .conversion_action_status import ( + ConversionActionStatusEnum, +) +from .conversion_action_type import ( + ConversionActionTypeEnum, +) +from .conversion_adjustment_type import ( + ConversionAdjustmentTypeEnum, +) +from .conversion_attribution_event_type import ( + ConversionAttributionEventTypeEnum, +) +from .conversion_custom_variable_status import ( + ConversionCustomVariableStatusEnum, +) +from .conversion_customer_type import ( + ConversionCustomerTypeEnum, +) +from .conversion_environment_enum import ( + ConversionEnvironmentEnum, +) +from .conversion_lag_bucket import ( + ConversionLagBucketEnum, +) +from .conversion_or_adjustment_lag_bucket import ( + ConversionOrAdjustmentLagBucketEnum, +) +from .conversion_origin import ( + ConversionOriginEnum, +) +from .conversion_tracking_status_enum import ( + ConversionTrackingStatusEnum, +) +from .conversion_value_rule_primary_dimension import ( + ConversionValueRulePrimaryDimensionEnum, +) +from .conversion_value_rule_set_status import ( + ConversionValueRuleSetStatusEnum, +) +from .conversion_value_rule_status import ( + ConversionValueRuleStatusEnum, +) +from .converting_user_prior_engagement_type_and_ltv_bucket import ( + ConvertingUserPriorEngagementTypeAndLtvBucketEnum, +) +from .criterion_category_channel_availability_mode import ( + CriterionCategoryChannelAvailabilityModeEnum, +) +from .criterion_category_locale_availability_mode import ( + CriterionCategoryLocaleAvailabilityModeEnum, +) +from .criterion_system_serving_status import ( + CriterionSystemServingStatusEnum, +) +from .criterion_type import ( + CriterionTypeEnum, +) +from .custom_audience_member_type import ( + CustomAudienceMemberTypeEnum, +) +from .custom_audience_status import ( + CustomAudienceStatusEnum, +) +from .custom_audience_type import ( + CustomAudienceTypeEnum, +) +from .custom_conversion_goal_status import ( + CustomConversionGoalStatusEnum, +) +from .custom_interest_member_type import ( + CustomInterestMemberTypeEnum, +) +from .custom_interest_status import ( + CustomInterestStatusEnum, +) +from .custom_interest_type import ( + CustomInterestTypeEnum, +) +from .customer_acquisition_optimization_mode import ( + CustomerAcquisitionOptimizationModeEnum, +) +from .customer_lifecycle_optimization_mode import ( + CustomerLifecycleOptimizationModeEnum, +) +from .customer_match_upload_key_type import ( + CustomerMatchUploadKeyTypeEnum, +) +from .customer_pay_per_conversion_eligibility_failure_reason import ( + CustomerPayPerConversionEligibilityFailureReasonEnum, +) +from .customer_status import ( + CustomerStatusEnum, +) +from .customizer_attribute_status import ( + CustomizerAttributeStatusEnum, +) +from .customizer_attribute_type import ( + CustomizerAttributeTypeEnum, +) +from .customizer_value_status import ( + CustomizerValueStatusEnum, +) +from .data_driven_model_status import ( + DataDrivenModelStatusEnum, +) +from .data_link_status import ( + DataLinkStatusEnum, +) +from .data_link_type import ( + DataLinkTypeEnum, +) +from .day_of_week import ( + DayOfWeekEnum, +) +from .demand_gen_channel_config import ( + DemandGenChannelConfigEnum, +) +from .demand_gen_channel_strategy import ( + DemandGenChannelStrategyEnum, +) +from .device import ( + DeviceEnum, +) +from .display_ad_format_setting import ( + DisplayAdFormatSettingEnum, +) +from .display_upload_product_type import ( + DisplayUploadProductTypeEnum, +) +from .distance_bucket import ( + DistanceBucketEnum, +) +from .eu_political_advertising_status import ( + EuPoliticalAdvertisingStatusEnum, +) +from .experiment_metric import ( + ExperimentMetricEnum, +) +from .experiment_metric_direction import ( + ExperimentMetricDirectionEnum, +) +from .experiment_status import ( + ExperimentStatusEnum, +) +from .experiment_type import ( + ExperimentTypeEnum, +) +from .external_conversion_source import ( + ExternalConversionSourceEnum, +) +from .fixed_cpm_goal import ( + FixedCpmGoalEnum, +) +from .fixed_cpm_target_frequency_time_unit import ( + FixedCpmTargetFrequencyTimeUnitEnum, +) +from .frequency_cap_event_type import ( + FrequencyCapEventTypeEnum, +) +from .frequency_cap_level import ( + FrequencyCapLevelEnum, +) +from .frequency_cap_time_unit import ( + FrequencyCapTimeUnitEnum, +) +from .gender_type import ( + GenderTypeEnum, +) +from .geo_target_constant_status import ( + GeoTargetConstantStatusEnum, +) +from .geo_targeting_type import ( + GeoTargetingTypeEnum, +) +from .goal_config_level import ( + GoalConfigLevelEnum, +) +from .goal_optimization_eligibility import ( + GoalOptimizationEligibilityEnum, +) +from .goal_type import ( + GoalTypeEnum, +) +from .google_ads_field_category import ( + GoogleAdsFieldCategoryEnum, +) +from .google_ads_field_data_type import ( + GoogleAdsFieldDataTypeEnum, +) +from .google_voice_call_status import ( + GoogleVoiceCallStatusEnum, +) +from .hotel_asset_suggestion_status import ( + HotelAssetSuggestionStatusEnum, +) +from .hotel_date_selection_type import ( + HotelDateSelectionTypeEnum, +) +from .hotel_price_bucket import ( + HotelPriceBucketEnum, +) +from .hotel_rate_type import ( + HotelRateTypeEnum, +) +from .hotel_reconciliation_status import ( + HotelReconciliationStatusEnum, +) +from .identity_verification_program import ( + IdentityVerificationProgramEnum, +) +from .identity_verification_program_status import ( + IdentityVerificationProgramStatusEnum, +) +from .incentive_state import ( + IncentiveStateEnum, +) +from .income_range_type import ( + IncomeRangeTypeEnum, +) +from .insights_knowledge_graph_entity_capabilities import ( + InsightsKnowledgeGraphEntityCapabilitiesEnum, +) +from .insights_trend import ( + InsightsTrendEnum, +) +from .interaction_event_type import ( + InteractionEventTypeEnum, +) +from .interaction_type import ( + InteractionTypeEnum, +) +from .invoice_type import ( + InvoiceTypeEnum, +) +from .keyword_match_type import ( + KeywordMatchTypeEnum, +) +from .keyword_plan_aggregate_metric_type import ( + KeywordPlanAggregateMetricTypeEnum, +) +from .keyword_plan_competition_level import ( + KeywordPlanCompetitionLevelEnum, +) +from .keyword_plan_concept_group_type import ( + KeywordPlanConceptGroupTypeEnum, +) +from .keyword_plan_forecast_interval import ( + KeywordPlanForecastIntervalEnum, +) +from .keyword_plan_keyword_annotation import ( + KeywordPlanKeywordAnnotationEnum, +) +from .keyword_plan_network import ( + KeywordPlanNetworkEnum, +) +from .label_status import ( + LabelStatusEnum, +) +from .landing_page_source import ( + LandingPageSourceEnum, +) +from .lead_form_call_to_action_type import ( + LeadFormCallToActionTypeEnum, +) +from .lead_form_desired_intent import ( + LeadFormDesiredIntentEnum, +) +from .lead_form_field_user_input_type import ( + LeadFormFieldUserInputTypeEnum, +) +from .lead_form_post_submit_call_to_action_type import ( + LeadFormPostSubmitCallToActionTypeEnum, +) +from .legacy_app_install_ad_app_store import ( + LegacyAppInstallAdAppStoreEnum, +) +from .linked_account_type import ( + LinkedAccountTypeEnum, +) +from .linked_product_type import ( + LinkedProductTypeEnum, +) +from .listing_group_filter_custom_attribute_index import ( + ListingGroupFilterCustomAttributeIndexEnum, +) +from .listing_group_filter_listing_source import ( + ListingGroupFilterListingSourceEnum, +) +from .listing_group_filter_product_category_level import ( + ListingGroupFilterProductCategoryLevelEnum, +) +from .listing_group_filter_product_channel import ( + ListingGroupFilterProductChannelEnum, +) +from .listing_group_filter_product_condition import ( + ListingGroupFilterProductConditionEnum, +) +from .listing_group_filter_product_type_level import ( + ListingGroupFilterProductTypeLevelEnum, +) +from .listing_group_filter_type_enum import ( + ListingGroupFilterTypeEnum, +) +from .listing_group_type import ( + ListingGroupTypeEnum, +) +from .listing_type import ( + ListingTypeEnum, +) +from .local_services_business_registration_check_rejection_reason import ( + LocalServicesBusinessRegistrationCheckRejectionReasonEnum, +) +from .local_services_business_registration_type import ( + LocalServicesBusinessRegistrationTypeEnum, +) +from .local_services_conversation_type import ( + LocalServicesLeadConversationTypeEnum, +) +from .local_services_employee_status import ( + LocalServicesEmployeeStatusEnum, +) +from .local_services_employee_type import ( + LocalServicesEmployeeTypeEnum, +) +from .local_services_insurance_rejection_reason import ( + LocalServicesInsuranceRejectionReasonEnum, +) +from .local_services_lead_credit_issuance_decision import ( + LocalServicesLeadCreditIssuanceDecisionEnum, +) +from .local_services_lead_credit_state import ( + LocalServicesCreditStateEnum, +) +from .local_services_lead_status import ( + LocalServicesLeadStatusEnum, +) +from .local_services_lead_survey_answer import ( + LocalServicesLeadSurveyAnswerEnum, +) +from .local_services_lead_survey_dissatisfied_reason import ( + LocalServicesLeadSurveyDissatisfiedReasonEnum, +) +from .local_services_lead_survey_satisfied_reason import ( + LocalServicesLeadSurveySatisfiedReasonEnum, +) +from .local_services_lead_type import ( + LocalServicesLeadTypeEnum, +) +from .local_services_license_rejection_reason import ( + LocalServicesLicenseRejectionReasonEnum, +) +from .local_services_participant_type import ( + LocalServicesParticipantTypeEnum, +) +from .local_services_verification_artifact_status import ( + LocalServicesVerificationArtifactStatusEnum, +) +from .local_services_verification_artifact_type import ( + LocalServicesVerificationArtifactTypeEnum, +) +from .local_services_verification_status import ( + LocalServicesVerificationStatusEnum, +) +from .location_group_radius_units import ( + LocationGroupRadiusUnitsEnum, +) +from .location_ownership_type import ( + LocationOwnershipTypeEnum, +) +from .location_source_type import ( + LocationSourceTypeEnum, +) +from .location_string_filter_type import ( + LocationStringFilterTypeEnum, +) +from .lookalike_expansion_level import ( + LookalikeExpansionLevelEnum, +) +from .manager_link_status import ( + ManagerLinkStatusEnum, +) +from .match_type import ( + MatchTypeEnum, +) +from .media_type import ( + MediaTypeEnum, +) +from .messaging_restriction_type import ( + MessagingRestrictionTypeEnum, +) +from .mime_type import ( + MimeTypeEnum, +) +from .minute_of_hour import ( + MinuteOfHourEnum, +) +from .mobile_app_vendor import ( + MobileAppVendorEnum, +) +from .mobile_device_type import ( + MobileDeviceTypeEnum, +) +from .month_of_year import ( + MonthOfYearEnum, +) +from .negative_geo_target_type import ( + NegativeGeoTargetTypeEnum, +) +from .non_skippable_max_duration import ( + NonSkippableMaxDurationEnum, +) +from .non_skippable_min_duration import ( + NonSkippableMinDurationEnum, +) +from .offline_conversion_diagnostic_status_enum import ( + OfflineConversionDiagnosticStatusEnum, +) +from .offline_event_upload_client_enum import ( + OfflineEventUploadClientEnum, +) +from .offline_user_data_job_failure_reason import ( + OfflineUserDataJobFailureReasonEnum, +) +from .offline_user_data_job_match_rate_range import ( + OfflineUserDataJobMatchRateRangeEnum, +) +from .offline_user_data_job_status import ( + OfflineUserDataJobStatusEnum, +) +from .offline_user_data_job_type import ( + OfflineUserDataJobTypeEnum, +) +from .operating_system_version_operator_type import ( + OperatingSystemVersionOperatorTypeEnum, +) +from .optimization_goal_type import ( + OptimizationGoalTypeEnum, +) +from .parental_status_type import ( + ParentalStatusTypeEnum, +) +from .partnership_opportunity import ( + PartnershipOpportunityEnum, +) +from .payment_mode import ( + PaymentModeEnum, +) +from .performance_max_upgrade_status import ( + PerformanceMaxUpgradeStatusEnum, +) +from .placement_type import ( + PlacementTypeEnum, +) +from .policy_approval_status import ( + PolicyApprovalStatusEnum, +) +from .policy_review_status import ( + PolicyReviewStatusEnum, +) +from .policy_topic_entry_type import ( + PolicyTopicEntryTypeEnum, +) +from .policy_topic_evidence_destination_mismatch_url_type import ( + PolicyTopicEvidenceDestinationMismatchUrlTypeEnum, +) +from .policy_topic_evidence_destination_not_working_device import ( + PolicyTopicEvidenceDestinationNotWorkingDeviceEnum, +) +from .policy_topic_evidence_destination_not_working_dns_error_type import ( + PolicyTopicEvidenceDestinationNotWorkingDnsErrorTypeEnum, +) +from .positive_geo_target_type import ( + PositiveGeoTargetTypeEnum, +) +from .preview_type import ( + PreviewTypeEnum, +) +from .price_extension_price_qualifier import ( + PriceExtensionPriceQualifierEnum, +) +from .price_extension_price_unit import ( + PriceExtensionPriceUnitEnum, +) +from .price_extension_type import ( + PriceExtensionTypeEnum, +) +from .product_availability import ( + ProductAvailabilityEnum, +) +from .product_category_level import ( + ProductCategoryLevelEnum, +) +from .product_category_state import ( + ProductCategoryStateEnum, +) +from .product_channel import ( + ProductChannelEnum, +) +from .product_channel_exclusivity import ( + ProductChannelExclusivityEnum, +) +from .product_condition import ( + ProductConditionEnum, +) +from .product_custom_attribute_index import ( + ProductCustomAttributeIndexEnum, +) +from .product_issue_severity import ( + ProductIssueSeverityEnum, +) +from .product_link_invitation_status import ( + ProductLinkInvitationStatusEnum, +) +from .product_status import ( + ProductStatusEnum, +) +from .product_type_level import ( + ProductTypeLevelEnum, +) +from .promotion_barcode_type import ( + PromotionBarcodeTypeEnum, +) +from .promotion_extension_discount_modifier import ( + PromotionExtensionDiscountModifierEnum, +) +from .promotion_extension_occasion import ( + PromotionExtensionOccasionEnum, +) +from .proximity_radius_units import ( + ProximityRadiusUnitsEnum, +) +from .quality_score_bucket import ( + QualityScoreBucketEnum, +) +from .reach_plan_age_range import ( + ReachPlanAgeRangeEnum, +) +from .reach_plan_buying_method import ( + ReachPlanBuyingMethodEnum, +) +from .reach_plan_conversion_rate_model import ( + ReachPlanConversionRateModelEnum, +) +from .reach_plan_cost_model import ( + ReachPlanCostModelEnum, +) +from .reach_plan_marketing_objective import ( + ReachPlanMarketingObjectiveEnum, +) +from .reach_plan_network import ( + ReachPlanNetworkEnum, +) +from .reach_plan_plannable_user_list_status import ( + ReachPlanPlannableUserListStatusEnum, +) +from .reach_plan_surface import ( + ReachPlanSurfaceEnum, +) +from .recommendation_subscription_status import ( + RecommendationSubscriptionStatusEnum, +) +from .recommendation_type import ( + RecommendationTypeEnum, +) +from .regulatory_fee_type import ( + RegulatoryFeeTypeEnum, +) +from .reservation_request_type import ( + ReservationRequestTypeEnum, +) +from .resource_change_operation import ( + ResourceChangeOperationEnum, +) +from .resource_limit_type import ( + ResourceLimitTypeEnum, +) +from .response_content_type import ( + ResponseContentTypeEnum, +) +from .search_engine_results_page_type import ( + SearchEngineResultsPageTypeEnum, +) +from .search_term_match_source import ( + SearchTermMatchSourceEnum, +) +from .search_term_match_type import ( + SearchTermMatchTypeEnum, +) +from .search_term_targeting_status import ( + SearchTermTargetingStatusEnum, +) +from .seasonality_event_scope import ( + SeasonalityEventScopeEnum, +) +from .seasonality_event_status import ( + SeasonalityEventStatusEnum, +) +from .served_asset_field_type import ( + ServedAssetFieldTypeEnum, +) +from .shared_set_status import ( + SharedSetStatusEnum, +) +from .shared_set_type import ( + SharedSetTypeEnum, +) +from .shopping_add_products_to_campaign_recommendation_enum import ( + ShoppingAddProductsToCampaignRecommendationEnum, +) +from .simulation_modification_method import ( + SimulationModificationMethodEnum, +) +from .simulation_type import ( + SimulationTypeEnum, +) +from .sk_ad_network_ad_event_type import ( + SkAdNetworkAdEventTypeEnum, +) +from .sk_ad_network_attribution_credit import ( + SkAdNetworkAttributionCreditEnum, +) +from .sk_ad_network_coarse_conversion_value import ( + SkAdNetworkCoarseConversionValueEnum, +) +from .sk_ad_network_source_type import ( + SkAdNetworkSourceTypeEnum, +) +from .sk_ad_network_user_type import ( + SkAdNetworkUserTypeEnum, +) +from .slot import ( + SlotEnum, +) +from .smart_campaign_not_eligible_reason import ( + SmartCampaignNotEligibleReasonEnum, +) +from .smart_campaign_status import ( + SmartCampaignStatusEnum, +) +from .spending_limit_type import ( + SpendingLimitTypeEnum, +) +from .summary_row_setting import ( + SummaryRowSettingEnum, +) +from .system_managed_entity_source import ( + SystemManagedResourceSourceEnum, +) +from .target_cpa_opt_in_recommendation_goal import ( + TargetCpaOptInRecommendationGoalEnum, +) +from .target_frequency_time_unit import ( + TargetFrequencyTimeUnitEnum, +) +from .target_impression_share_location import ( + TargetImpressionShareLocationEnum, +) +from .targeting_dimension import ( + TargetingDimensionEnum, +) +from .third_party_brand_lift_integration_partner import ( + ThirdPartyBrandLiftIntegrationPartnerEnum, +) +from .third_party_brand_safety_integration_partner import ( + ThirdPartyBrandSafetyIntegrationPartnerEnum, +) +from .third_party_reach_integration_partner import ( + ThirdPartyReachIntegrationPartnerEnum, +) +from .third_party_viewability_integration_partner import ( + ThirdPartyViewabilityIntegrationPartnerEnum, +) +from .time_type import ( + TimeTypeEnum, +) +from .tracking_code_page_format import ( + TrackingCodePageFormatEnum, +) +from .tracking_code_type import ( + TrackingCodeTypeEnum, +) +from .unit_of_measure import ( + UnitOfMeasureEnum, +) +from .user_identifier_source import ( + UserIdentifierSourceEnum, +) +from .user_interest_taxonomy_type import ( + UserInterestTaxonomyTypeEnum, +) +from .user_list_access_status import ( + UserListAccessStatusEnum, +) +from .user_list_closing_reason import ( + UserListClosingReasonEnum, +) +from .user_list_crm_data_source_type import ( + UserListCrmDataSourceTypeEnum, +) +from .user_list_customer_type_category import ( + UserListCustomerTypeCategoryEnum, +) +from .user_list_date_rule_item_operator import ( + UserListDateRuleItemOperatorEnum, +) +from .user_list_flexible_rule_operator import ( + UserListFlexibleRuleOperatorEnum, +) +from .user_list_logical_rule_operator import ( + UserListLogicalRuleOperatorEnum, +) +from .user_list_membership_status import ( + UserListMembershipStatusEnum, +) +from .user_list_number_rule_item_operator import ( + UserListNumberRuleItemOperatorEnum, +) +from .user_list_prepopulation_status import ( + UserListPrepopulationStatusEnum, +) +from .user_list_rule_type import ( + UserListRuleTypeEnum, +) +from .user_list_size_range import ( + UserListSizeRangeEnum, +) +from .user_list_string_rule_item_operator import ( + UserListStringRuleItemOperatorEnum, +) +from .user_list_type import ( + UserListTypeEnum, +) +from .value_rule_device_type import ( + ValueRuleDeviceTypeEnum, +) +from .value_rule_geo_location_match_type import ( + ValueRuleGeoLocationMatchTypeEnum, +) +from .value_rule_operation import ( + ValueRuleOperationEnum, +) +from .value_rule_set_attachment_type import ( + ValueRuleSetAttachmentTypeEnum, +) +from .value_rule_set_dimension import ( + ValueRuleSetDimensionEnum, +) +from .vanity_pharma_display_url_mode import ( + VanityPharmaDisplayUrlModeEnum, +) +from .vanity_pharma_text import ( + VanityPharmaTextEnum, +) +from .vertical_ads_item_vertical_type import ( + VerticalAdsItemVerticalTypeEnum, +) +from .video_ad_format_restriction import ( + VideoAdFormatRestrictionEnum, +) +from .video_ad_sequence_interaction_type import ( + VideoAdSequenceInteractionTypeEnum, +) +from .video_ad_sequence_minimum_duration import ( + VideoAdSequenceMinimumDurationEnum, +) +from .video_enhancement_source import ( + VideoEnhancementSourceEnum, +) +from .video_thumbnail import ( + VideoThumbnailEnum, +) +from .webpage_condition_operand import ( + WebpageConditionOperandEnum, +) +from .webpage_condition_operator import ( + WebpageConditionOperatorEnum, +) +from .youtube_video_privacy import ( + YouTubeVideoPrivacyEnum, +) +from .youtube_video_property import ( + YouTubeVideoPropertyEnum, +) +from .youtube_video_upload_state import ( + YouTubeVideoUploadStateEnum, +) + +__all__ = ( + "AccessInvitationStatusEnum", + "AccessReasonEnum", + "AccessRoleEnum", + "AccountBudgetProposalStatusEnum", + "AccountBudgetProposalTypeEnum", + "AccountBudgetStatusEnum", + "AccountLinkStatusEnum", + "AdDestinationTypeEnum", + "AdFormatTypeEnum", + "AdGroupAdPrimaryStatusEnum", + "AdGroupAdPrimaryStatusReasonEnum", + "AdGroupAdRotationModeEnum", + "AdGroupAdStatusEnum", + "AdGroupCriterionApprovalStatusEnum", + "AdGroupCriterionPrimaryStatusEnum", + "AdGroupCriterionPrimaryStatusReasonEnum", + "AdGroupCriterionStatusEnum", + "AdGroupPrimaryStatusEnum", + "AdGroupPrimaryStatusReasonEnum", + "AdGroupStatusEnum", + "AdGroupTypeEnum", + "AdNetworkTypeEnum", + "AdServingOptimizationStatusEnum", + "AdStrengthEnum", + "AdStrengthActionItemTypeEnum", + "AdSubNetworkTypeEnum", + "AdTypeEnum", + "AdvertisingChannelSubTypeEnum", + "AdvertisingChannelTypeEnum", + "AgeRangeTypeEnum", + "AndroidPrivacyInteractionTypeEnum", + "AndroidPrivacyNetworkTypeEnum", + "AppBiddingGoalEnum", + "AppCampaignAppStoreEnum", + "AppCampaignBiddingStrategyGoalTypeEnum", + "AppPaymentModelTypeEnum", + "AppUrlOperatingSystemTypeEnum", + "ApplicationInstanceEnum", + "AssetAutomationStatusEnum", + "AssetAutomationTypeEnum", + "AssetCoverageVideoAspectRatioRequirementEnum", + "AssetFieldTypeEnum", + "AssetGroupPrimaryStatusEnum", + "AssetGroupPrimaryStatusReasonEnum", + "AssetGroupSignalApprovalStatusEnum", + "AssetGroupStatusEnum", + "AssetLinkPrimaryStatusEnum", + "AssetLinkPrimaryStatusReasonEnum", + "AssetLinkStatusEnum", + "AssetOfflineEvaluationErrorReasonsEnum", + "AssetOrientationEnum", + "AssetPerformanceLabelEnum", + "AssetSetAssetStatusEnum", + "AssetSetLinkStatusEnum", + "AssetSetStatusEnum", + "AssetSetTypeEnum", + "AssetSourceEnum", + "AssetTypeEnum", + "AsyncActionStatusEnum", + "AttributionModelEnum", + "AudienceInsightsDimensionEnum", + "AudienceInsightsMarketingObjectiveEnum", + "AudienceScopeEnum", + "AudienceStatusEnum", + "BatchJobStatusEnum", + "BenchmarksMarketingObjectiveEnum", + "BenchmarksSourceTypeEnum", + "BenchmarksTimeGranularityEnum", + "BidModifierSourceEnum", + "BiddingSourceEnum", + "BiddingStrategyStatusEnum", + "BiddingStrategySystemStatusEnum", + "BiddingStrategyTypeEnum", + "BillingSetupStatusEnum", + "BookingStatusEnum", + "BrandRequestRejectionReasonEnum", + "BrandSafetySuitabilityEnum", + "BrandStateEnum", + "BudgetCampaignAssociationStatusEnum", + "BudgetDeliveryMethodEnum", + "BudgetPeriodEnum", + "BudgetStatusEnum", + "BudgetTypeEnum", + "BusinessMessageCallToActionTypeEnum", + "BusinessMessageProviderEnum", + "CallConversionReportingStateEnum", + "CallToActionTypeEnum", + "CallTrackingDisplayLocationEnum", + "CallTypeEnum", + "CampaignCriterionStatusEnum", + "CampaignDraftStatusEnum", + "CampaignExperimentTypeEnum", + "CampaignGroupStatusEnum", + "CampaignKeywordMatchTypeEnum", + "CampaignPrimaryStatusEnum", + "CampaignPrimaryStatusReasonEnum", + "CampaignServingStatusEnum", + "CampaignSharedSetStatusEnum", + "CampaignStatusEnum", + "ChainRelationshipTypeEnum", + "ChangeClientTypeEnum", + "ChangeEventResourceTypeEnum", + "ChangeStatusOperationEnum", + "ChangeStatusResourceTypeEnum", + "ClickTypeEnum", + "CombinedAudienceStatusEnum", + "ConsentStatusEnum", + "ContentLabelTypeEnum", + "ConversionActionCategoryEnum", + "ConversionActionCountingTypeEnum", + "ConversionActionStatusEnum", + "ConversionActionTypeEnum", + "ConversionAdjustmentTypeEnum", + "ConversionAttributionEventTypeEnum", + "ConversionCustomVariableStatusEnum", + "ConversionCustomerTypeEnum", + "ConversionEnvironmentEnum", + "ConversionLagBucketEnum", + "ConversionOrAdjustmentLagBucketEnum", + "ConversionOriginEnum", + "ConversionTrackingStatusEnum", + "ConversionValueRulePrimaryDimensionEnum", + "ConversionValueRuleSetStatusEnum", + "ConversionValueRuleStatusEnum", + "ConvertingUserPriorEngagementTypeAndLtvBucketEnum", + "CriterionCategoryChannelAvailabilityModeEnum", + "CriterionCategoryLocaleAvailabilityModeEnum", + "CriterionSystemServingStatusEnum", + "CriterionTypeEnum", + "CustomAudienceMemberTypeEnum", + "CustomAudienceStatusEnum", + "CustomAudienceTypeEnum", + "CustomConversionGoalStatusEnum", + "CustomInterestMemberTypeEnum", + "CustomInterestStatusEnum", + "CustomInterestTypeEnum", + "CustomerAcquisitionOptimizationModeEnum", + "CustomerLifecycleOptimizationModeEnum", + "CustomerMatchUploadKeyTypeEnum", + "CustomerPayPerConversionEligibilityFailureReasonEnum", + "CustomerStatusEnum", + "CustomizerAttributeStatusEnum", + "CustomizerAttributeTypeEnum", + "CustomizerValueStatusEnum", + "DataDrivenModelStatusEnum", + "DataLinkStatusEnum", + "DataLinkTypeEnum", + "DayOfWeekEnum", + "DemandGenChannelConfigEnum", + "DemandGenChannelStrategyEnum", + "DeviceEnum", + "DisplayAdFormatSettingEnum", + "DisplayUploadProductTypeEnum", + "DistanceBucketEnum", + "EuPoliticalAdvertisingStatusEnum", + "ExperimentMetricEnum", + "ExperimentMetricDirectionEnum", + "ExperimentStatusEnum", + "ExperimentTypeEnum", + "ExternalConversionSourceEnum", + "FixedCpmGoalEnum", + "FixedCpmTargetFrequencyTimeUnitEnum", + "FrequencyCapEventTypeEnum", + "FrequencyCapLevelEnum", + "FrequencyCapTimeUnitEnum", + "GenderTypeEnum", + "GeoTargetConstantStatusEnum", + "GeoTargetingTypeEnum", + "GoalConfigLevelEnum", + "GoalOptimizationEligibilityEnum", + "GoalTypeEnum", + "GoogleAdsFieldCategoryEnum", + "GoogleAdsFieldDataTypeEnum", + "GoogleVoiceCallStatusEnum", + "HotelAssetSuggestionStatusEnum", + "HotelDateSelectionTypeEnum", + "HotelPriceBucketEnum", + "HotelRateTypeEnum", + "HotelReconciliationStatusEnum", + "IdentityVerificationProgramEnum", + "IdentityVerificationProgramStatusEnum", + "IncentiveStateEnum", + "IncomeRangeTypeEnum", + "InsightsKnowledgeGraphEntityCapabilitiesEnum", + "InsightsTrendEnum", + "InteractionEventTypeEnum", + "InteractionTypeEnum", + "InvoiceTypeEnum", + "KeywordMatchTypeEnum", + "KeywordPlanAggregateMetricTypeEnum", + "KeywordPlanCompetitionLevelEnum", + "KeywordPlanConceptGroupTypeEnum", + "KeywordPlanForecastIntervalEnum", + "KeywordPlanKeywordAnnotationEnum", + "KeywordPlanNetworkEnum", + "LabelStatusEnum", + "LandingPageSourceEnum", + "LeadFormCallToActionTypeEnum", + "LeadFormDesiredIntentEnum", + "LeadFormFieldUserInputTypeEnum", + "LeadFormPostSubmitCallToActionTypeEnum", + "LegacyAppInstallAdAppStoreEnum", + "LinkedAccountTypeEnum", + "LinkedProductTypeEnum", + "ListingGroupFilterCustomAttributeIndexEnum", + "ListingGroupFilterListingSourceEnum", + "ListingGroupFilterProductCategoryLevelEnum", + "ListingGroupFilterProductChannelEnum", + "ListingGroupFilterProductConditionEnum", + "ListingGroupFilterProductTypeLevelEnum", + "ListingGroupFilterTypeEnum", + "ListingGroupTypeEnum", + "ListingTypeEnum", + "LocalServicesBusinessRegistrationCheckRejectionReasonEnum", + "LocalServicesBusinessRegistrationTypeEnum", + "LocalServicesLeadConversationTypeEnum", + "LocalServicesEmployeeStatusEnum", + "LocalServicesEmployeeTypeEnum", + "LocalServicesInsuranceRejectionReasonEnum", + "LocalServicesLeadCreditIssuanceDecisionEnum", + "LocalServicesCreditStateEnum", + "LocalServicesLeadStatusEnum", + "LocalServicesLeadSurveyAnswerEnum", + "LocalServicesLeadSurveyDissatisfiedReasonEnum", + "LocalServicesLeadSurveySatisfiedReasonEnum", + "LocalServicesLeadTypeEnum", + "LocalServicesLicenseRejectionReasonEnum", + "LocalServicesParticipantTypeEnum", + "LocalServicesVerificationArtifactStatusEnum", + "LocalServicesVerificationArtifactTypeEnum", + "LocalServicesVerificationStatusEnum", + "LocationGroupRadiusUnitsEnum", + "LocationOwnershipTypeEnum", + "LocationSourceTypeEnum", + "LocationStringFilterTypeEnum", + "LookalikeExpansionLevelEnum", + "ManagerLinkStatusEnum", + "MatchTypeEnum", + "MediaTypeEnum", + "MessagingRestrictionTypeEnum", + "MimeTypeEnum", + "MinuteOfHourEnum", + "MobileAppVendorEnum", + "MobileDeviceTypeEnum", + "MonthOfYearEnum", + "NegativeGeoTargetTypeEnum", + "NonSkippableMaxDurationEnum", + "NonSkippableMinDurationEnum", + "OfflineConversionDiagnosticStatusEnum", + "OfflineEventUploadClientEnum", + "OfflineUserDataJobFailureReasonEnum", + "OfflineUserDataJobMatchRateRangeEnum", + "OfflineUserDataJobStatusEnum", + "OfflineUserDataJobTypeEnum", + "OperatingSystemVersionOperatorTypeEnum", + "OptimizationGoalTypeEnum", + "ParentalStatusTypeEnum", + "PartnershipOpportunityEnum", + "PaymentModeEnum", + "PerformanceMaxUpgradeStatusEnum", + "PlacementTypeEnum", + "PolicyApprovalStatusEnum", + "PolicyReviewStatusEnum", + "PolicyTopicEntryTypeEnum", + "PolicyTopicEvidenceDestinationMismatchUrlTypeEnum", + "PolicyTopicEvidenceDestinationNotWorkingDeviceEnum", + "PolicyTopicEvidenceDestinationNotWorkingDnsErrorTypeEnum", + "PositiveGeoTargetTypeEnum", + "PreviewTypeEnum", + "PriceExtensionPriceQualifierEnum", + "PriceExtensionPriceUnitEnum", + "PriceExtensionTypeEnum", + "ProductAvailabilityEnum", + "ProductCategoryLevelEnum", + "ProductCategoryStateEnum", + "ProductChannelEnum", + "ProductChannelExclusivityEnum", + "ProductConditionEnum", + "ProductCustomAttributeIndexEnum", + "ProductIssueSeverityEnum", + "ProductLinkInvitationStatusEnum", + "ProductStatusEnum", + "ProductTypeLevelEnum", + "PromotionBarcodeTypeEnum", + "PromotionExtensionDiscountModifierEnum", + "PromotionExtensionOccasionEnum", + "ProximityRadiusUnitsEnum", + "QualityScoreBucketEnum", + "ReachPlanAgeRangeEnum", + "ReachPlanBuyingMethodEnum", + "ReachPlanConversionRateModelEnum", + "ReachPlanCostModelEnum", + "ReachPlanMarketingObjectiveEnum", + "ReachPlanNetworkEnum", + "ReachPlanPlannableUserListStatusEnum", + "ReachPlanSurfaceEnum", + "RecommendationSubscriptionStatusEnum", + "RecommendationTypeEnum", + "RegulatoryFeeTypeEnum", + "ReservationRequestTypeEnum", + "ResourceChangeOperationEnum", + "ResourceLimitTypeEnum", + "ResponseContentTypeEnum", + "SearchEngineResultsPageTypeEnum", + "SearchTermMatchSourceEnum", + "SearchTermMatchTypeEnum", + "SearchTermTargetingStatusEnum", + "SeasonalityEventScopeEnum", + "SeasonalityEventStatusEnum", + "ServedAssetFieldTypeEnum", + "SharedSetStatusEnum", + "SharedSetTypeEnum", + "ShoppingAddProductsToCampaignRecommendationEnum", + "SimulationModificationMethodEnum", + "SimulationTypeEnum", + "SkAdNetworkAdEventTypeEnum", + "SkAdNetworkAttributionCreditEnum", + "SkAdNetworkCoarseConversionValueEnum", + "SkAdNetworkSourceTypeEnum", + "SkAdNetworkUserTypeEnum", + "SlotEnum", + "SmartCampaignNotEligibleReasonEnum", + "SmartCampaignStatusEnum", + "SpendingLimitTypeEnum", + "SummaryRowSettingEnum", + "SystemManagedResourceSourceEnum", + "TargetCpaOptInRecommendationGoalEnum", + "TargetFrequencyTimeUnitEnum", + "TargetImpressionShareLocationEnum", + "TargetingDimensionEnum", + "ThirdPartyBrandLiftIntegrationPartnerEnum", + "ThirdPartyBrandSafetyIntegrationPartnerEnum", + "ThirdPartyReachIntegrationPartnerEnum", + "ThirdPartyViewabilityIntegrationPartnerEnum", + "TimeTypeEnum", + "TrackingCodePageFormatEnum", + "TrackingCodeTypeEnum", + "UnitOfMeasureEnum", + "UserIdentifierSourceEnum", + "UserInterestTaxonomyTypeEnum", + "UserListAccessStatusEnum", + "UserListClosingReasonEnum", + "UserListCrmDataSourceTypeEnum", + "UserListCustomerTypeCategoryEnum", + "UserListDateRuleItemOperatorEnum", + "UserListFlexibleRuleOperatorEnum", + "UserListLogicalRuleOperatorEnum", + "UserListMembershipStatusEnum", + "UserListNumberRuleItemOperatorEnum", + "UserListPrepopulationStatusEnum", + "UserListRuleTypeEnum", + "UserListSizeRangeEnum", + "UserListStringRuleItemOperatorEnum", + "UserListTypeEnum", + "ValueRuleDeviceTypeEnum", + "ValueRuleGeoLocationMatchTypeEnum", + "ValueRuleOperationEnum", + "ValueRuleSetAttachmentTypeEnum", + "ValueRuleSetDimensionEnum", + "VanityPharmaDisplayUrlModeEnum", + "VanityPharmaTextEnum", + "VerticalAdsItemVerticalTypeEnum", + "VideoAdFormatRestrictionEnum", + "VideoAdSequenceInteractionTypeEnum", + "VideoAdSequenceMinimumDurationEnum", + "VideoEnhancementSourceEnum", + "VideoThumbnailEnum", + "WebpageConditionOperandEnum", + "WebpageConditionOperatorEnum", + "YouTubeVideoPrivacyEnum", + "YouTubeVideoPropertyEnum", + "YouTubeVideoUploadStateEnum", +) diff --git a/google/ads/googleads/v24/enums/types/access_invitation_status.py b/google/ads/googleads/v24/enums/types/access_invitation_status.py new file mode 100644 index 000000000..0aca459b0 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/access_invitation_status.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AccessInvitationStatusEnum", + }, +) + + +class AccessInvitationStatusEnum(proto.Message): + r"""Container for enum for identifying the status of access + invitation + + """ + + class AccessInvitationStatus(proto.Enum): + r"""Possible access invitation status of a user + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PENDING (2): + The initial state of an invitation, before + being acted upon by anyone. + DECLINED (3): + Invitation process was terminated by the + email recipient. No new user was created. + EXPIRED (4): + Invitation URLs expired without being acted + upon. No new user can be created. Invitations + expire 20 days after creation. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + DECLINED = 3 + EXPIRED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/access_reason.py b/google/ads/googleads/v24/enums/types/access_reason.py new file mode 100644 index 000000000..9b11160fc --- /dev/null +++ b/google/ads/googleads/v24/enums/types/access_reason.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AccessReasonEnum", + }, +) + + +class AccessReasonEnum(proto.Message): + r"""Indicates the way the resource such as user list is related + to a user. + + """ + + class AccessReason(proto.Enum): + r"""Enum describing possible access reasons. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + OWNED (2): + The resource is owned by the user. + SHARED (3): + The resource is shared to the user. + LICENSED (4): + The resource is licensed to the user. + SUBSCRIBED (5): + The user subscribed to the resource. + AFFILIATED (6): + The resource is accessible to the user. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + OWNED = 2 + SHARED = 3 + LICENSED = 4 + SUBSCRIBED = 5 + AFFILIATED = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/access_role.py b/google/ads/googleads/v24/enums/types/access_role.py new file mode 100644 index 000000000..9779692d2 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/access_role.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AccessRoleEnum", + }, +) + + +class AccessRoleEnum(proto.Message): + r"""Container for enum describing possible access role for user.""" + + class AccessRole(proto.Enum): + r"""Possible access role of a user. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ADMIN (2): + Owns its account and can control the addition + of other users. + STANDARD (3): + Can modify campaigns, but can't affect other + users. + READ_ONLY (4): + Can view campaigns and account changes, but + cannot make edits. + EMAIL_ONLY (5): + Role for \"email only\" access. Represents an + email recipient rather than a true User entity. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ADMIN = 2 + STANDARD = 3 + READ_ONLY = 4 + EMAIL_ONLY = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/account_budget_proposal_status.py b/google/ads/googleads/v24/enums/types/account_budget_proposal_status.py new file mode 100644 index 000000000..480b1750d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/account_budget_proposal_status.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AccountBudgetProposalStatusEnum", + }, +) + + +class AccountBudgetProposalStatusEnum(proto.Message): + r"""Message describing AccountBudgetProposal statuses.""" + + class AccountBudgetProposalStatus(proto.Enum): + r"""The possible statuses of an AccountBudgetProposal. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PENDING (2): + The proposal is pending approval. + APPROVED_HELD (3): + The proposal has been approved but the + corresponding billing setup has not. This can + occur for proposals that set up the first budget + when signing up for billing or when performing a + change of bill-to operation. + APPROVED (4): + The proposal has been approved. + CANCELLED (5): + The proposal has been cancelled by the user. + REJECTED (6): + The proposal has been rejected by the user, + for example, by rejecting an acceptance email. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + APPROVED_HELD = 3 + APPROVED = 4 + CANCELLED = 5 + REJECTED = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/account_budget_proposal_type.py b/google/ads/googleads/v24/enums/types/account_budget_proposal_type.py new file mode 100644 index 000000000..f35e5f8c1 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/account_budget_proposal_type.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AccountBudgetProposalTypeEnum", + }, +) + + +class AccountBudgetProposalTypeEnum(proto.Message): + r"""Message describing AccountBudgetProposal types.""" + + class AccountBudgetProposalType(proto.Enum): + r"""The possible types of an AccountBudgetProposal. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CREATE (2): + Identifies a request to create a new budget. + UPDATE (3): + Identifies a request to edit an existing + budget. + END (4): + Identifies a request to end a budget that has + already started. + REMOVE (5): + Identifies a request to remove a budget that + hasn't started yet. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CREATE = 2 + UPDATE = 3 + END = 4 + REMOVE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/account_budget_status.py b/google/ads/googleads/v24/enums/types/account_budget_status.py new file mode 100644 index 000000000..2543821c0 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/account_budget_status.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AccountBudgetStatusEnum", + }, +) + + +class AccountBudgetStatusEnum(proto.Message): + r"""Message describing AccountBudget statuses.""" + + class AccountBudgetStatus(proto.Enum): + r"""The possible statuses of an AccountBudget. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PENDING (2): + The account budget is pending approval. + APPROVED (3): + The account budget has been approved. + CANCELLED (4): + The account budget has been cancelled by the + user. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + APPROVED = 3 + CANCELLED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/account_link_status.py b/google/ads/googleads/v24/enums/types/account_link_status.py new file mode 100644 index 000000000..8c90eec16 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/account_link_status.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AccountLinkStatusEnum", + }, +) + + +class AccountLinkStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of an account + link. + + """ + + class AccountLinkStatus(proto.Enum): + r"""Describes the possible statuses for a link between a Google + Ads customer and another account. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + The link is enabled. + REMOVED (3): + The link is removed/disabled. + REQUESTED (4): + The link to the other account has been + requested. A user on the other account may now + approve the link by setting the status to + ENABLED. + PENDING_APPROVAL (5): + This link has been requested by a user on the + other account. It may be approved by a user on + this account by setting the status to ENABLED. + REJECTED (6): + The link is rejected by the approver. + REVOKED (7): + The link is revoked by the user who requested + the link. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + REQUESTED = 4 + PENDING_APPROVAL = 5 + REJECTED = 6 + REVOKED = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_destination_type.py b/google/ads/googleads/v24/enums/types/ad_destination_type.py new file mode 100644 index 000000000..f80785c8e --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_destination_type.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdDestinationTypeEnum", + }, +) + + +class AdDestinationTypeEnum(proto.Message): + r"""Container for enumeration of Google Ads destination types.""" + + class AdDestinationType(proto.Enum): + r"""Enumerates Google Ads destination types + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + NOT_APPLICABLE (2): + Ads that don't intend to drive users off from + ads to other destinations + WEBSITE (3): + Website + APP_DEEP_LINK (4): + App Deep Link + APP_STORE (5): + iOS App Store or Play Store + PHONE_CALL (6): + Call Dialer + MAP_DIRECTIONS (7): + Map App + LOCATION_LISTING (8): + Location Dedicated Page + MESSAGE (9): + Text Message + LEAD_FORM (10): + Lead Generation Form + YOUTUBE (11): + YouTube + UNMODELED_FOR_CONVERSIONS (12): + Ad Destination for Conversions with keys + unknown + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NOT_APPLICABLE = 2 + WEBSITE = 3 + APP_DEEP_LINK = 4 + APP_STORE = 5 + PHONE_CALL = 6 + MAP_DIRECTIONS = 7 + LOCATION_LISTING = 8 + MESSAGE = 9 + LEAD_FORM = 10 + YOUTUBE = 11 + UNMODELED_FOR_CONVERSIONS = 12 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_format_type.py b/google/ads/googleads/v24/enums/types/ad_format_type.py new file mode 100644 index 000000000..8f60d3325 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_format_type.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdFormatTypeEnum", + }, +) + + +class AdFormatTypeEnum(proto.Message): + r"""Container for enumeration of Google Ads format types.""" + + class AdFormatType(proto.Enum): + r"""Enumerates Google Ads format types. + + Note that this segmentation is available only for Video and + Demand Gen campaigns. For assets, only video assets are + supported. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + OTHER (2): + Value assigned to formats (such as + experimental formats) which don't support format + segmentation in Video and Demand Gen campaigns. + + Note that these formats may change categories in + the future, for example if an experimental + format is exposed or a new format is added. We + strongly recommend to not rely on this field for + long term decisions. + UNSEGMENTED (3): + Value assigned for Video TrueView for Action + campaigns statistics. + Note that statistics with this value may change + categories in the future, for example if format + segmentation support is added for new campaign + types. We strongly recommend to not rely on this + field for long term decisions. + INSTREAM_SKIPPABLE (4): + Skippable in-stream ads. + INSTREAM_NON_SKIPPABLE (5): + Non-skippable in-stream ads. + INFEED (6): + In-feed YouTube or image ads served on feed + surfaces (e.g. Discover Feed, YouTube Home, + etc.). + BUMPER (7): + Short (<7 secs) in-stream non-skippable + YouTube ads. + OUTSTREAM (8): + Outstream ads. + MASTHEAD (9): + Masthead ads. + AUDIO (10): + Audio ads. + SHORTS (11): + Vertical full-screen video or image ads + served on YouTube Shorts or BrandConnect ads + served as organic YouTube Shorts. + PAUSE (12): + Image ads served when a user pauses an + organic YouTube video on a TV screen. These ads + are displayed directly next to the static video + frame on the pause screen itself. Note that this + does not include Demand Gen image ads served on + the ad panel below or on top of a paused organic + video. Those are reported under INFEED. + VERTICAL_ADS_PROMOTION (13): + An ad format that promotes a specific entity + within a vertical, for example, a hotel ad in + the Travel vertical on Search. + VERTICAL_ADS_BOOKING_LINK (14): + An ad format for a booking link + call-to-action within a vertical ad, for example + a 'Book Now' link for a hotel ad. + TEXT (15): + A standard text ad format. This is currently + only used for ads on the Search network. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + OTHER = 2 + UNSEGMENTED = 3 + INSTREAM_SKIPPABLE = 4 + INSTREAM_NON_SKIPPABLE = 5 + INFEED = 6 + BUMPER = 7 + OUTSTREAM = 8 + MASTHEAD = 9 + AUDIO = 10 + SHORTS = 11 + PAUSE = 12 + VERTICAL_ADS_PROMOTION = 13 + VERTICAL_ADS_BOOKING_LINK = 14 + TEXT = 15 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_group_ad_primary_status.py b/google/ads/googleads/v24/enums/types/ad_group_ad_primary_status.py new file mode 100644 index 000000000..95f91845a --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_group_ad_primary_status.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupAdPrimaryStatusEnum", + }, +) + + +class AdGroupAdPrimaryStatusEnum(proto.Message): + r"""Ad Group Ad Primary Status. Provides insight into why an ad + group ad is not serving or not serving optimally. + + """ + + class AdGroupAdPrimaryStatus(proto.Enum): + r"""The possible statuses of an AdGroupAd. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ELIGIBLE (2): + The ad group ad is eligible to serve. + PAUSED (3): + The ad group ad is paused. + REMOVED (4): + The ad group ad is removed. + PENDING (5): + The ad cannot serve now, but may serve later + without advertiser action. + LIMITED (6): + The ad group ad is serving in a limited + capacity. + NOT_ELIGIBLE (7): + The ad group ad is not eligible to serve. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ELIGIBLE = 2 + PAUSED = 3 + REMOVED = 4 + PENDING = 5 + LIMITED = 6 + NOT_ELIGIBLE = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_group_ad_primary_status_reason.py b/google/ads/googleads/v24/enums/types/ad_group_ad_primary_status_reason.py new file mode 100644 index 000000000..0743fee85 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_group_ad_primary_status_reason.py @@ -0,0 +1,121 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupAdPrimaryStatusReasonEnum", + }, +) + + +class AdGroupAdPrimaryStatusReasonEnum(proto.Message): + r"""AdGroupAd Primary Status Reason. Provides insight into why an + ad group ad is not serving or not serving optimally. These + reasons are aggregated to determine an overall + AdGroupAdPrimaryStatus. + + """ + + class AdGroupAdPrimaryStatusReason(proto.Enum): + r"""Possible ad group ad status reasons. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CAMPAIGN_REMOVED (2): + The user-specified campaign status is + removed. Contributes to + AdGroupAdPrimaryStatus.REMOVED. + CAMPAIGN_PAUSED (3): + The user-specified campaign status is paused. + Contributes to AdGroupAdPrimaryStatus.PAUSED. + CAMPAIGN_PENDING (4): + The user-specified time for this campaign to + start is in the future. Contributes to + AdGroupAdPrimaryStatus.PENDING. + CAMPAIGN_ENDED (5): + The user-specified time for this campaign to + end has passed. Contributes to + AdGroupAdPrimaryStatus.ENDED. + AD_GROUP_PAUSED (6): + The user-specified ad group status is paused. + Contributes to AdGroupAdPrimaryStatus.PAUSED. + AD_GROUP_REMOVED (7): + The user-specified ad group status is + removed. Contributes to + AdGroupAdPrimaryStatus.REMOVED. + AD_GROUP_AD_PAUSED (8): + The user-specified ad status is paused. + Contributes to AdGroupAdPrimaryStatus.PAUSED. + AD_GROUP_AD_REMOVED (9): + The user-specified ad status is removed. + Contributes to AdGroupAdPrimaryStatus.REMOVED. + AD_GROUP_AD_DISAPPROVED (10): + The ad is disapproved. Contributes to + AdGroupAdPrimaryStatus.NOT_ELIGIBLE. + AD_GROUP_AD_UNDER_REVIEW (11): + The ad is under review. Contributes to + AdGroupAdPrimaryStatus.PENDING. + AD_GROUP_AD_POOR_QUALITY (12): + The ad is poor quality. This is determined by + the serving stack that served the Ad. + Contributes to AdGroupAdPrimaryStatus.LIMITED. + AD_GROUP_AD_NO_ADS (13): + No eligible ads instances could be generated. + Contributes to AdGroupAdPrimaryStatus.PENDING. + AD_GROUP_AD_APPROVED_LABELED (14): + The ad is internally labeled with a limiting + label. Contributes to + AdGroupAdPrimaryStatus.LIMITED. + AD_GROUP_AD_AREA_OF_INTEREST_ONLY (15): + The ad is only serving in the user-specified + area of interest. Contributes to + AdGroupAdPrimaryStatus.LIMITED. + AD_GROUP_AD_UNDER_APPEAL (16): + The ad is part of an ongoing appeal. This + reason does not impact AdGroupAdPrimaryStatus. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CAMPAIGN_REMOVED = 2 + CAMPAIGN_PAUSED = 3 + CAMPAIGN_PENDING = 4 + CAMPAIGN_ENDED = 5 + AD_GROUP_PAUSED = 6 + AD_GROUP_REMOVED = 7 + AD_GROUP_AD_PAUSED = 8 + AD_GROUP_AD_REMOVED = 9 + AD_GROUP_AD_DISAPPROVED = 10 + AD_GROUP_AD_UNDER_REVIEW = 11 + AD_GROUP_AD_POOR_QUALITY = 12 + AD_GROUP_AD_NO_ADS = 13 + AD_GROUP_AD_APPROVED_LABELED = 14 + AD_GROUP_AD_AREA_OF_INTEREST_ONLY = 15 + AD_GROUP_AD_UNDER_APPEAL = 16 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_group_ad_rotation_mode.py b/google/ads/googleads/v24/enums/types/ad_group_ad_rotation_mode.py new file mode 100644 index 000000000..b34989235 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_group_ad_rotation_mode.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupAdRotationModeEnum", + }, +) + + +class AdGroupAdRotationModeEnum(proto.Message): + r"""Container for enum describing possible ad rotation modes of + ads within an ad group. + + """ + + class AdGroupAdRotationMode(proto.Enum): + r"""The possible ad rotation modes of an ad group. + + Values: + UNSPECIFIED (0): + The ad rotation mode has not been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + OPTIMIZE (2): + Optimize ad group ads based on clicks or + conversions. + ROTATE_FOREVER (3): + Rotate evenly forever. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + OPTIMIZE = 2 + ROTATE_FOREVER = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_group_ad_status.py b/google/ads/googleads/v24/enums/types/ad_group_ad_status.py new file mode 100644 index 000000000..412ab45d1 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_group_ad_status.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupAdStatusEnum", + }, +) + + +class AdGroupAdStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of an + AdGroupAd. + + """ + + class AdGroupAdStatus(proto.Enum): + r"""The possible statuses of an AdGroupAd. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + ENABLED (2): + The ad group ad is enabled. + PAUSED (3): + The ad group ad is paused. + REMOVED (4): + The ad group ad is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + PAUSED = 3 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_group_criterion_approval_status.py b/google/ads/googleads/v24/enums/types/ad_group_criterion_approval_status.py new file mode 100644 index 000000000..fcde0b83f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_group_criterion_approval_status.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupCriterionApprovalStatusEnum", + }, +) + + +class AdGroupCriterionApprovalStatusEnum(proto.Message): + r"""Container for enum describing possible AdGroupCriterion + approval statuses. + + """ + + class AdGroupCriterionApprovalStatus(proto.Enum): + r"""Enumerates AdGroupCriterion approval statuses. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + APPROVED (2): + Approved. + DISAPPROVED (3): + Disapproved. + PENDING_REVIEW (4): + Pending Review. + UNDER_REVIEW (5): + Under review. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + APPROVED = 2 + DISAPPROVED = 3 + PENDING_REVIEW = 4 + UNDER_REVIEW = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_group_criterion_primary_status.py b/google/ads/googleads/v24/enums/types/ad_group_criterion_primary_status.py new file mode 100644 index 000000000..d8640a453 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_group_criterion_primary_status.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupCriterionPrimaryStatusEnum", + }, +) + + +class AdGroupCriterionPrimaryStatusEnum(proto.Message): + r"""Container for enum describing possible ad group criterion + primary status. + + """ + + class AdGroupCriterionPrimaryStatus(proto.Enum): + r"""Enum describing the possible ad group criterion primary + status. Provides insight into why an ad group criterion is not + serving or not serving optimally. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ELIGIBLE (2): + The ad group criterion is eligible to serve. + PAUSED (3): + The ad group criterion is paused. + REMOVED (4): + The ad group criterion is removed. + PENDING (5): + The ad group criterion is pending. + NOT_ELIGIBLE (6): + The ad group criterion is not eligible to + serve. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ELIGIBLE = 2 + PAUSED = 3 + REMOVED = 4 + PENDING = 5 + NOT_ELIGIBLE = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_group_criterion_primary_status_reason.py b/google/ads/googleads/v24/enums/types/ad_group_criterion_primary_status_reason.py new file mode 100644 index 000000000..e8f3beec8 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_group_criterion_primary_status_reason.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupCriterionPrimaryStatusReasonEnum", + }, +) + + +class AdGroupCriterionPrimaryStatusReasonEnum(proto.Message): + r"""Container for enum describing possible ad group criterion + primary status reasons. + + """ + + class AdGroupCriterionPrimaryStatusReason(proto.Enum): + r"""Enum describing the possible Ad Group Criterion primary + status reasons. Provides insight into why an Ad Group Criterion + is not serving or not serving optimally. These reasons are + aggregated to determine an overall Ad Group Criterion primary + status. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents + unknown value in this version. + CAMPAIGN_PENDING (2): + The user-specified time for this campaign to + start is in the future. Contributes to + AdGroupCriterionPrimaryStatus.PENDING. + CAMPAIGN_CRITERION_NEGATIVE (3): + The ad group criterion is overridden by negative campaign + criterion. Contributes to + AdGroupCriterionPrimaryStatus.NOT_ELIGIBLE. + CAMPAIGN_PAUSED (4): + The user-specified campaign status is paused. + Contributes to + AdGroupCriterionPrimaryStatus.PAUSED. + CAMPAIGN_REMOVED (5): + The user-specified campaign status is + removed. Contributes to + AdGroupCriterionPrimaryStatus.REMOVED. + CAMPAIGN_ENDED (6): + The user-specified time for this campaign to + end has passed. Contributes to + AdGroupCriterionPrimaryStatus.ENDED. + AD_GROUP_PAUSED (7): + The user-specified ad group status is paused. + Contributes to + AdGroupCriterionPrimaryStatus.PAUSED. + AD_GROUP_REMOVED (8): + The user-specified ad group status is + removed. Contributes to + AdGroupCriterionPrimaryStatus.REMOVED. + AD_GROUP_CRITERION_DISAPPROVED (9): + The ad group criterion is disapproved by the ads approval + system. Contributes to + AdGroupCriterionPrimaryStatus.NOT_ELIGIBLE. + AD_GROUP_CRITERION_RARELY_SERVED (10): + The ad group criterion is rarely served. Contributes to + AdGroupCriterionPrimaryStatus.NOT_ELIGIBLE. + AD_GROUP_CRITERION_LOW_QUALITY (11): + The ad group criterion has a low quality + score. Contributes to + AdGroupCriterionPrimaryStatus.LIMITED. + AD_GROUP_CRITERION_UNDER_REVIEW (12): + The ad group criterion is under review. + Contributes to + AdGroupCriterionPrimaryStatus.PENDING. + AD_GROUP_CRITERION_PENDING_REVIEW (13): + The ad group criterion is pending review. Contributes to + AdGroupCriterionPrimaryStatus.NOT_ELIGIBLE. + AD_GROUP_CRITERION_BELOW_FIRST_PAGE_BID (14): + The ad group criterion's bid is below the + value necessary to serve on the first page. + Contributes to + AdGroupCriterionPrimaryStatus.LIMITED. + AD_GROUP_CRITERION_NEGATIVE (15): + The ad group criterion is negative. Contributes to + AdGroupCriterionPrimaryStatus.NOT_ELIGIBLE. + AD_GROUP_CRITERION_RESTRICTED (16): + The ad group criterion is restricted. Contributes to + AdGroupCriterionPrimaryStatus.NOT_ELIGIBLE. + AD_GROUP_CRITERION_PAUSED (17): + The user-specified ad group criterion status + is paused. Contributes to + AdGroupCriterionPrimaryStatus.PAUSED. + AD_GROUP_CRITERION_PAUSED_DUE_TO_LOW_ACTIVITY (18): + The ad group criterion has been paused due to + prolonged low activity in serving. Contributes + to AdGroupCriterionPrimaryStatus.PAUSED. + AD_GROUP_CRITERION_REMOVED (19): + The user-specified ad group criterion status + is removed. Contributes to + AdGroupCriterionPrimaryStatus.REMOVED. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CAMPAIGN_PENDING = 2 + CAMPAIGN_CRITERION_NEGATIVE = 3 + CAMPAIGN_PAUSED = 4 + CAMPAIGN_REMOVED = 5 + CAMPAIGN_ENDED = 6 + AD_GROUP_PAUSED = 7 + AD_GROUP_REMOVED = 8 + AD_GROUP_CRITERION_DISAPPROVED = 9 + AD_GROUP_CRITERION_RARELY_SERVED = 10 + AD_GROUP_CRITERION_LOW_QUALITY = 11 + AD_GROUP_CRITERION_UNDER_REVIEW = 12 + AD_GROUP_CRITERION_PENDING_REVIEW = 13 + AD_GROUP_CRITERION_BELOW_FIRST_PAGE_BID = 14 + AD_GROUP_CRITERION_NEGATIVE = 15 + AD_GROUP_CRITERION_RESTRICTED = 16 + AD_GROUP_CRITERION_PAUSED = 17 + AD_GROUP_CRITERION_PAUSED_DUE_TO_LOW_ACTIVITY = 18 + AD_GROUP_CRITERION_REMOVED = 19 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_group_criterion_status.py b/google/ads/googleads/v24/enums/types/ad_group_criterion_status.py new file mode 100644 index 000000000..9ac0b0847 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_group_criterion_status.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupCriterionStatusEnum", + }, +) + + +class AdGroupCriterionStatusEnum(proto.Message): + r"""Message describing AdGroupCriterion statuses.""" + + class AdGroupCriterionStatus(proto.Enum): + r"""The possible statuses of an AdGroupCriterion. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + ENABLED (2): + The ad group criterion is enabled. + PAUSED (3): + The ad group criterion is paused. + REMOVED (4): + The ad group criterion is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + PAUSED = 3 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_group_primary_status.py b/google/ads/googleads/v24/enums/types/ad_group_primary_status.py new file mode 100644 index 000000000..f90593867 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_group_primary_status.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupPrimaryStatusEnum", + }, +) + + +class AdGroupPrimaryStatusEnum(proto.Message): + r"""Ad Group Primary Status. Provides insight into why an ad + group is not serving or not serving optimally. + + """ + + class AdGroupPrimaryStatus(proto.Enum): + r"""The possible statuses of an AdGroup. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ELIGIBLE (2): + The ad group is eligible to serve. + PAUSED (3): + The ad group is paused. + REMOVED (4): + The ad group is removed. + PENDING (5): + The ad group may serve in the future. + NOT_ELIGIBLE (6): + The ad group is not eligible to serve. + LIMITED (7): + The ad group has limited servability. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ELIGIBLE = 2 + PAUSED = 3 + REMOVED = 4 + PENDING = 5 + NOT_ELIGIBLE = 6 + LIMITED = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_group_primary_status_reason.py b/google/ads/googleads/v24/enums/types/ad_group_primary_status_reason.py new file mode 100644 index 000000000..25082ddc1 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_group_primary_status_reason.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupPrimaryStatusReasonEnum", + }, +) + + +class AdGroupPrimaryStatusReasonEnum(proto.Message): + r"""Ad Group Primary Status Reason. Provides insight into why an + ad group is not serving or not serving optimally. These reasons + are aggregated to determine an overall AdGroupPrimaryStatus. + + """ + + class AdGroupPrimaryStatusReason(proto.Enum): + r"""Possible ad group status reasons. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CAMPAIGN_REMOVED (2): + The user-specified campaign status is removed. Contributes + to AdGroupPrimaryStatus.NOT_ELIGIBLE. + CAMPAIGN_PAUSED (3): + The user-specified campaign status is paused. Contributes to + AdGroupPrimaryStatus.NOT_ELIGIBLE. + CAMPAIGN_PENDING (4): + The user-specified time for this campaign to start is in the + future. Contributes to AdGroupPrimaryStatus.NOT_ELIGIBLE + CAMPAIGN_ENDED (5): + The user-specified time for this campaign to end has passed. + Contributes to AdGroupPrimaryStatus.NOT_ELIGIBLE. + AD_GROUP_PAUSED (6): + The user-specified ad group status is paused. + Contributes to AdGroupPrimaryStatus.PAUSED. + AD_GROUP_REMOVED (7): + The user-specified ad group status is + removed. Contributes to + AdGroupPrimaryStatus.REMOVED. + AD_GROUP_INCOMPLETE (8): + The construction of this ad group is not yet complete. + Contributes to AdGroupPrimaryStatus.NOT_ELIGIBLE. + KEYWORDS_PAUSED (9): + The user-specified keyword statuses in this ad group are all + paused. Contributes to AdGroupPrimaryStatus.NOT_ELIGIBLE. + NO_KEYWORDS (10): + No eligible keywords exist in this ad group. Contributes to + AdGroupPrimaryStatus.NOT_ELIGIBLE. + AD_GROUP_ADS_PAUSED (11): + The user-specified ad group ads statuses in this ad group + are all paused. Contributes to + AdGroupPrimaryStatus.NOT_ELIGIBLE. + NO_AD_GROUP_ADS (12): + No eligible ad group ads exist in this ad group. Contributes + to AdGroupPrimaryStatus.NOT_ELIGIBLE. + HAS_ADS_DISAPPROVED (13): + Policy status reason when at least one ad is + disapproved. Contributes to multiple + AdGroupPrimaryStatus. + HAS_ADS_LIMITED_BY_POLICY (14): + Policy status reason when at least one ad is + limited by policy. Contributes to multiple + AdGroupPrimaryStatus. + MOST_ADS_UNDER_REVIEW (15): + Policy status reason when most ads are + pending review. Contributes to + AdGroupPrimaryStatus.PENDING. + CAMPAIGN_DRAFT (16): + The AdGroup belongs to a Draft campaign. Contributes to + AdGroupPrimaryStatus.NOT_ELIGIBLE. + AD_GROUP_PAUSED_DUE_TO_LOW_ACTIVITY (19): + Ad group has been paused due to prolonged low + activity in serving. Contributes to + AdGroupPrimaryStatus.PAUSED. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CAMPAIGN_REMOVED = 2 + CAMPAIGN_PAUSED = 3 + CAMPAIGN_PENDING = 4 + CAMPAIGN_ENDED = 5 + AD_GROUP_PAUSED = 6 + AD_GROUP_REMOVED = 7 + AD_GROUP_INCOMPLETE = 8 + KEYWORDS_PAUSED = 9 + NO_KEYWORDS = 10 + AD_GROUP_ADS_PAUSED = 11 + NO_AD_GROUP_ADS = 12 + HAS_ADS_DISAPPROVED = 13 + HAS_ADS_LIMITED_BY_POLICY = 14 + MOST_ADS_UNDER_REVIEW = 15 + CAMPAIGN_DRAFT = 16 + AD_GROUP_PAUSED_DUE_TO_LOW_ACTIVITY = 19 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_group_status.py b/google/ads/googleads/v24/enums/types/ad_group_status.py new file mode 100644 index 000000000..8f4a9d963 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_group_status.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupStatusEnum", + }, +) + + +class AdGroupStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of an ad + group. + + """ + + class AdGroupStatus(proto.Enum): + r"""The possible statuses of an ad group. + + Values: + UNSPECIFIED (0): + The status has not been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + ENABLED (2): + The ad group is enabled. + PAUSED (3): + The ad group is paused. + REMOVED (4): + The ad group is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + PAUSED = 3 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_group_type.py b/google/ads/googleads/v24/enums/types/ad_group_type.py new file mode 100644 index 000000000..9dc5b4031 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_group_type.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupTypeEnum", + }, +) + + +class AdGroupTypeEnum(proto.Message): + r"""Defines types of an ad group, specific to a particular + campaign channel type. This type drives validations that + restrict which entities can be added to the ad group. + + """ + + class AdGroupType(proto.Enum): + r"""Enum listing the possible types of an ad group. + + Values: + UNSPECIFIED (0): + The type has not been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + SEARCH_STANDARD (2): + The default ad group type for Search + campaigns. + DISPLAY_STANDARD (3): + The default ad group type for Display + campaigns. + SHOPPING_PRODUCT_ADS (4): + The ad group type for Shopping campaigns + serving standard product ads. + HOTEL_ADS (6): + The default ad group type for Hotel + campaigns. + SHOPPING_SMART_ADS (7): + The type for ad groups in Smart Shopping + campaigns. + VIDEO_BUMPER (8): + Short unskippable in-stream video ads. + VIDEO_TRUE_VIEW_IN_STREAM (9): + TrueView (skippable) in-stream video ads. + VIDEO_TRUE_VIEW_IN_DISPLAY (10): + TrueView in-display video ads. + VIDEO_NON_SKIPPABLE_IN_STREAM (11): + Unskippable in-stream video ads. + SEARCH_DYNAMIC_ADS (13): + Ad group type for Dynamic Search Ads ad + groups. + SHOPPING_COMPARISON_LISTING_ADS (14): + The type for ad groups in Shopping Comparison + Listing campaigns. + PROMOTED_HOTEL_ADS (15): + The ad group type for Promoted Hotel ad + groups. + VIDEO_RESPONSIVE (16): + Video responsive ad groups. + VIDEO_EFFICIENT_REACH (17): + Video efficient reach ad groups. + SMART_CAMPAIGN_ADS (18): + Ad group type for Smart campaigns. + TRAVEL_ADS (19): + Ad group type for Travel campaigns. + YOUTUBE_AUDIO (20): + Ad group type for YouTube Audio campaigns. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SEARCH_STANDARD = 2 + DISPLAY_STANDARD = 3 + SHOPPING_PRODUCT_ADS = 4 + HOTEL_ADS = 6 + SHOPPING_SMART_ADS = 7 + VIDEO_BUMPER = 8 + VIDEO_TRUE_VIEW_IN_STREAM = 9 + VIDEO_TRUE_VIEW_IN_DISPLAY = 10 + VIDEO_NON_SKIPPABLE_IN_STREAM = 11 + SEARCH_DYNAMIC_ADS = 13 + SHOPPING_COMPARISON_LISTING_ADS = 14 + PROMOTED_HOTEL_ADS = 15 + VIDEO_RESPONSIVE = 16 + VIDEO_EFFICIENT_REACH = 17 + SMART_CAMPAIGN_ADS = 18 + TRAVEL_ADS = 19 + YOUTUBE_AUDIO = 20 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_network_type.py b/google/ads/googleads/v24/enums/types/ad_network_type.py new file mode 100644 index 000000000..aade9e80a --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_network_type.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdNetworkTypeEnum", + }, +) + + +class AdNetworkTypeEnum(proto.Message): + r"""Container for enumeration of Google Ads network types.""" + + class AdNetworkType(proto.Enum): + r"""Enumerates Google Ads network types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + SEARCH (2): + Google search. + SEARCH_PARTNERS (3): + Search partners. + CONTENT (4): + Display Network. + MIXED (7): + Cross-network. + YOUTUBE (8): + YouTube + GOOGLE_TV (9): + Google TV + GOOGLE_OWNED_CHANNELS (10): + This network is used for Google Owned + channels such as Discover feed, Gmail, YouTube. + Starting with V20, Demand Gen Stats will be + attributed to more granular network types such + as GMAIL, DISCOVER, MAPS, YOUTUBE; this value + will only be used for historical data. + GMAIL (11): + Gmail + DISCOVER (12): + Discover Feed + MAPS (13): + Maps + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SEARCH = 2 + SEARCH_PARTNERS = 3 + CONTENT = 4 + MIXED = 7 + YOUTUBE = 8 + GOOGLE_TV = 9 + GOOGLE_OWNED_CHANNELS = 10 + GMAIL = 11 + DISCOVER = 12 + MAPS = 13 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_serving_optimization_status.py b/google/ads/googleads/v24/enums/types/ad_serving_optimization_status.py new file mode 100644 index 000000000..f08be3f52 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_serving_optimization_status.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdServingOptimizationStatusEnum", + }, +) + + +class AdServingOptimizationStatusEnum(proto.Message): + r"""Possible ad serving statuses of a campaign.""" + + class AdServingOptimizationStatus(proto.Enum): + r"""Enum describing possible serving statuses. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + OPTIMIZE (2): + Ad serving is optimized based on CTR for the + campaign. + CONVERSION_OPTIMIZE (3): + Ad serving is optimized based on CTR \* Conversion for the + campaign. If the campaign is not in the conversion optimizer + bidding strategy, it will default to OPTIMIZED. + ROTATE (4): + Ads are rotated evenly for 90 days, then + optimized for clicks. + ROTATE_INDEFINITELY (5): + Show lower performing ads more evenly with + higher performing ads, and do not optimize. + UNAVAILABLE (6): + Ad serving optimization status is not + available. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + OPTIMIZE = 2 + CONVERSION_OPTIMIZE = 3 + ROTATE = 4 + ROTATE_INDEFINITELY = 5 + UNAVAILABLE = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_strength.py b/google/ads/googleads/v24/enums/types/ad_strength.py new file mode 100644 index 000000000..fe01f670f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_strength.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdStrengthEnum", + }, +) + + +class AdStrengthEnum(proto.Message): + r"""Container for enum describing possible ad strengths.""" + + class AdStrength(proto.Enum): + r"""Enum listing the possible ad strengths. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PENDING (2): + The ad strength is currently pending. + NO_ADS (3): + No ads could be generated. + POOR (4): + Poor strength. + AVERAGE (5): + Average strength. + GOOD (6): + Good strength. + EXCELLENT (7): + Excellent strength. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + NO_ADS = 3 + POOR = 4 + AVERAGE = 5 + GOOD = 6 + EXCELLENT = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_strength_action_item_type.py b/google/ads/googleads/v24/enums/types/ad_strength_action_item_type.py new file mode 100644 index 000000000..77f722630 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_strength_action_item_type.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdStrengthActionItemTypeEnum", + }, +) + + +class AdStrengthActionItemTypeEnum(proto.Message): + r"""Container for enumeration of ad strength action item types.""" + + class AdStrengthActionItemType(proto.Enum): + r"""Enumerates ad strength action item types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ADD_ASSET (2): + This action item suggests adding an asset to + the asset group. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ADD_ASSET = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_sub_network_type.py b/google/ads/googleads/v24/enums/types/ad_sub_network_type.py new file mode 100644 index 000000000..a907fc42b --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_sub_network_type.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdSubNetworkTypeEnum", + }, +) + + +class AdSubNetworkTypeEnum(proto.Message): + r"""Container for enumeration of Google Ads sub network types.""" + + class AdSubNetworkType(proto.Enum): + r"""Enumerates Google Ads sub network types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Unknown. + UNSEGMENTED (2): + The whole network without any sub network + type segmentation. + YOUTUBE_INSTREAM (3): + Ads served in-stream of YouTube organic + videos. + YOUTUBE_INFEED (4): + Ads served on YouTube feed surfaces, such as + YouTube Home or Watch Next. + YOUTUBE_SHORTS (5): + Ads served on the YouTube Shorts feed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UNSEGMENTED = 2 + YOUTUBE_INSTREAM = 3 + YOUTUBE_INFEED = 4 + YOUTUBE_SHORTS = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/ad_type.py b/google/ads/googleads/v24/enums/types/ad_type.py new file mode 100644 index 000000000..74b12a263 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/ad_type.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdTypeEnum", + }, +) + + +class AdTypeEnum(proto.Message): + r"""Container for enum describing possible types of an ad.""" + + class AdType(proto.Enum): + r"""The possible types of an ad. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + TEXT_AD (2): + The ad is a text ad. + EXPANDED_TEXT_AD (3): + The ad is an expanded text ad. Expanded text + ads are deprecated. + EXPANDED_DYNAMIC_SEARCH_AD (7): + The ad is an expanded dynamic search ad. + HOTEL_AD (8): + The ad is a hotel ad. + SHOPPING_SMART_AD (9): + The ad is a Smart Shopping ad. + SHOPPING_PRODUCT_AD (10): + The ad is a standard Shopping ad. + VIDEO_AD (12): + The ad is a video ad. + IMAGE_AD (14): + This ad is an Image ad. + RESPONSIVE_SEARCH_AD (15): + The ad is a responsive search ad. + LEGACY_RESPONSIVE_DISPLAY_AD (16): + The ad is a legacy responsive display ad. + APP_AD (17): + The ad is an app ad. + LEGACY_APP_INSTALL_AD (18): + The ad is a legacy app install ad. + RESPONSIVE_DISPLAY_AD (19): + The ad is a responsive display ad. + LOCAL_AD (20): + The ad is a local ad. + HTML5_UPLOAD_AD (21): + The ad is a display upload ad with the HTML5_UPLOAD_AD + product type. + DYNAMIC_HTML5_AD (22): + The ad is a display upload ad with one of the + DYNAMIC_HTML5\_\* product types. + APP_ENGAGEMENT_AD (23): + The ad is an app engagement ad. + SHOPPING_COMPARISON_LISTING_AD (24): + The ad is a Shopping Comparison Listing ad. + VIDEO_BUMPER_AD (25): + Video bumper ad. + VIDEO_NON_SKIPPABLE_IN_STREAM_AD (26): + Video non-skippable in-stream ad. + VIDEO_TRUEVIEW_IN_STREAM_AD (29): + Video TrueView in-stream ad. + VIDEO_RESPONSIVE_AD (30): + Video responsive ad. + SMART_CAMPAIGN_AD (31): + Smart campaign ad. + CALL_AD (32): + Call ad. + APP_PRE_REGISTRATION_AD (33): + Universal app pre-registration ad. + IN_FEED_VIDEO_AD (34): + In-feed video ad. + DEMAND_GEN_MULTI_ASSET_AD (40): + Demand Gen multi asset ad. + DEMAND_GEN_CAROUSEL_AD (41): + Demand Gen carousel ad. + TRAVEL_AD (37): + Travel ad. + DEMAND_GEN_VIDEO_RESPONSIVE_AD (42): + Demand Gen video responsive ad. + DEMAND_GEN_PRODUCT_AD (39): + Demand Gen product ad. + YOUTUBE_AUDIO_AD (44): + YouTube Audio ad. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + TEXT_AD = 2 + EXPANDED_TEXT_AD = 3 + EXPANDED_DYNAMIC_SEARCH_AD = 7 + HOTEL_AD = 8 + SHOPPING_SMART_AD = 9 + SHOPPING_PRODUCT_AD = 10 + VIDEO_AD = 12 + IMAGE_AD = 14 + RESPONSIVE_SEARCH_AD = 15 + LEGACY_RESPONSIVE_DISPLAY_AD = 16 + APP_AD = 17 + LEGACY_APP_INSTALL_AD = 18 + RESPONSIVE_DISPLAY_AD = 19 + LOCAL_AD = 20 + HTML5_UPLOAD_AD = 21 + DYNAMIC_HTML5_AD = 22 + APP_ENGAGEMENT_AD = 23 + SHOPPING_COMPARISON_LISTING_AD = 24 + VIDEO_BUMPER_AD = 25 + VIDEO_NON_SKIPPABLE_IN_STREAM_AD = 26 + VIDEO_TRUEVIEW_IN_STREAM_AD = 29 + VIDEO_RESPONSIVE_AD = 30 + SMART_CAMPAIGN_AD = 31 + CALL_AD = 32 + APP_PRE_REGISTRATION_AD = 33 + IN_FEED_VIDEO_AD = 34 + DEMAND_GEN_MULTI_ASSET_AD = 40 + DEMAND_GEN_CAROUSEL_AD = 41 + TRAVEL_AD = 37 + DEMAND_GEN_VIDEO_RESPONSIVE_AD = 42 + DEMAND_GEN_PRODUCT_AD = 39 + YOUTUBE_AUDIO_AD = 44 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/advertising_channel_sub_type.py b/google/ads/googleads/v24/enums/types/advertising_channel_sub_type.py new file mode 100644 index 000000000..b7d1b8e2a --- /dev/null +++ b/google/ads/googleads/v24/enums/types/advertising_channel_sub_type.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdvertisingChannelSubTypeEnum", + }, +) + + +class AdvertisingChannelSubTypeEnum(proto.Message): + r"""An immutable specialization of an Advertising Channel.""" + + class AdvertisingChannelSubType(proto.Enum): + r"""Enum describing the different channel subtypes. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used as a return value only. Represents value + unknown in this version. + SEARCH_MOBILE_APP (2): + Mobile app campaigns for Search. + DISPLAY_MOBILE_APP (3): + Mobile app campaigns for Display. + SEARCH_EXPRESS (4): + AdWords express campaigns for search. + DISPLAY_EXPRESS (5): + AdWords Express campaigns for display. + SHOPPING_SMART_ADS (6): + Smart Shopping campaigns. + DISPLAY_GMAIL_AD (7): + Gmail Ad campaigns. + DISPLAY_SMART_CAMPAIGN (8): + Smart display campaigns. New campaigns of + this sub type cannot be created. + VIDEO_ACTION (10): + Video TrueView for Action campaigns. + VIDEO_NON_SKIPPABLE (11): + Video campaigns with non-skippable video ads. + APP_CAMPAIGN (12): + App Campaign that lets you easily promote + your Android or iOS app across Google's top + properties including Search, Play, YouTube, and + the Google Display Network. + APP_CAMPAIGN_FOR_ENGAGEMENT (13): + App Campaign for engagement, focused on + driving re-engagement with the app across + several of Google's top properties including + Search, YouTube, and the Google Display Network. + LOCAL_CAMPAIGN (14): + Campaigns specialized for local advertising. + SHOPPING_COMPARISON_LISTING_ADS (15): + Shopping Comparison Listing campaigns. + SMART_CAMPAIGN (16): + Standard Smart campaigns. + VIDEO_SEQUENCE (17): + Video campaigns with sequence video ads. + APP_CAMPAIGN_FOR_PRE_REGISTRATION (18): + App Campaign for pre registration, + specialized for advertising mobile app + pre-registration, that targets multiple + advertising channels across Google Play, YouTube + and Display Network. See + https://support.google.com/google-ads/answer/9441344 + to learn more. + VIDEO_REACH_TARGET_FREQUENCY (19): + Video reach campaign with Target Frequency + bidding strategy. + TRAVEL_ACTIVITIES (20): + Travel Activities campaigns. + YOUTUBE_AUDIO (22): + YouTube Audio campaigns. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SEARCH_MOBILE_APP = 2 + DISPLAY_MOBILE_APP = 3 + SEARCH_EXPRESS = 4 + DISPLAY_EXPRESS = 5 + SHOPPING_SMART_ADS = 6 + DISPLAY_GMAIL_AD = 7 + DISPLAY_SMART_CAMPAIGN = 8 + VIDEO_ACTION = 10 + VIDEO_NON_SKIPPABLE = 11 + APP_CAMPAIGN = 12 + APP_CAMPAIGN_FOR_ENGAGEMENT = 13 + LOCAL_CAMPAIGN = 14 + SHOPPING_COMPARISON_LISTING_ADS = 15 + SMART_CAMPAIGN = 16 + VIDEO_SEQUENCE = 17 + APP_CAMPAIGN_FOR_PRE_REGISTRATION = 18 + VIDEO_REACH_TARGET_FREQUENCY = 19 + TRAVEL_ACTIVITIES = 20 + YOUTUBE_AUDIO = 22 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/advertising_channel_type.py b/google/ads/googleads/v24/enums/types/advertising_channel_type.py new file mode 100644 index 000000000..9f42a76d9 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/advertising_channel_type.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AdvertisingChannelTypeEnum", + }, +) + + +class AdvertisingChannelTypeEnum(proto.Message): + r"""The channel type a campaign may target to serve on.""" + + class AdvertisingChannelType(proto.Enum): + r"""Enum describing the various advertising channel types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + SEARCH (2): + Search Network. Includes display bundled, and + Search+ campaigns. + DISPLAY (3): + Google Display Network only. + SHOPPING (4): + Shopping campaigns serve on the shopping + property and on google.com search results. + HOTEL (5): + Hotel Ads campaigns. + VIDEO (6): + Video campaigns. + MULTI_CHANNEL (7): + App Campaigns, and App Campaigns for + Engagement, that run across multiple channels. + LOCAL (8): + Local ads campaigns. + SMART (9): + Smart campaigns. + PERFORMANCE_MAX (10): + Performance Max campaigns. + LOCAL_SERVICES (11): + Local services campaigns. + TRAVEL (13): + Travel campaigns. + DEMAND_GEN (14): + Demand Gen campaigns. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SEARCH = 2 + DISPLAY = 3 + SHOPPING = 4 + HOTEL = 5 + VIDEO = 6 + MULTI_CHANNEL = 7 + LOCAL = 8 + SMART = 9 + PERFORMANCE_MAX = 10 + LOCAL_SERVICES = 11 + TRAVEL = 13 + DEMAND_GEN = 14 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/age_range_type.py b/google/ads/googleads/v24/enums/types/age_range_type.py new file mode 100644 index 000000000..c2bd7b321 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/age_range_type.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AgeRangeTypeEnum", + }, +) + + +class AgeRangeTypeEnum(proto.Message): + r"""Container for enum describing the type of demographic age + ranges. + + """ + + class AgeRangeType(proto.Enum): + r"""The type of demographic age ranges (for example, between 18 + and 24 years old). + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + AGE_RANGE_18_24 (503001): + Between 18 and 24 years old. + AGE_RANGE_25_34 (503002): + Between 25 and 34 years old. + AGE_RANGE_35_44 (503003): + Between 35 and 44 years old. + AGE_RANGE_45_54 (503004): + Between 45 and 54 years old. + AGE_RANGE_55_64 (503005): + Between 55 and 64 years old. + AGE_RANGE_65_UP (503006): + 65 years old and beyond. + AGE_RANGE_UNDETERMINED (503999): + Undetermined age range. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AGE_RANGE_18_24 = 503001 + AGE_RANGE_25_34 = 503002 + AGE_RANGE_35_44 = 503003 + AGE_RANGE_45_54 = 503004 + AGE_RANGE_55_64 = 503005 + AGE_RANGE_65_UP = 503006 + AGE_RANGE_UNDETERMINED = 503999 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/android_privacy_interaction_type.py b/google/ads/googleads/v24/enums/types/android_privacy_interaction_type.py new file mode 100644 index 000000000..7e146b131 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/android_privacy_interaction_type.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AndroidPrivacyInteractionTypeEnum", + }, +) + + +class AndroidPrivacyInteractionTypeEnum(proto.Message): + r"""The interaction type enum for Android privacy shared key.""" + + class AndroidPrivacyInteractionType(proto.Enum): + r"""Enumerates interaction types + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + CLICK (2): + The physical click interaction type. + ENGAGED_VIEW (3): + The 10 seconds engaged view interaction type. + VIEW (4): + The view (ad impression) interaction type. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CLICK = 2 + ENGAGED_VIEW = 3 + VIEW = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/android_privacy_network_type.py b/google/ads/googleads/v24/enums/types/android_privacy_network_type.py new file mode 100644 index 000000000..406ecd8c0 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/android_privacy_network_type.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AndroidPrivacyNetworkTypeEnum", + }, +) + + +class AndroidPrivacyNetworkTypeEnum(proto.Message): + r"""The network type enum for Android privacy shared key.""" + + class AndroidPrivacyNetworkType(proto.Enum): + r"""Enumerates network types + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + SEARCH (2): + Search Network. + DISPLAY (3): + Display Network. + YOUTUBE (4): + YouTube Network. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SEARCH = 2 + DISPLAY = 3 + YOUTUBE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/app_bidding_goal.py b/google/ads/googleads/v24/enums/types/app_bidding_goal.py new file mode 100644 index 000000000..197562056 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/app_bidding_goal.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AppBiddingGoalEnum", + }, +) + + +class AppBiddingGoalEnum(proto.Message): + r"""Container for enum describing an app bidding goal for raise + Target CPA recommendation. + + """ + + class AppBiddingGoal(proto.Enum): + r"""Represents the goal towards which the bidding strategy, of an + app campaign, should optimize for. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Represents value unknown in this version of + the API. + OPTIMIZE_FOR_INSTALL_CONVERSION_VOLUME (2): + The bidding strategy of the app campaign + should aim to maximize installation of the app. + OPTIMIZE_FOR_IN_APP_CONVERSION_VOLUME (3): + The bidding strategy of the app campaign + should aim to maximize the selected in-app + conversions' volume. + OPTIMIZE_FOR_TOTAL_CONVERSION_VALUE (4): + The bidding strategy of the app campaign + should aim to maximize all conversions' value, + that is, install and selected in-app + conversions. + OPTIMIZE_FOR_TARGET_IN_APP_CONVERSION (5): + The bidding strategy of the app campaign + should aim to maximize just the selected in-app + conversion's volume, while achieving or + exceeding target cost per in-app conversion. + OPTIMIZE_FOR_RETURN_ON_ADVERTISING_SPEND (6): + The bidding strategy of the app campaign + should aim to maximize all conversions' value, + that is, install and selected in-app conversions + while achieving or exceeding target return on + advertising spend. + OPTIMIZE_FOR_INSTALL_CONVERSION_VOLUME_WITHOUT_TARGET_CPI (7): + This bidding strategy of the app campaign + should aim to maximize installation of the app + without advertiser-provided target + cost-per-install. + OPTIMIZE_FOR_PRE_REGISTRATION_CONVERSION_VOLUME (8): + This bidding strategy of the app campaign + should aim to maximize pre-registration of the + app. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + OPTIMIZE_FOR_INSTALL_CONVERSION_VOLUME = 2 + OPTIMIZE_FOR_IN_APP_CONVERSION_VOLUME = 3 + OPTIMIZE_FOR_TOTAL_CONVERSION_VALUE = 4 + OPTIMIZE_FOR_TARGET_IN_APP_CONVERSION = 5 + OPTIMIZE_FOR_RETURN_ON_ADVERTISING_SPEND = 6 + OPTIMIZE_FOR_INSTALL_CONVERSION_VOLUME_WITHOUT_TARGET_CPI = 7 + OPTIMIZE_FOR_PRE_REGISTRATION_CONVERSION_VOLUME = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/app_campaign_app_store.py b/google/ads/googleads/v24/enums/types/app_campaign_app_store.py new file mode 100644 index 000000000..3137112ca --- /dev/null +++ b/google/ads/googleads/v24/enums/types/app_campaign_app_store.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AppCampaignAppStoreEnum", + }, +) + + +class AppCampaignAppStoreEnum(proto.Message): + r"""The application store that distributes mobile applications.""" + + class AppCampaignAppStore(proto.Enum): + r"""Enum describing app campaign app store. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + APPLE_APP_STORE (2): + Apple app store. + GOOGLE_APP_STORE (3): + Google play. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + APPLE_APP_STORE = 2 + GOOGLE_APP_STORE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/app_campaign_bidding_strategy_goal_type.py b/google/ads/googleads/v24/enums/types/app_campaign_bidding_strategy_goal_type.py new file mode 100644 index 000000000..40f74bfea --- /dev/null +++ b/google/ads/googleads/v24/enums/types/app_campaign_bidding_strategy_goal_type.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AppCampaignBiddingStrategyGoalTypeEnum", + }, +) + + +class AppCampaignBiddingStrategyGoalTypeEnum(proto.Message): + r"""Container for enum describing goal towards which the bidding + strategy of an app campaign should optimize for. + + """ + + class AppCampaignBiddingStrategyGoalType(proto.Enum): + r"""Goal type of App campaign BiddingStrategy. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + OPTIMIZE_INSTALLS_TARGET_INSTALL_COST (2): + Aim to maximize the number of app installs. + The cpa bid is the target cost per install. + OPTIMIZE_IN_APP_CONVERSIONS_TARGET_INSTALL_COST (3): + Aim to maximize the long term number of + selected in-app conversions from app installs. + The cpa bid is the target cost per install. + OPTIMIZE_IN_APP_CONVERSIONS_TARGET_CONVERSION_COST (4): + Aim to maximize the long term number of + selected in-app conversions from app installs. + The cpa bid is the target cost per in-app + conversion. Note that the actual cpa may seem + higher than the target cpa at first, since the + long term conversions haven't happened yet. + OPTIMIZE_RETURN_ON_ADVERTISING_SPEND (5): + Aim to maximize all conversions' value, for + example, install + selected in-app conversions + while achieving or exceeding target return on + advertising spend. + OPTIMIZE_PRE_REGISTRATION_CONVERSION_VOLUME (6): + Aim to maximize the pre-registration of the + app. + OPTIMIZE_INSTALLS_WITHOUT_TARGET_INSTALL_COST (7): + Aim to maximize installation of the app + without target cost-per-install. + OPTIMIZE_IN_APP_CONVERSIONS_WITHOUT_TARGET_CPA (8): + Aim to maximize the selected in-app + conversion's volume while spending the full + budget. No advertiser-specific target CPA. + OPTIMIZE_TOTAL_VALUE_WITHOUT_TARGET_ROAS (9): + Aim to maximize total conversion value, such + as install and selected in-app conversions, + while spending the full budget. No + advertiser-specified target ROAS. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + OPTIMIZE_INSTALLS_TARGET_INSTALL_COST = 2 + OPTIMIZE_IN_APP_CONVERSIONS_TARGET_INSTALL_COST = 3 + OPTIMIZE_IN_APP_CONVERSIONS_TARGET_CONVERSION_COST = 4 + OPTIMIZE_RETURN_ON_ADVERTISING_SPEND = 5 + OPTIMIZE_PRE_REGISTRATION_CONVERSION_VOLUME = 6 + OPTIMIZE_INSTALLS_WITHOUT_TARGET_INSTALL_COST = 7 + OPTIMIZE_IN_APP_CONVERSIONS_WITHOUT_TARGET_CPA = 8 + OPTIMIZE_TOTAL_VALUE_WITHOUT_TARGET_ROAS = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/app_payment_model_type.py b/google/ads/googleads/v24/enums/types/app_payment_model_type.py new file mode 100644 index 000000000..bd945c646 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/app_payment_model_type.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AppPaymentModelTypeEnum", + }, +) + + +class AppPaymentModelTypeEnum(proto.Message): + r"""Represents a criterion for targeting paid apps.""" + + class AppPaymentModelType(proto.Enum): + r"""Enum describing possible app payment models. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PAID (30): + Represents paid-for apps. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PAID = 30 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/app_url_operating_system_type.py b/google/ads/googleads/v24/enums/types/app_url_operating_system_type.py new file mode 100644 index 000000000..ebcd80a88 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/app_url_operating_system_type.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AppUrlOperatingSystemTypeEnum", + }, +) + + +class AppUrlOperatingSystemTypeEnum(proto.Message): + r"""The possible OS types for a deeplink AppUrl.""" + + class AppUrlOperatingSystemType(proto.Enum): + r"""Operating System + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + IOS (2): + The Apple IOS operating system. + ANDROID (3): + The Android operating system. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + IOS = 2 + ANDROID = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/application_instance.py b/google/ads/googleads/v24/enums/types/application_instance.py new file mode 100644 index 000000000..ad416abff --- /dev/null +++ b/google/ads/googleads/v24/enums/types/application_instance.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ApplicationInstanceEnum", + }, +) + + +class ApplicationInstanceEnum(proto.Message): + r"""Container for enum describing application instance types.""" + + class ApplicationInstance(proto.Enum): + r"""Possible application instances sending the request. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + DEVELOPMENT_AND_TESTING (2): + The instance is for development and testing + purposes. + PRODUCTION (3): + The instance is for production purposes. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DEVELOPMENT_AND_TESTING = 2 + PRODUCTION = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_automation_status.py b/google/ads/googleads/v24/enums/types/asset_automation_status.py new file mode 100644 index 000000000..852578e22 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_automation_status.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetAutomationStatusEnum", + }, +) + + +class AssetAutomationStatusEnum(proto.Message): + r"""Container for enum describing the status of asset automation.""" + + class AssetAutomationStatus(proto.Enum): + r"""The status of asset automation. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used as a return value only. Represents value + unknown in this version. + OPTED_IN (2): + Opted-in will enable generating and serving + an asset automation type. + OPTED_OUT (3): + Opted-out will stop generating and serving an + asset automation type. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + OPTED_IN = 2 + OPTED_OUT = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_automation_type.py b/google/ads/googleads/v24/enums/types/asset_automation_type.py new file mode 100644 index 000000000..bf166cfa0 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_automation_type.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetAutomationTypeEnum", + }, +) + + +class AssetAutomationTypeEnum(proto.Message): + r"""Container for enum describing the type of asset automation.""" + + class AssetAutomationType(proto.Enum): + r"""The type of asset automation. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used as a return value only. Represents value + unknown in this version. + TEXT_ASSET_AUTOMATION (2): + Text asset automation includes headlines and + descriptions. By default, advertisers are + opted-in for Performance Max and opted-out for + Search. + GENERATE_VERTICAL_YOUTUBE_VIDEOS (3): + Converts horizontal video assets to vertical + orientation using content-aware technology. By + default, advertisers are opted in for + DemandGenVideoResponsiveAd. + GENERATE_SHORTER_YOUTUBE_VIDEOS (4): + Shortens video assets to better capture user + attention using content-aware technology. By + default, advertisers are opted in for + DemandGenVideoResponsiveAd. + GENERATE_LANDING_PAGE_PREVIEW (5): + Generates a preview of the landing page shown + in the engagement panel. + By using this feature, you confirm that you own + all legal rights to the images on the landing + page used by this account (or you have + permission to share the images with Google). You + hereby instruct Google to publish these images + on your behalf for advertising or other + commercial purposes. + GENERATE_ENHANCED_YOUTUBE_VIDEOS (6): + Generates video enhancements (vertical and + shorter videos) for PMax campaigns. Opted in by + default. + GENERATE_IMAGE_ENHANCEMENT (7): + Generates image enhancements (AutoCrop and + AutoEnhance). Opted in by default for pmax. + GENERATE_IMAGE_EXTRACTION (9): + Generates image extraction. It defaults to + account level Dynamic Image Extension control + value. + GENERATE_DESIGN_VERSIONS_FOR_IMAGES (10): + Adds design elements and embeds text assets + into image assets to create images with + different aspect ratios. By default, advertisers + are opted in for DemandGenMultiAssetAd. + FINAL_URL_EXPANSION_TEXT_ASSET_AUTOMATION (11): + Controls automation for text assets related + to Final URL expansion. This includes + automatically creating dynamic landing pages + from the final URL and generating text assets + from the content of those landing pages. This + setting is turned OFF by default for Search + campaigns, but it is turned ON by default for + Performance Max campaigns. + GENERATE_VIDEOS_FROM_OTHER_ASSETS (12): + Generates videos using other Assets as input, + such as images and text. By default, advertisers + are opted in for DemandGenMultiAssetAd. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + TEXT_ASSET_AUTOMATION = 2 + GENERATE_VERTICAL_YOUTUBE_VIDEOS = 3 + GENERATE_SHORTER_YOUTUBE_VIDEOS = 4 + GENERATE_LANDING_PAGE_PREVIEW = 5 + GENERATE_ENHANCED_YOUTUBE_VIDEOS = 6 + GENERATE_IMAGE_ENHANCEMENT = 7 + GENERATE_IMAGE_EXTRACTION = 9 + GENERATE_DESIGN_VERSIONS_FOR_IMAGES = 10 + FINAL_URL_EXPANSION_TEXT_ASSET_AUTOMATION = 11 + GENERATE_VIDEOS_FROM_OTHER_ASSETS = 12 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_coverage_video_aspect_ratio_requirement.py b/google/ads/googleads/v24/enums/types/asset_coverage_video_aspect_ratio_requirement.py new file mode 100644 index 000000000..0cf04f858 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_coverage_video_aspect_ratio_requirement.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetCoverageVideoAspectRatioRequirementEnum", + }, +) + + +class AssetCoverageVideoAspectRatioRequirementEnum(proto.Message): + r"""Container for enum describing possible ad strength video + aspect ratio requirements. + + """ + + class AssetCoverageVideoAspectRatioRequirement(proto.Enum): + r"""Enum describing possible ad strength video aspect ratio + requirements. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The received value is not known in this + version. + HORIZONTAL (2): + The video requires a horizontal aspect ratio. + SQUARE (3): + The video requires a square aspect ratio. + VERTICAL (4): + The video requires a vertical aspect ratio. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + HORIZONTAL = 2 + SQUARE = 3 + VERTICAL = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_field_type.py b/google/ads/googleads/v24/enums/types/asset_field_type.py new file mode 100644 index 000000000..f1c7b621a --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_field_type.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetFieldTypeEnum", + }, +) + + +class AssetFieldTypeEnum(proto.Message): + r"""Container for enum describing the possible placements of an + asset. + + """ + + class AssetFieldType(proto.Enum): + r"""Enum describing the possible placements of an asset. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + HEADLINE (2): + The asset is linked for use as a headline. + DESCRIPTION (3): + The asset is linked for use as a description. + MANDATORY_AD_TEXT (4): + The asset is linked for use as mandatory ad + text. + MARKETING_IMAGE (5): + The asset is linked for use as a marketing + image. + MEDIA_BUNDLE (6): + The asset is linked for use as a media + bundle. + YOUTUBE_VIDEO (7): + The asset is linked for use as a YouTube + video. + BOOK_ON_GOOGLE (8): + The asset is linked to indicate that a hotels + campaign is "Book on Google" enabled. + LEAD_FORM (9): + The asset is linked for use as a Lead Form + extension. + PROMOTION (10): + The asset is linked for use as a Promotion + extension. + CALLOUT (11): + The asset is linked for use as a Callout + extension. + STRUCTURED_SNIPPET (12): + The asset is linked for use as a Structured + Snippet extension. + SITELINK (13): + The asset is linked for use as a Sitelink. + MOBILE_APP (14): + The asset is linked for use as a Mobile App + extension. + HOTEL_CALLOUT (15): + The asset is linked for use as a Hotel + Callout extension. + CALL (16): + The asset is linked for use as a Call + extension. + PRICE (24): + The asset is linked for use as a Price + extension. + LONG_HEADLINE (17): + The asset is linked for use as a long + headline. + BUSINESS_NAME (18): + The asset is linked for use as a business + name. + SQUARE_MARKETING_IMAGE (19): + The asset is linked for use as a square + marketing image. + PORTRAIT_MARKETING_IMAGE (20): + The asset is linked for use as a portrait + marketing image. + LOGO (21): + The asset is linked for use as a logo. + LANDSCAPE_LOGO (22): + The asset is linked for use as a landscape + logo. + VIDEO (23): + The asset is linked for use as a non YouTube + logo. + CALL_TO_ACTION_SELECTION (25): + The asset is linked for use to select a + call-to-action. + AD_IMAGE (26): + The asset is linked for use to select an ad + image. + BUSINESS_LOGO (27): + The asset is linked for use as a business + logo. + HOTEL_PROPERTY (28): + The asset is linked for use as a hotel + property in a Performance Max for travel goals + campaign. + DEMAND_GEN_CAROUSEL_CARD (30): + The asset is linked for use as a Demand Gen + carousel card. + BUSINESS_MESSAGE (31): + The asset is linked for use as a Business + Message. + TALL_PORTRAIT_MARKETING_IMAGE (32): + The asset is linked for use as a tall + portrait marketing image. + RELATED_YOUTUBE_VIDEOS (33): + The asset is linked for use as related + YouTube videos. + LANDING_PAGE_PREVIEW (38): + The asset is linked for use as a landing page + preview image. + LONG_DESCRIPTION (39): + The asset is linked for use as a long + description. + CALL_TO_ACTION (40): + The asset is linked for use as a + call-to-action. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + HEADLINE = 2 + DESCRIPTION = 3 + MANDATORY_AD_TEXT = 4 + MARKETING_IMAGE = 5 + MEDIA_BUNDLE = 6 + YOUTUBE_VIDEO = 7 + BOOK_ON_GOOGLE = 8 + LEAD_FORM = 9 + PROMOTION = 10 + CALLOUT = 11 + STRUCTURED_SNIPPET = 12 + SITELINK = 13 + MOBILE_APP = 14 + HOTEL_CALLOUT = 15 + CALL = 16 + PRICE = 24 + LONG_HEADLINE = 17 + BUSINESS_NAME = 18 + SQUARE_MARKETING_IMAGE = 19 + PORTRAIT_MARKETING_IMAGE = 20 + LOGO = 21 + LANDSCAPE_LOGO = 22 + VIDEO = 23 + CALL_TO_ACTION_SELECTION = 25 + AD_IMAGE = 26 + BUSINESS_LOGO = 27 + HOTEL_PROPERTY = 28 + DEMAND_GEN_CAROUSEL_CARD = 30 + BUSINESS_MESSAGE = 31 + TALL_PORTRAIT_MARKETING_IMAGE = 32 + RELATED_YOUTUBE_VIDEOS = 33 + LANDING_PAGE_PREVIEW = 38 + LONG_DESCRIPTION = 39 + CALL_TO_ACTION = 40 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_group_primary_status.py b/google/ads/googleads/v24/enums/types/asset_group_primary_status.py new file mode 100644 index 000000000..73674e207 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_group_primary_status.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGroupPrimaryStatusEnum", + }, +) + + +class AssetGroupPrimaryStatusEnum(proto.Message): + r"""Container for enum describing possible asset group primary + status. + + """ + + class AssetGroupPrimaryStatus(proto.Enum): + r"""Enum describing the possible asset group primary status. + Provides insights into why an asset group is not serving or not + serving optimally. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ELIGIBLE (2): + The asset group is eligible to serve. + PAUSED (3): + The asset group is paused. + REMOVED (4): + The asset group is removed. + NOT_ELIGIBLE (5): + The asset group is not eligible to serve. + LIMITED (6): + The asset group has limited servability. + PENDING (7): + The asset group is pending approval and may + serve in the future. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ELIGIBLE = 2 + PAUSED = 3 + REMOVED = 4 + NOT_ELIGIBLE = 5 + LIMITED = 6 + PENDING = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_group_primary_status_reason.py b/google/ads/googleads/v24/enums/types/asset_group_primary_status_reason.py new file mode 100644 index 000000000..5ef30dd63 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_group_primary_status_reason.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGroupPrimaryStatusReasonEnum", + }, +) + + +class AssetGroupPrimaryStatusReasonEnum(proto.Message): + r"""Container for enum describing possible asset group primary + status reasons. + + """ + + class AssetGroupPrimaryStatusReason(proto.Enum): + r"""Enum describing the possible asset group primary status + reasons. Provides reasons into why an asset group is not serving + or not serving optimally. It will be empty when the asset group + is serving without issues. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ASSET_GROUP_PAUSED (2): + The user-specified asset group status is + paused. Contributes to + AssetGroupPrimaryStatus.PAUSED + ASSET_GROUP_REMOVED (3): + The user-specified asset group status is + removed. Contributes to + AssetGroupPrimaryStatus.REMOVED. + CAMPAIGN_REMOVED (4): + The user-specified campaign status is removed. Contributes + to AssetGroupPrimaryStatus.NOT_ELIGIBLE. + CAMPAIGN_PAUSED (5): + The user-specified campaign status is paused. Contributes to + AssetGroupPrimaryStatus.NOT_ELIGIBLE. + CAMPAIGN_PENDING (6): + The user-specified time for this campaign to start is in the + future. Contributes to AssetGroupPrimaryStatus.NOT_ELIGIBLE. + CAMPAIGN_ENDED (7): + The user-specified time for this campaign to end has passed. + Contributes to AssetGroupPrimaryStatus.NOT_ELIGIBLE. + ASSET_GROUP_LIMITED (8): + The asset group is approved but only serves + in limited capacity due to policies. Contributes + to AssetGroupPrimaryStatus.LIMITED. + ASSET_GROUP_DISAPPROVED (9): + The asset group has been marked as disapproved. Contributes + to AssetGroupPrimaryStatus.NOT_ELIGIBLE. + ASSET_GROUP_UNDER_REVIEW (10): + The asset group has not completed policy + review. Contributes to + AssetGroupPrimaryStatus.PENDING. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ASSET_GROUP_PAUSED = 2 + ASSET_GROUP_REMOVED = 3 + CAMPAIGN_REMOVED = 4 + CAMPAIGN_PAUSED = 5 + CAMPAIGN_PENDING = 6 + CAMPAIGN_ENDED = 7 + ASSET_GROUP_LIMITED = 8 + ASSET_GROUP_DISAPPROVED = 9 + ASSET_GROUP_UNDER_REVIEW = 10 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_group_signal_approval_status.py b/google/ads/googleads/v24/enums/types/asset_group_signal_approval_status.py new file mode 100644 index 000000000..fa7fe1d2d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_group_signal_approval_status.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGroupSignalApprovalStatusEnum", + }, +) + + +class AssetGroupSignalApprovalStatusEnum(proto.Message): + r"""Container for enum describing possible AssetGroupSignal + approval statuses. Details see + https://support.google.com/google-ads/answer/2453978. + + """ + + class AssetGroupSignalApprovalStatus(proto.Enum): + r"""Enumerates AssetGroupSignal approval statuses, which are only + used for Search Theme Signal. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + APPROVED (2): + Search Theme is eligible to show ads. + LIMITED (3): + Low search volume; Below first page bid + estimate. + DISAPPROVED (4): + Search Theme is inactive and isn't showing + ads. A disapproved Search Theme usually means + there's an issue with one or more of our + advertising policies. + UNDER_REVIEW (5): + Search Theme is under review. It won’t be + able to trigger ads until it's been reviewed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + APPROVED = 2 + LIMITED = 3 + DISAPPROVED = 4 + UNDER_REVIEW = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_group_status.py b/google/ads/googleads/v24/enums/types/asset_group_status.py new file mode 100644 index 000000000..eba9e79d6 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_group_status.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGroupStatusEnum", + }, +) + + +class AssetGroupStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of an asset + group. + + """ + + class AssetGroupStatus(proto.Enum): + r"""The possible statuses of an asset group. + + Values: + UNSPECIFIED (0): + The status has not been specified. + UNKNOWN (1): + The received value is not known in this + version. + ENABLED (2): + The asset group is enabled. + PAUSED (3): + The asset group is paused. + REMOVED (4): + The asset group is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + PAUSED = 3 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_link_primary_status.py b/google/ads/googleads/v24/enums/types/asset_link_primary_status.py new file mode 100644 index 000000000..6882b7596 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_link_primary_status.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetLinkPrimaryStatusEnum", + }, +) + + +class AssetLinkPrimaryStatusEnum(proto.Message): + r"""Provides the primary status of an asset link. + For example: a sitelink may be paused for a particular campaign. + + """ + + class AssetLinkPrimaryStatus(proto.Enum): + r"""Enum Provides insight into why an asset is not serving or not + serving at full capacity for a particular link level. There + could be one status with multiple reasons. For example, a + sitelink might be paused by the user, but also limited in + serving due to violation of an alcohol policy. In this case, the + PrimaryStatus will be returned as PAUSED, since the asset's + effective status is determined by its paused state. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ELIGIBLE (2): + The asset is eligible to serve. + PAUSED (3): + The user-specified asset link status is + paused. + REMOVED (4): + The user-specified asset link status is + removed. + PENDING (5): + The asset may serve in the future. + LIMITED (6): + The asset is serving in a partial capacity. + NOT_ELIGIBLE (7): + The asset is not eligible to serve. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ELIGIBLE = 2 + PAUSED = 3 + REMOVED = 4 + PENDING = 5 + LIMITED = 6 + NOT_ELIGIBLE = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_link_primary_status_reason.py b/google/ads/googleads/v24/enums/types/asset_link_primary_status_reason.py new file mode 100644 index 000000000..418850a66 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_link_primary_status_reason.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetLinkPrimaryStatusReasonEnum", + }, +) + + +class AssetLinkPrimaryStatusReasonEnum(proto.Message): + r"""Provides the reason of a primary status. + For example: a sitelink may be paused for a particular campaign. + + """ + + class AssetLinkPrimaryStatusReason(proto.Enum): + r"""Enum Provides insight into why an asset is not serving or not + serving at full capacity for a particular link level. These + reasons are aggregated to determine a final PrimaryStatus. + For example, a sitelink might be paused by the user, but also + limited in serving due to violation of an alcohol policy. In + this case, the PrimaryStatus will be returned as PAUSED, since + the asset's effective status is determined by its paused state. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ASSET_LINK_PAUSED (2): + The asset is paused for its linked rollup + level. Contributes to a PrimaryStatus of PAUSED. + ASSET_LINK_REMOVED (3): + The asset is removed for its linked rollup + level. Contributes to a PrimaryStatus of + REMOVED. + ASSET_DISAPPROVED (4): + The asset has been marked as disapproved. Contributes to a + PrimaryStatus of NOT_ELIGIBLE + ASSET_UNDER_REVIEW (5): + The asset has not completed policy review. + Contributes to a PrimaryStatus of PENDING. + ASSET_APPROVED_LABELED (6): + The asset is approved with policies applied. + Contributes to a PrimaryStatus of LIMITED. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ASSET_LINK_PAUSED = 2 + ASSET_LINK_REMOVED = 3 + ASSET_DISAPPROVED = 4 + ASSET_UNDER_REVIEW = 5 + ASSET_APPROVED_LABELED = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_link_status.py b/google/ads/googleads/v24/enums/types/asset_link_status.py new file mode 100644 index 000000000..0cb11aafd --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_link_status.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetLinkStatusEnum", + }, +) + + +class AssetLinkStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of an asset + link. + + """ + + class AssetLinkStatus(proto.Enum): + r"""Enum describing statuses of an asset link. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + Asset link is enabled. + REMOVED (3): + Asset link has been removed. + PAUSED (4): + Asset link is paused. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + PAUSED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_offline_evaluation_error_reasons.py b/google/ads/googleads/v24/enums/types/asset_offline_evaluation_error_reasons.py new file mode 100644 index 000000000..36e41abc4 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_offline_evaluation_error_reasons.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetOfflineEvaluationErrorReasonsEnum", + }, +) + + +class AssetOfflineEvaluationErrorReasonsEnum(proto.Message): + r"""Provides the quality evaluation disapproval reason of an + asset. + + """ + + class AssetOfflineEvaluationErrorReasons(proto.Enum): + r"""Enum describing the quality evaluation disapproval reason of + an asset. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PRICE_ASSET_DESCRIPTION_REPEATS_ROW_HEADER (2): + One or more descriptions repeats its + corresponding row header. + PRICE_ASSET_REPETITIVE_HEADERS (3): + Price asset contains repetitive headers. + PRICE_ASSET_HEADER_INCOMPATIBLE_WITH_PRICE_TYPE (4): + Price item header is not relevant to the + price type. + PRICE_ASSET_DESCRIPTION_INCOMPATIBLE_WITH_ITEM_HEADER (5): + Price item description is not relevant to the + item header. + PRICE_ASSET_DESCRIPTION_HAS_PRICE_QUALIFIER (6): + Price asset has a price qualifier in a + description. + PRICE_ASSET_UNSUPPORTED_LANGUAGE (7): + Unsupported language for price assets + PRICE_ASSET_OTHER_ERROR (8): + Human raters identified an issue with the + price asset that isn't captured by other error + reasons. The primary purpose of this value is to + represent legacy FeedItem disapprovals that are + no longer produced. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PRICE_ASSET_DESCRIPTION_REPEATS_ROW_HEADER = 2 + PRICE_ASSET_REPETITIVE_HEADERS = 3 + PRICE_ASSET_HEADER_INCOMPATIBLE_WITH_PRICE_TYPE = 4 + PRICE_ASSET_DESCRIPTION_INCOMPATIBLE_WITH_ITEM_HEADER = 5 + PRICE_ASSET_DESCRIPTION_HAS_PRICE_QUALIFIER = 6 + PRICE_ASSET_UNSUPPORTED_LANGUAGE = 7 + PRICE_ASSET_OTHER_ERROR = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_orientation.py b/google/ads/googleads/v24/enums/types/asset_orientation.py new file mode 100644 index 000000000..7d309f41c --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_orientation.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetOrientationEnum", + }, +) + + +class AssetOrientationEnum(proto.Message): + r"""Container for enum describing the orientation of an image or + video asset. + + """ + + class AssetOrientation(proto.Enum): + r"""The orientation of an image or video asset. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + LANDSCAPE (2): + Landscape orientation. + PORTRAIT (3): + Portrait orientation. + SQUARE (4): + Square orientation. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LANDSCAPE = 2 + PORTRAIT = 3 + SQUARE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_performance_label.py b/google/ads/googleads/v24/enums/types/asset_performance_label.py new file mode 100644 index 000000000..572478f7e --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_performance_label.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetPerformanceLabelEnum", + }, +) + + +class AssetPerformanceLabelEnum(proto.Message): + r"""Container for enum describing the performance label of an + asset. + + """ + + class AssetPerformanceLabel(proto.Enum): + r"""Enum describing the possible performance labels of an asset, + usually computed in the context of a linkage. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PENDING (2): + This asset does not yet have any performance + informantion. This may be because it is still + under review. + LEARNING (3): + The asset has started getting impressions but + the stats are not statistically significant + enough to get an asset performance label. + LOW (4): + Worst performing assets. + GOOD (5): + Good performing assets. + BEST (6): + Best performing assets. + NOT_APPLICABLE (7): + Performance label cannot be assigned to this + asset. This may be because it's not used by + asset based creatives. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + LEARNING = 3 + LOW = 4 + GOOD = 5 + BEST = 6 + NOT_APPLICABLE = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_set_asset_status.py b/google/ads/googleads/v24/enums/types/asset_set_asset_status.py new file mode 100644 index 000000000..89cdb2954 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_set_asset_status.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetSetAssetStatusEnum", + }, +) + + +class AssetSetAssetStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of an asset + set asset. + + """ + + class AssetSetAssetStatus(proto.Enum): + r"""The possible statuses of an asset set asset. + + Values: + UNSPECIFIED (0): + The status has not been specified. + UNKNOWN (1): + The received value is not known in this + version. This is a response-only value. + ENABLED (2): + The asset set asset is enabled. + REMOVED (3): + The asset set asset is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_set_link_status.py b/google/ads/googleads/v24/enums/types/asset_set_link_status.py new file mode 100644 index 000000000..0685e52f1 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_set_link_status.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetSetLinkStatusEnum", + }, +) + + +class AssetSetLinkStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of the + linkage between asset set and its container. + + """ + + class AssetSetLinkStatus(proto.Enum): + r"""The possible statuses of the linkage between asset set and + its container. + + Values: + UNSPECIFIED (0): + The status has not been specified. + UNKNOWN (1): + The received value is not known in this + version. This is a response-only value. + ENABLED (2): + The linkage between asset set and its + container is enabled. + REMOVED (3): + The linkage between asset set and its + container is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_set_status.py b/google/ads/googleads/v24/enums/types/asset_set_status.py new file mode 100644 index 000000000..c4f436e9e --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_set_status.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetSetStatusEnum", + }, +) + + +class AssetSetStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of an asset + set. + + """ + + class AssetSetStatus(proto.Enum): + r"""The possible statuses of an asset set. + + Values: + UNSPECIFIED (0): + The status has not been specified. + UNKNOWN (1): + The received value is not known in this + version. This is a response-only value. + ENABLED (2): + The asset set is enabled. + REMOVED (3): + The asset set is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_set_type.py b/google/ads/googleads/v24/enums/types/asset_set_type.py new file mode 100644 index 000000000..b2b82e052 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_set_type.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetSetTypeEnum", + }, +) + + +class AssetSetTypeEnum(proto.Message): + r"""Container for enum describing possible types of an asset set.""" + + class AssetSetType(proto.Enum): + r"""Possible types of an asset set. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PAGE_FEED (2): + Page asset set. + DYNAMIC_EDUCATION (3): + Dynamic education asset set. + MERCHANT_CENTER_FEED (4): + Google Merchant Center asset set. + DYNAMIC_REAL_ESTATE (5): + Dynamic real estate asset set. + DYNAMIC_CUSTOM (6): + Dynamic custom asset set. + DYNAMIC_HOTELS_AND_RENTALS (7): + Dynamic hotels and rentals asset set. + DYNAMIC_FLIGHTS (8): + Dynamic flights asset set. + DYNAMIC_TRAVEL (9): + Dynamic travel asset set. + DYNAMIC_LOCAL (10): + Dynamic local asset set. + DYNAMIC_JOBS (11): + Dynamic jobs asset set. + LOCATION_SYNC (12): + Location sync level asset set. + BUSINESS_PROFILE_DYNAMIC_LOCATION_GROUP (13): + Business Profile location group asset set. + CHAIN_DYNAMIC_LOCATION_GROUP (14): + Chain location group asset set which can be + used for both owned locations and affiliate + locations. + STATIC_LOCATION_GROUP (15): + Static location group asset set which can be + used for both owned locations and affiliate + locations. + HOTEL_PROPERTY (16): + Hotel Property asset set which is used to + link a hotel property feed to Performance Max + for travel goals campaigns. + TRAVEL_FEED (17): + Travel Feed asset set type. Can represent + either a Hotel feed or a Things to Do + (activities) feed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PAGE_FEED = 2 + DYNAMIC_EDUCATION = 3 + MERCHANT_CENTER_FEED = 4 + DYNAMIC_REAL_ESTATE = 5 + DYNAMIC_CUSTOM = 6 + DYNAMIC_HOTELS_AND_RENTALS = 7 + DYNAMIC_FLIGHTS = 8 + DYNAMIC_TRAVEL = 9 + DYNAMIC_LOCAL = 10 + DYNAMIC_JOBS = 11 + LOCATION_SYNC = 12 + BUSINESS_PROFILE_DYNAMIC_LOCATION_GROUP = 13 + CHAIN_DYNAMIC_LOCATION_GROUP = 14 + STATIC_LOCATION_GROUP = 15 + HOTEL_PROPERTY = 16 + TRAVEL_FEED = 17 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_source.py b/google/ads/googleads/v24/enums/types/asset_source.py new file mode 100644 index 000000000..4668085db --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_source.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetSourceEnum", + }, +) + + +class AssetSourceEnum(proto.Message): + r"""Source of the asset or asset link for who generated the + entity. For example, advertiser or automatically created. + + """ + + class AssetSource(proto.Enum): + r"""Enum describing possible source of asset. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ADVERTISER (2): + The asset or asset link is provided by + advertiser. + AUTOMATICALLY_CREATED (3): + The asset or asset link is generated by + Google. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ADVERTISER = 2 + AUTOMATICALLY_CREATED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/asset_type.py b/google/ads/googleads/v24/enums/types/asset_type.py new file mode 100644 index 000000000..2a13fea42 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/asset_type.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AssetTypeEnum", + }, +) + + +class AssetTypeEnum(proto.Message): + r"""Container for enum describing the types of asset.""" + + class AssetType(proto.Enum): + r"""Enum describing possible types of asset. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + YOUTUBE_VIDEO (2): + YouTube video asset. + MEDIA_BUNDLE (3): + Media bundle asset. + IMAGE (4): + Image asset. + TEXT (5): + Text asset. + LEAD_FORM (6): + Lead form asset. + BOOK_ON_GOOGLE (7): + Book on Google asset. + PROMOTION (8): + Promotion asset. + CALLOUT (9): + Callout asset. + STRUCTURED_SNIPPET (10): + Structured Snippet asset. + SITELINK (11): + Sitelink asset. + PAGE_FEED (12): + Page Feed asset. + DYNAMIC_EDUCATION (13): + Dynamic Education asset. + MOBILE_APP (14): + Mobile app asset. + HOTEL_CALLOUT (15): + Hotel callout asset. + CALL (16): + Call asset. + PRICE (17): + Price asset. + CALL_TO_ACTION (18): + Call to action asset. + DYNAMIC_REAL_ESTATE (19): + Dynamic real estate asset. + DYNAMIC_CUSTOM (20): + Dynamic custom asset. + DYNAMIC_HOTELS_AND_RENTALS (21): + Dynamic hotels and rentals asset. + DYNAMIC_FLIGHTS (22): + Dynamic flights asset. + DYNAMIC_TRAVEL (24): + Dynamic travel asset. + DYNAMIC_LOCAL (25): + Dynamic local asset. + DYNAMIC_JOBS (26): + Dynamic jobs asset. + LOCATION (27): + Location asset. + HOTEL_PROPERTY (28): + Hotel property asset. + DEMAND_GEN_CAROUSEL_CARD (29): + Demand Gen Carousel Card asset. + BUSINESS_MESSAGE (30): + Business message asset. + APP_DEEP_LINK (31): + App deep link asset. + YOUTUBE_VIDEO_LIST (32): + YouTube video list asset. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + YOUTUBE_VIDEO = 2 + MEDIA_BUNDLE = 3 + IMAGE = 4 + TEXT = 5 + LEAD_FORM = 6 + BOOK_ON_GOOGLE = 7 + PROMOTION = 8 + CALLOUT = 9 + STRUCTURED_SNIPPET = 10 + SITELINK = 11 + PAGE_FEED = 12 + DYNAMIC_EDUCATION = 13 + MOBILE_APP = 14 + HOTEL_CALLOUT = 15 + CALL = 16 + PRICE = 17 + CALL_TO_ACTION = 18 + DYNAMIC_REAL_ESTATE = 19 + DYNAMIC_CUSTOM = 20 + DYNAMIC_HOTELS_AND_RENTALS = 21 + DYNAMIC_FLIGHTS = 22 + DYNAMIC_TRAVEL = 24 + DYNAMIC_LOCAL = 25 + DYNAMIC_JOBS = 26 + LOCATION = 27 + HOTEL_PROPERTY = 28 + DEMAND_GEN_CAROUSEL_CARD = 29 + BUSINESS_MESSAGE = 30 + APP_DEEP_LINK = 31 + YOUTUBE_VIDEO_LIST = 32 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/async_action_status.py b/google/ads/googleads/v24/enums/types/async_action_status.py new file mode 100644 index 000000000..372aca03d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/async_action_status.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AsyncActionStatusEnum", + }, +) + + +class AsyncActionStatusEnum(proto.Message): + r"""Container for enum describing the experiment async action + status. + + """ + + class AsyncActionStatus(proto.Enum): + r"""The async action status of the experiment. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + NOT_STARTED (2): + Action has not started. + IN_PROGRESS (3): + Action is in progress. + COMPLETED (4): + Action has completed successfully. + FAILED (5): + Action has failed. + COMPLETED_WITH_WARNING (6): + Action has completed successfully with + warnings. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NOT_STARTED = 2 + IN_PROGRESS = 3 + COMPLETED = 4 + FAILED = 5 + COMPLETED_WITH_WARNING = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/attribution_model.py b/google/ads/googleads/v24/enums/types/attribution_model.py new file mode 100644 index 000000000..54881fc93 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/attribution_model.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AttributionModelEnum", + }, +) + + +class AttributionModelEnum(proto.Message): + r"""Container for enum representing the attribution model that + describes how to distribute credit for a particular conversion + across potentially many prior interactions. + + """ + + class AttributionModel(proto.Enum): + r"""The attribution model that describes how to distribute credit + for a particular conversion across potentially many prior + interactions. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + EXTERNAL (100): + Uses external attribution. + GOOGLE_ADS_LAST_CLICK (101): + Attributes all credit for a conversion to its + last click. + GOOGLE_SEARCH_ATTRIBUTION_FIRST_CLICK (102): + Attributes all credit for a conversion to its + first click using Google Search attribution. + GOOGLE_SEARCH_ATTRIBUTION_LINEAR (103): + Attributes credit for a conversion equally + across all of its clicks using Google Search + attribution. + GOOGLE_SEARCH_ATTRIBUTION_TIME_DECAY (104): + Attributes exponentially more credit for a + conversion to its more recent clicks using + Google Search attribution (half-life is 1 week). + GOOGLE_SEARCH_ATTRIBUTION_POSITION_BASED (105): + Attributes 40% of the credit for a conversion + to its first and last clicks. Remaining 20% is + evenly distributed across all other clicks. This + uses Google Search attribution. + GOOGLE_SEARCH_ATTRIBUTION_DATA_DRIVEN (106): + Flexible model that uses machine learning to + determine the appropriate distribution of credit + among clicks using Google Search attribution. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EXTERNAL = 100 + GOOGLE_ADS_LAST_CLICK = 101 + GOOGLE_SEARCH_ATTRIBUTION_FIRST_CLICK = 102 + GOOGLE_SEARCH_ATTRIBUTION_LINEAR = 103 + GOOGLE_SEARCH_ATTRIBUTION_TIME_DECAY = 104 + GOOGLE_SEARCH_ATTRIBUTION_POSITION_BASED = 105 + GOOGLE_SEARCH_ATTRIBUTION_DATA_DRIVEN = 106 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/audience_insights_dimension.py b/google/ads/googleads/v24/enums/types/audience_insights_dimension.py new file mode 100644 index 000000000..718846133 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/audience_insights_dimension.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AudienceInsightsDimensionEnum", + }, +) + + +class AudienceInsightsDimensionEnum(proto.Message): + r"""Container for enum describing insights dimensions.""" + + class AudienceInsightsDimension(proto.Enum): + r"""Possible dimensions for use in generating insights. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + CATEGORY (2): + A Product & Service category. + KNOWLEDGE_GRAPH (3): + A Knowledge Graph entity. + GEO_TARGET_COUNTRY (4): + A country, represented by a geo target. + SUB_COUNTRY_LOCATION (5): + A geographic location within a country. + YOUTUBE_CHANNEL (6): + A YouTube channel. + AFFINITY_USER_INTEREST (8): + An Affinity UserInterest. + IN_MARKET_USER_INTEREST (9): + An In-Market UserInterest. + PARENTAL_STATUS (10): + A Parental Status value (parent, or not a + parent). + INCOME_RANGE (11): + A household income percentile range. + AGE_RANGE (12): + An age range. + GENDER (13): + A gender. + YOUTUBE_VIDEO (14): + A YouTube video. + DEVICE (15): + A device type, such as Mobile, Desktop, + Tablet, and Connected TV. + YOUTUBE_LINEUP (16): + A YouTube Lineup. + USER_LIST (17): + A User List. + LIFE_EVENT_USER_INTEREST (18): + A Life Event UserInterest. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CATEGORY = 2 + KNOWLEDGE_GRAPH = 3 + GEO_TARGET_COUNTRY = 4 + SUB_COUNTRY_LOCATION = 5 + YOUTUBE_CHANNEL = 6 + AFFINITY_USER_INTEREST = 8 + IN_MARKET_USER_INTEREST = 9 + PARENTAL_STATUS = 10 + INCOME_RANGE = 11 + AGE_RANGE = 12 + GENDER = 13 + YOUTUBE_VIDEO = 14 + DEVICE = 15 + YOUTUBE_LINEUP = 16 + USER_LIST = 17 + LIFE_EVENT_USER_INTEREST = 18 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/audience_insights_marketing_objective.py b/google/ads/googleads/v24/enums/types/audience_insights_marketing_objective.py new file mode 100644 index 000000000..b64135f38 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/audience_insights_marketing_objective.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AudienceInsightsMarketingObjectiveEnum", + }, +) + + +class AudienceInsightsMarketingObjectiveEnum(proto.Message): + r"""Container for enum describing marketing objectives.""" + + class AudienceInsightsMarketingObjective(proto.Enum): + r"""Describes the overall objective for defining an audience for + insights. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + AWARENESS (2): + The objective is to increase awareness of a + brand or product among relevant audiences. + CONSIDERATION (3): + The objective is to encourage potential + customers to consider your brand or products + when they're researching or shopping for + product. + RESEARCH (4): + The objective is for research, to gain + further insights into your audience. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AWARENESS = 2 + CONSIDERATION = 3 + RESEARCH = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/audience_scope.py b/google/ads/googleads/v24/enums/types/audience_scope.py new file mode 100644 index 000000000..6cb45472c --- /dev/null +++ b/google/ads/googleads/v24/enums/types/audience_scope.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AudienceScopeEnum", + }, +) + + +class AudienceScopeEnum(proto.Message): + r"""Defines the scope an audience can be used in.""" + + class AudienceScope(proto.Enum): + r"""Enum containing possible audience scope values. + + Values: + UNSPECIFIED (0): + The scope has not been specified. + UNKNOWN (1): + The received value is not known in this + version. + CUSTOMER (2): + The audience is scoped at the customer level. + ASSET_GROUP (3): + The audience is scoped under a specific + AssetGroup. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER = 2 + ASSET_GROUP = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/audience_status.py b/google/ads/googleads/v24/enums/types/audience_status.py new file mode 100644 index 000000000..e43f47621 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/audience_status.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "AudienceStatusEnum", + }, +) + + +class AudienceStatusEnum(proto.Message): + r"""The status of audience.""" + + class AudienceStatus(proto.Enum): + r"""Enum containing possible audience status types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + Enabled status - audience is enabled and can + be targeted. + REMOVED (3): + Removed status - audience is removed and + cannot be used for targeting. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/batch_job_status.py b/google/ads/googleads/v24/enums/types/batch_job_status.py new file mode 100644 index 000000000..847eca7d6 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/batch_job_status.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BatchJobStatusEnum", + }, +) + + +class BatchJobStatusEnum(proto.Message): + r"""Container for enum describing possible batch job statuses.""" + + class BatchJobStatus(proto.Enum): + r"""The batch job statuses. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PENDING (2): + The job is not currently running. + RUNNING (3): + The job is running. + DONE (4): + The job is done. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + RUNNING = 3 + DONE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/benchmarks_marketing_objective.py b/google/ads/googleads/v24/enums/types/benchmarks_marketing_objective.py new file mode 100644 index 000000000..0ee86cb3b --- /dev/null +++ b/google/ads/googleads/v24/enums/types/benchmarks_marketing_objective.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BenchmarksMarketingObjectiveEnum", + }, +) + + +class BenchmarksMarketingObjectiveEnum(proto.Message): + r"""Container for enum describing YouTube ad benchmarks marketing + objectives. + + """ + + class BenchmarksMarketingObjective(proto.Enum): + r"""The YouTube ad benchmarks marketing objective. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + AWARENESS (2): + The objective is to increase awareness. + CONSIDERATION (3): + The objective is to encourage potential + customers to consider the brand or products. + ACTION (4): + The objective is to drive a specific + conversion, such as a purchase. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AWARENESS = 2 + CONSIDERATION = 3 + ACTION = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/benchmarks_source_type.py b/google/ads/googleads/v24/enums/types/benchmarks_source_type.py new file mode 100644 index 000000000..c9e12983c --- /dev/null +++ b/google/ads/googleads/v24/enums/types/benchmarks_source_type.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BenchmarksSourceTypeEnum", + }, +) + + +class BenchmarksSourceTypeEnum(proto.Message): + r"""Container for enum describing YouTube ad benchmarks sources.""" + + class BenchmarksSourceType(proto.Enum): + r"""Possible YouTube ad benchmarks sources. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + INDUSTRY_VERTICAL (2): + The classification of ad categories for + benchmarking. (for example, "Technology" or + "Finance"). + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INDUSTRY_VERTICAL = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/benchmarks_time_granularity.py b/google/ads/googleads/v24/enums/types/benchmarks_time_granularity.py new file mode 100644 index 000000000..ba5e60c30 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/benchmarks_time_granularity.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BenchmarksTimeGranularityEnum", + }, +) + + +class BenchmarksTimeGranularityEnum(proto.Message): + r"""Container for enum describing time granularities for + aggregating YouTube ad benchmarks data. + + """ + + class BenchmarksTimeGranularity(proto.Enum): + r"""Possible time granularities for aggregating YouTube ad + benchmarks data. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used as a return value only. Represents value + unknown in this version. + WEEK (2): + Aggregate by week. + MONTH (3): + Aggregate by month. + QUARTER (4): + Aggregate by quarter. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + WEEK = 2 + MONTH = 3 + QUARTER = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/bid_modifier_source.py b/google/ads/googleads/v24/enums/types/bid_modifier_source.py new file mode 100644 index 000000000..a8828211e --- /dev/null +++ b/google/ads/googleads/v24/enums/types/bid_modifier_source.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BidModifierSourceEnum", + }, +) + + +class BidModifierSourceEnum(proto.Message): + r"""Container for enum describing possible bid modifier sources.""" + + class BidModifierSource(proto.Enum): + r"""Enum describing possible bid modifier sources. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CAMPAIGN (2): + The bid modifier is specified at the campaign + level, on the campaign level criterion. + AD_GROUP (3): + The bid modifier is specified (overridden) at + the ad group level. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CAMPAIGN = 2 + AD_GROUP = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/bidding_source.py b/google/ads/googleads/v24/enums/types/bidding_source.py new file mode 100644 index 000000000..d5b25bf20 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/bidding_source.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BiddingSourceEnum", + }, +) + + +class BiddingSourceEnum(proto.Message): + r"""Container for enum describing possible bidding sources.""" + + class BiddingSource(proto.Enum): + r"""Indicates where a bid or target is defined. For example, an + ad group criterion may define a cpc bid directly, or it can + inherit its cpc bid from the ad group. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CAMPAIGN_BIDDING_STRATEGY (5): + Effective bid or target is inherited from + campaign bidding strategy. + AD_GROUP (6): + The bid or target is defined on the ad group. + AD_GROUP_CRITERION (7): + The bid or target is defined on the ad group + criterion. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CAMPAIGN_BIDDING_STRATEGY = 5 + AD_GROUP = 6 + AD_GROUP_CRITERION = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/bidding_strategy_status.py b/google/ads/googleads/v24/enums/types/bidding_strategy_status.py new file mode 100644 index 000000000..1d779c300 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/bidding_strategy_status.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BiddingStrategyStatusEnum", + }, +) + + +class BiddingStrategyStatusEnum(proto.Message): + r"""Message describing BiddingStrategy statuses.""" + + class BiddingStrategyStatus(proto.Enum): + r"""The possible statuses of a BiddingStrategy. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + ENABLED (2): + The bidding strategy is enabled. + REMOVED (4): + The bidding strategy is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/bidding_strategy_system_status.py b/google/ads/googleads/v24/enums/types/bidding_strategy_system_status.py new file mode 100644 index 000000000..52760b482 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/bidding_strategy_system_status.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BiddingStrategySystemStatusEnum", + }, +) + + +class BiddingStrategySystemStatusEnum(proto.Message): + r"""Message describing BiddingStrategy system statuses.""" + + class BiddingStrategySystemStatus(proto.Enum): + r"""The possible system statuses of a BiddingStrategy. + + Values: + UNSPECIFIED (0): + Signals that an unexpected error occurred, + for example, no bidding strategy type was found, + or no status information was found. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + The bid strategy is active, and AdWords + cannot find any specific issues with the + strategy. + LEARNING_NEW (3): + The bid strategy is learning because it has + been recently created or recently reactivated. + LEARNING_SETTING_CHANGE (4): + The bid strategy is learning because of a + recent setting change. + LEARNING_BUDGET_CHANGE (5): + The bid strategy is learning because of a + recent budget change. + LEARNING_COMPOSITION_CHANGE (6): + The bid strategy is learning because of + recent change in number of campaigns, ad groups + or keywords attached to it. + LEARNING_CONVERSION_TYPE_CHANGE (7): + The bid strategy depends on conversion + reporting and the customer recently modified + conversion types that were relevant to the bid + strategy. + LEARNING_CONVERSION_SETTING_CHANGE (8): + The bid strategy depends on conversion + reporting and the customer recently changed + their conversion settings. + LIMITED_BY_CPC_BID_CEILING (9): + The bid strategy is limited by its bid + ceiling. + LIMITED_BY_CPC_BID_FLOOR (10): + The bid strategy is limited by its bid floor. + LIMITED_BY_DATA (11): + The bid strategy is limited because there was + not enough conversion traffic over the past + weeks. + LIMITED_BY_BUDGET (12): + A significant fraction of keywords in this + bid strategy are limited by budget. + LIMITED_BY_LOW_PRIORITY_SPEND (13): + The bid strategy cannot reach its target + spend because its spend has been de-prioritized. + LIMITED_BY_LOW_QUALITY (14): + A significant fraction of keywords in this + bid strategy have a low Quality Score. + LIMITED_BY_INVENTORY (15): + The bid strategy cannot fully spend its + budget because of narrow targeting. + MISCONFIGURED_ZERO_ELIGIBILITY (16): + Missing conversion tracking (no pings + present) and/or remarketing lists for SSC. + MISCONFIGURED_CONVERSION_TYPES (17): + The bid strategy depends on conversion + reporting and the customer is lacking conversion + types that might be reported against this + strategy. + MISCONFIGURED_CONVERSION_SETTINGS (18): + The bid strategy depends on conversion + reporting and the customer's conversion settings + are misconfigured. + MISCONFIGURED_SHARED_BUDGET (19): + There are campaigns outside the bid strategy + that share budgets with campaigns included in + the strategy. + MISCONFIGURED_STRATEGY_TYPE (20): + The campaign has an invalid strategy type and + is not serving. + PAUSED (21): + The bid strategy is not active. Either there + are no active campaigns, ad groups or keywords + attached to the bid strategy. Or there are no + active budgets connected to the bid strategy. + UNAVAILABLE (22): + This bid strategy currently does not support + status reporting. + MULTIPLE_LEARNING (23): + There were multiple LEARNING\_\* system statuses for this + bid strategy during the time in question. + MULTIPLE_LIMITED (24): + There were multiple LIMITED\_\* system statuses for this bid + strategy during the time in question. + MULTIPLE_MISCONFIGURED (25): + There were multiple MISCONFIGURED\_\* system statuses for + this bid strategy during the time in question. + MULTIPLE (26): + There were multiple system statuses for this + bid strategy during the time in question. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + LEARNING_NEW = 3 + LEARNING_SETTING_CHANGE = 4 + LEARNING_BUDGET_CHANGE = 5 + LEARNING_COMPOSITION_CHANGE = 6 + LEARNING_CONVERSION_TYPE_CHANGE = 7 + LEARNING_CONVERSION_SETTING_CHANGE = 8 + LIMITED_BY_CPC_BID_CEILING = 9 + LIMITED_BY_CPC_BID_FLOOR = 10 + LIMITED_BY_DATA = 11 + LIMITED_BY_BUDGET = 12 + LIMITED_BY_LOW_PRIORITY_SPEND = 13 + LIMITED_BY_LOW_QUALITY = 14 + LIMITED_BY_INVENTORY = 15 + MISCONFIGURED_ZERO_ELIGIBILITY = 16 + MISCONFIGURED_CONVERSION_TYPES = 17 + MISCONFIGURED_CONVERSION_SETTINGS = 18 + MISCONFIGURED_SHARED_BUDGET = 19 + MISCONFIGURED_STRATEGY_TYPE = 20 + PAUSED = 21 + UNAVAILABLE = 22 + MULTIPLE_LEARNING = 23 + MULTIPLE_LIMITED = 24 + MULTIPLE_MISCONFIGURED = 25 + MULTIPLE = 26 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/bidding_strategy_type.py b/google/ads/googleads/v24/enums/types/bidding_strategy_type.py new file mode 100644 index 000000000..9b034796b --- /dev/null +++ b/google/ads/googleads/v24/enums/types/bidding_strategy_type.py @@ -0,0 +1,168 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BiddingStrategyTypeEnum", + }, +) + + +class BiddingStrategyTypeEnum(proto.Message): + r"""Container for enum describing possible bidding strategy + types. + + """ + + class BiddingStrategyType(proto.Enum): + r"""Enum describing possible bidding strategy types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + COMMISSION (16): + Commission is an automatic bidding strategy + in which the advertiser pays a certain portion + of the conversion value. + ENHANCED_CPC (2): + Enhanced CPC is a bidding strategy that + raises bids for clicks that seem more likely to + lead to a conversion and lowers them for clicks + where they seem less likely. + FIXED_CPM (19): + Fixed CPM is a manual bidding strategy with a + fixed CPM. + FIXED_SHARE_OF_VOICE (22): + Fixed share of voice is a manual bidding + strategy for YouTube Sponsorships that bills + either on CPM or a fixed cost per day. + INVALID (17): + Used for return value only. Indicates that a + campaign does not have a bidding strategy. This + prevents the campaign from serving. For example, + a campaign may be attached to a manager bidding + strategy and the serving account is subsequently + unlinked from the manager account. In this case + the campaign will automatically be detached from + the now inaccessible manager bidding strategy + and transition to the INVALID bidding strategy + type. + MANUAL_CPA (18): + Manual bidding strategy that allows + advertiser to set the bid per + advertiser-specified action. + MANUAL_CPC (3): + Manual click based bidding where user pays + per click. + MANUAL_CPM (4): + Manual impression based bidding + where user pays per thousand impressions. + MANUAL_CPV (13): + A bidding strategy that pays a configurable + amount per video view. + MAXIMIZE_CONVERSIONS (10): + A bidding strategy that automatically + maximizes number of conversions given a daily + budget. + MAXIMIZE_CONVERSION_VALUE (11): + An automated bidding strategy that + automatically sets bids to maximize revenue + while spending your budget. + PAGE_ONE_PROMOTED (5): + Page-One Promoted bidding scheme, which sets + max cpc bids to target impressions on page one + or page one promoted slots on google.com. This + enum value is deprecated. + PERCENT_CPC (12): + Percent Cpc is bidding strategy where bids + are a fraction of the advertised price for some + good or service. + TARGET_CPA (6): + Target CPA is an automated bid strategy that + sets bids to help get as many conversions as + possible at the target cost-per-acquisition + (CPA) you set. + TARGET_CPC (21): + Target CPC is an automated bid strategy that + sets bids to help get as many clicks as possible + at the target cost-per-click (CPC) you set. + TARGET_CPM (14): + Target CPM is an automated bid strategy that + sets bids to help get as many impressions as + possible at the target cost per one thousand + impressions (CPM) you set. + TARGET_CPV (20): + Target CPV is an automated bidding strategy + that sets bids to optimize performance given the + average target cost per view. + TARGET_IMPRESSION_SHARE (15): + An automated bidding strategy that sets bids + so that a certain percentage of search ads are + shown at the top of the first page (or other + targeted location). + TARGET_OUTRANK_SHARE (7): + Target Outrank Share is an automated bidding + strategy that sets bids based on the target + fraction of auctions where the advertiser should + outrank a specific competitor. + This enum value is deprecated. + TARGET_ROAS (8): + Target ROAS is an automated bidding strategy + that helps you maximize revenue while averaging + a specific target Return On Average Spend + (ROAS). + TARGET_SPEND (9): + Target Spend is an automated bid strategy + that sets your bids to help get as many clicks + as possible within your budget. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + COMMISSION = 16 + ENHANCED_CPC = 2 + FIXED_CPM = 19 + FIXED_SHARE_OF_VOICE = 22 + INVALID = 17 + MANUAL_CPA = 18 + MANUAL_CPC = 3 + MANUAL_CPM = 4 + MANUAL_CPV = 13 + MAXIMIZE_CONVERSIONS = 10 + MAXIMIZE_CONVERSION_VALUE = 11 + PAGE_ONE_PROMOTED = 5 + PERCENT_CPC = 12 + TARGET_CPA = 6 + TARGET_CPC = 21 + TARGET_CPM = 14 + TARGET_CPV = 20 + TARGET_IMPRESSION_SHARE = 15 + TARGET_OUTRANK_SHARE = 7 + TARGET_ROAS = 8 + TARGET_SPEND = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/billing_setup_status.py b/google/ads/googleads/v24/enums/types/billing_setup_status.py new file mode 100644 index 000000000..ebfdb72bf --- /dev/null +++ b/google/ads/googleads/v24/enums/types/billing_setup_status.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BillingSetupStatusEnum", + }, +) + + +class BillingSetupStatusEnum(proto.Message): + r"""Message describing BillingSetup statuses.""" + + class BillingSetupStatus(proto.Enum): + r"""The possible statuses of a BillingSetup. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PENDING (2): + The billing setup is pending approval. + APPROVED_HELD (3): + The billing setup has been approved but the + corresponding first budget has not. This can + only occur for billing setups configured for + monthly invoicing. + APPROVED (4): + The billing setup has been approved. + CANCELLED (5): + The billing setup was cancelled by the user + prior to approval. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + APPROVED_HELD = 3 + APPROVED = 4 + CANCELLED = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/booking_status.py b/google/ads/googleads/v24/enums/types/booking_status.py new file mode 100644 index 000000000..233a11a87 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/booking_status.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BookingStatusEnum", + }, +) + + +class BookingStatusEnum(proto.Message): + r"""Container for enum with booking status.""" + + class BookingStatus(proto.Enum): + r"""Booking status. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BOOKED (2): + The booking is active and holds inventory for + the campaign. + HELD (3): + The campaign is holding inventory, but the + booking is not confirmed. + CAMPAIGN_ENDED (4): + The campaign has ended and is no longer + holding inventory. + HOLD_EXPIRED (5): + The hold on the inventory has expired. + BOOKING_CANCELLED (6): + The campaign was booked, but was in a + non-servable state for too long and the booking + was cancelled by the system. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BOOKED = 2 + HELD = 3 + CAMPAIGN_ENDED = 4 + HOLD_EXPIRED = 5 + BOOKING_CANCELLED = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/brand_request_rejection_reason.py b/google/ads/googleads/v24/enums/types/brand_request_rejection_reason.py new file mode 100644 index 000000000..ab2ba2b38 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/brand_request_rejection_reason.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BrandRequestRejectionReasonEnum", + }, +) + + +class BrandRequestRejectionReasonEnum(proto.Message): + r"""Container for enum describing rejection reasons for the + customer brand requests. + + """ + + class BrandRequestRejectionReason(proto.Enum): + r"""Enumeration of different brand request rejection reasons. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + EXISTING_BRAND (2): + Brand is already present in the commercial + brand set. + EXISTING_BRAND_VARIANT (3): + Brand is already present in the commercial + brand set, but is a variant. + INCORRECT_INFORMATION (4): + Brand information is not correct (eg: URL and + name don't match). + NOT_A_BRAND (5): + Not a valid brand as per Google policy. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EXISTING_BRAND = 2 + EXISTING_BRAND_VARIANT = 3 + INCORRECT_INFORMATION = 4 + NOT_A_BRAND = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/brand_safety_suitability.py b/google/ads/googleads/v24/enums/types/brand_safety_suitability.py new file mode 100644 index 000000000..b60bc6050 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/brand_safety_suitability.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BrandSafetySuitabilityEnum", + }, +) + + +class BrandSafetySuitabilityEnum(proto.Message): + r"""Container for enum with 3-Tier brand safety suitability + control. + + """ + + class BrandSafetySuitability(proto.Enum): + r"""3-Tier brand safety suitability control. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + EXPANDED_INVENTORY (2): + This option lets you show ads across all + inventory on YouTube and video partners that + meet our standards for monetization. This option + may be an appropriate choice for brands that + want maximum access to the full breadth of + videos eligible for ads, including, for example, + videos that have strong profanity in the context + of comedy or a documentary, or excessive + violence as featured in video games. + STANDARD_INVENTORY (3): + This option lets you show ads across a wide + range of content that's appropriate for most + brands, such as popular music videos, + documentaries, and movie trailers. The content + you can show ads on is based on YouTube's + advertiser-friendly content guidelines that take + into account, for example, the strength or + frequency of profanity, or the appropriateness + of subject matter like sensitive events. Ads + won't show, for example, on content with + repeated strong profanity, strong sexual + content, or graphic violence. + LIMITED_INVENTORY (4): + This option lets you show ads on a reduced + range of content that's appropriate for brands + with particularly strict guidelines around + inappropriate language and sexual + suggestiveness; above and beyond what YouTube's + advertiser-friendly content guidelines address. + The videos accessible in this sensitive category + meet heightened requirements, especially for + inappropriate language and sexual + suggestiveness. For example, your ads will be + excluded from showing on some of YouTube's most + popular music videos and other pop culture + content across YouTube and Google video + partners. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EXPANDED_INVENTORY = 2 + STANDARD_INVENTORY = 3 + LIMITED_INVENTORY = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/brand_state.py b/google/ads/googleads/v24/enums/types/brand_state.py new file mode 100644 index 000000000..1e9a087b9 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/brand_state.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BrandStateEnum", + }, +) + + +class BrandStateEnum(proto.Message): + r"""Container for enum describing possible brand states.""" + + class BrandState(proto.Enum): + r"""Enumeration of different brand states. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + Brand is verified and globally available for + selection + DEPRECATED (3): + Brand was globally available in past but is + no longer a valid brand (based on business + criteria) + UNVERIFIED (4): + Brand is unverified and customer scoped, but + can be selected by customer (only who requested + for same) for targeting + APPROVED (5): + Was a customer-scoped (unverified) brand, + which got approved by business and added to the + global list. Its assigned CKG MID should be used + instead of this + CANCELLED (6): + Was a customer-scoped (unverified) brand, but + the request was canceled by customer and this + brand id is no longer valid + REJECTED (7): + Was a customer-scoped (unverified) brand, but + the request was rejected by internal business + team and this brand id is no longer valid + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + DEPRECATED = 3 + UNVERIFIED = 4 + APPROVED = 5 + CANCELLED = 6 + REJECTED = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/budget_campaign_association_status.py b/google/ads/googleads/v24/enums/types/budget_campaign_association_status.py new file mode 100644 index 000000000..537a03ffb --- /dev/null +++ b/google/ads/googleads/v24/enums/types/budget_campaign_association_status.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BudgetCampaignAssociationStatusEnum", + }, +) + + +class BudgetCampaignAssociationStatusEnum(proto.Message): + r"""Message describing the status of the association between the + Budget and the Campaign. + + """ + + class BudgetCampaignAssociationStatus(proto.Enum): + r"""Possible statuses of the association between the Budget and + the Campaign. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + The campaign is currently using the budget. + REMOVED (3): + The campaign is no longer using the budget. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/budget_delivery_method.py b/google/ads/googleads/v24/enums/types/budget_delivery_method.py new file mode 100644 index 000000000..065f9bef6 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/budget_delivery_method.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BudgetDeliveryMethodEnum", + }, +) + + +class BudgetDeliveryMethodEnum(proto.Message): + r"""Message describing Budget delivery methods. A delivery method + determines the rate at which the Budget is spent. + + """ + + class BudgetDeliveryMethod(proto.Enum): + r"""Possible delivery methods of a Budget. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + STANDARD (2): + The budget server will throttle serving + evenly across the entire time period. + ACCELERATED (3): + The budget server will not throttle serving, + and ads will serve as fast as possible. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + STANDARD = 2 + ACCELERATED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/budget_period.py b/google/ads/googleads/v24/enums/types/budget_period.py new file mode 100644 index 000000000..0f7170306 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/budget_period.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BudgetPeriodEnum", + }, +) + + +class BudgetPeriodEnum(proto.Message): + r"""Message describing Budget period.""" + + class BudgetPeriod(proto.Enum): + r"""Possible period of a Budget. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + DAILY (2): + Daily budget. + CUSTOM_PERIOD (5): + Custom budget, added back in V5. Custom budget can be used + with total_amount to specify lifetime budget limit. See: + https://support.google.com/google-ads/answer/6385083 for + more info. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DAILY = 2 + CUSTOM_PERIOD = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/budget_status.py b/google/ads/googleads/v24/enums/types/budget_status.py new file mode 100644 index 000000000..1cb9ccff5 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/budget_status.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BudgetStatusEnum", + }, +) + + +class BudgetStatusEnum(proto.Message): + r"""Message describing a Budget status""" + + class BudgetStatus(proto.Enum): + r"""Possible statuses of a Budget. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + Budget is enabled. + REMOVED (3): + Budget is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/budget_type.py b/google/ads/googleads/v24/enums/types/budget_type.py new file mode 100644 index 000000000..065c1d8db --- /dev/null +++ b/google/ads/googleads/v24/enums/types/budget_type.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BudgetTypeEnum", + }, +) + + +class BudgetTypeEnum(proto.Message): + r"""Describes Budget types.""" + + class BudgetType(proto.Enum): + r"""Possible Budget types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + STANDARD (2): + Budget type for standard Google Ads usage. + Caps daily spend at two times the specified + budget amount. Full details: + https://support.google.com/google-ads/answer/6385083 + FIXED_CPA (4): + Budget type with a fixed cost-per-acquisition (conversion). + Full details: + https://support.google.com/google-ads/answer/7528254 + + This type is only supported by campaigns with + AdvertisingChannelType.DISPLAY (excluding + AdvertisingChannelSubType.DISPLAY_GMAIL), + BiddingStrategyType.TARGET_CPA and PaymentMode.CONVERSIONS. + SMART_CAMPAIGN (5): + Budget type for Smart Campaign. Full details: + https://support.google.com/google-ads/answer/7653509 + + This type is only supported by campaigns with + AdvertisingChannelType.SMART and + AdvertisingChannelSubType.SMART_CAMPAIGN. + LOCAL_SERVICES (6): + Budget type for Local Services Campaign. Full details: + https://support.google.com/localservices/answer/7434558 + + This type is only supported by campaigns with + AdvertisingChannelType.LOCAL_SERVICES. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + STANDARD = 2 + FIXED_CPA = 4 + SMART_CAMPAIGN = 5 + LOCAL_SERVICES = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/business_message_call_to_action_type.py b/google/ads/googleads/v24/enums/types/business_message_call_to_action_type.py new file mode 100644 index 000000000..bc1a57823 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/business_message_call_to_action_type.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BusinessMessageCallToActionTypeEnum", + }, +) + + +class BusinessMessageCallToActionTypeEnum(proto.Message): + r"""Describes the type of call-to-action phrases in a business + message. + + """ + + class BusinessMessageCallToActionType(proto.Enum): + r"""Enum describing the type of call-to-action phrases in a + business message. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + APPLY_NOW (2): + Apply now. + BOOK_NOW (3): + Book now. + CONTACT_US (4): + Contact us. + GET_INFO (5): + Get info. + GET_OFFER (6): + Get offer. + GET_QUOTE (7): + Get quote. + GET_STARTED (8): + Get started. + LEARN_MORE (9): + Learn more. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + APPLY_NOW = 2 + BOOK_NOW = 3 + CONTACT_US = 4 + GET_INFO = 5 + GET_OFFER = 6 + GET_QUOTE = 7 + GET_STARTED = 8 + LEARN_MORE = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/business_message_provider.py b/google/ads/googleads/v24/enums/types/business_message_provider.py new file mode 100644 index 000000000..880500757 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/business_message_provider.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "BusinessMessageProviderEnum", + }, +) + + +class BusinessMessageProviderEnum(proto.Message): + r"""Describes business message provider types.""" + + class BusinessMessageProvider(proto.Enum): + r"""The possible value of business message provider types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + WHATSAPP (2): + WhatsApp message provider + FACEBOOK_MESSENGER (3): + Facebook Messenger message provider + ZALO (4): + Zalo message provider + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + WHATSAPP = 2 + FACEBOOK_MESSENGER = 3 + ZALO = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/call_conversion_reporting_state.py b/google/ads/googleads/v24/enums/types/call_conversion_reporting_state.py new file mode 100644 index 000000000..1f62803e5 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/call_conversion_reporting_state.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CallConversionReportingStateEnum", + }, +) + + +class CallConversionReportingStateEnum(proto.Message): + r"""Container for enum describing possible data types for call + conversion reporting state. + + """ + + class CallConversionReportingState(proto.Enum): + r"""Possible data types for a call conversion action state. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + DISABLED (2): + Call conversion action is disabled. + USE_ACCOUNT_LEVEL_CALL_CONVERSION_ACTION (3): + Call conversion action will use call + conversion type set at the account level. + USE_RESOURCE_LEVEL_CALL_CONVERSION_ACTION (4): + Call conversion action will use call + conversion type set at the resource (call only + ads/call extensions) level. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DISABLED = 2 + USE_ACCOUNT_LEVEL_CALL_CONVERSION_ACTION = 3 + USE_RESOURCE_LEVEL_CALL_CONVERSION_ACTION = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/call_to_action_type.py b/google/ads/googleads/v24/enums/types/call_to_action_type.py new file mode 100644 index 000000000..988e171d6 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/call_to_action_type.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CallToActionTypeEnum", + }, +) + + +class CallToActionTypeEnum(proto.Message): + r"""Container for enum describing the call to action types.""" + + class CallToActionType(proto.Enum): + r"""Enum describing possible types of call to action. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + LEARN_MORE (2): + The call to action type is learn more. + GET_QUOTE (3): + The call to action type is get quote. + APPLY_NOW (4): + The call to action type is apply now. + SIGN_UP (5): + The call to action type is sign up. + CONTACT_US (6): + The call to action type is contact us. + SUBSCRIBE (7): + The call to action type is subscribe. + DOWNLOAD (8): + The call to action type is download. + BOOK_NOW (9): + The call to action type is book now. + SHOP_NOW (10): + The call to action type is shop now. + BUY_NOW (11): + The call to action type is buy now. + DONATE_NOW (12): + The call to action type is donate now. + ORDER_NOW (13): + The call to action type is order now. + PLAY_NOW (14): + The call to action type is play now. + SEE_MORE (15): + The call to action type is see more. + START_NOW (16): + The call to action type is start now. + VISIT_SITE (17): + The call to action type is visit site. + WATCH_NOW (18): + The call to action type is watch now. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LEARN_MORE = 2 + GET_QUOTE = 3 + APPLY_NOW = 4 + SIGN_UP = 5 + CONTACT_US = 6 + SUBSCRIBE = 7 + DOWNLOAD = 8 + BOOK_NOW = 9 + SHOP_NOW = 10 + BUY_NOW = 11 + DONATE_NOW = 12 + ORDER_NOW = 13 + PLAY_NOW = 14 + SEE_MORE = 15 + START_NOW = 16 + VISIT_SITE = 17 + WATCH_NOW = 18 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/call_tracking_display_location.py b/google/ads/googleads/v24/enums/types/call_tracking_display_location.py new file mode 100644 index 000000000..d9ebf294b --- /dev/null +++ b/google/ads/googleads/v24/enums/types/call_tracking_display_location.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CallTrackingDisplayLocationEnum", + }, +) + + +class CallTrackingDisplayLocationEnum(proto.Message): + r"""Container for enum describing possible call tracking display + locations. + + """ + + class CallTrackingDisplayLocation(proto.Enum): + r"""Possible call tracking display locations. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + AD (2): + The phone call placed from the ad. + LANDING_PAGE (3): + The phone call placed from the landing page + ad points to. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AD = 2 + LANDING_PAGE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/call_type.py b/google/ads/googleads/v24/enums/types/call_type.py new file mode 100644 index 000000000..2fa17aa3a --- /dev/null +++ b/google/ads/googleads/v24/enums/types/call_type.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CallTypeEnum", + }, +) + + +class CallTypeEnum(proto.Message): + r"""Container for enum describing possible types of property from + where the call was made. + + """ + + class CallType(proto.Enum): + r"""Possible types of property from where the call was made. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + MANUALLY_DIALED (2): + The phone call was manually dialed. + HIGH_END_MOBILE_SEARCH (3): + The phone call was a mobile click-to-call. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MANUALLY_DIALED = 2 + HIGH_END_MOBILE_SEARCH = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/campaign_criterion_status.py b/google/ads/googleads/v24/enums/types/campaign_criterion_status.py new file mode 100644 index 000000000..76982138d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/campaign_criterion_status.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignCriterionStatusEnum", + }, +) + + +class CampaignCriterionStatusEnum(proto.Message): + r"""Message describing CampaignCriterion statuses.""" + + class CampaignCriterionStatus(proto.Enum): + r"""The possible statuses of a CampaignCriterion. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + ENABLED (2): + The campaign criterion is enabled. + PAUSED (3): + The campaign criterion is paused. + REMOVED (4): + The campaign criterion is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + PAUSED = 3 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/campaign_draft_status.py b/google/ads/googleads/v24/enums/types/campaign_draft_status.py new file mode 100644 index 000000000..c9fe8660e --- /dev/null +++ b/google/ads/googleads/v24/enums/types/campaign_draft_status.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignDraftStatusEnum", + }, +) + + +class CampaignDraftStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a campaign + draft. + + """ + + class CampaignDraftStatus(proto.Enum): + r"""Possible statuses of a campaign draft. + + Values: + UNSPECIFIED (0): + The status has not been specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PROPOSED (2): + Initial state of the draft, the advertiser + can start adding changes with no effect on + serving. + REMOVED (3): + The campaign draft is removed. + PROMOTING (5): + Advertiser requested to promote draft's + changes back into the original campaign. + Advertiser can poll the long running operation + returned by the promote action to see the status + of the promotion. + PROMOTED (4): + The process to merge changes in the draft + back to the original campaign has completed + successfully. + PROMOTE_FAILED (6): + The promotion failed after it was partially + applied. Promote cannot be attempted again + safely, so the issue must be corrected in the + original campaign. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PROPOSED = 2 + REMOVED = 3 + PROMOTING = 5 + PROMOTED = 4 + PROMOTE_FAILED = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/campaign_experiment_type.py b/google/ads/googleads/v24/enums/types/campaign_experiment_type.py new file mode 100644 index 000000000..eb71ebf7a --- /dev/null +++ b/google/ads/googleads/v24/enums/types/campaign_experiment_type.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignExperimentTypeEnum", + }, +) + + +class CampaignExperimentTypeEnum(proto.Message): + r"""Container for enum describing campaign experiment type.""" + + class CampaignExperimentType(proto.Enum): + r"""Indicates if this campaign is a normal campaign, + a draft campaign, or an experiment campaign. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BASE (2): + This is a regular campaign. + DRAFT (3): + This is a draft version of a campaign. + It has some modifications from a base campaign, + but it does not serve or accrue metrics. + EXPERIMENT (4): + This is an experiment version of a campaign. + It has some modifications from a base campaign, + and a percentage of traffic is being diverted + from the BASE campaign to this experiment + campaign. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BASE = 2 + DRAFT = 3 + EXPERIMENT = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/campaign_group_status.py b/google/ads/googleads/v24/enums/types/campaign_group_status.py new file mode 100644 index 000000000..fbcc9c3de --- /dev/null +++ b/google/ads/googleads/v24/enums/types/campaign_group_status.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignGroupStatusEnum", + }, +) + + +class CampaignGroupStatusEnum(proto.Message): + r"""Message describing CampaignGroup statuses.""" + + class CampaignGroupStatus(proto.Enum): + r"""Possible statuses of a CampaignGroup. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + The campaign group is active. + REMOVED (3): + The campaign group has been removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/campaign_keyword_match_type.py b/google/ads/googleads/v24/enums/types/campaign_keyword_match_type.py new file mode 100644 index 000000000..4d7439e6e --- /dev/null +++ b/google/ads/googleads/v24/enums/types/campaign_keyword_match_type.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignKeywordMatchTypeEnum", + }, +) + + +class CampaignKeywordMatchTypeEnum(proto.Message): + r"""Container for enum describing keyword match type.""" + + class CampaignKeywordMatchType(proto.Enum): + r"""Enum describing keyword match type of Campaign. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BROAD (2): + Campaign level broad match. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BROAD = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/campaign_primary_status.py b/google/ads/googleads/v24/enums/types/campaign_primary_status.py new file mode 100644 index 000000000..827134c39 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/campaign_primary_status.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignPrimaryStatusEnum", + }, +) + + +class CampaignPrimaryStatusEnum(proto.Message): + r"""Container for enum describing possible campaign primary + status. + + """ + + class CampaignPrimaryStatus(proto.Enum): + r"""Enum describing the possible campaign primary status. + Provides insight into why a campaign is not serving or not + serving optimally. Modification to the campaign and its related + entities might take a while to be reflected in this status. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ELIGIBLE (2): + The campaign is eligible to serve. + PAUSED (3): + The user-specified campaign status is paused. + REMOVED (4): + The user-specified campaign status is + removed. + ENDED (5): + The user-specified time for this campaign to + end has passed. + PENDING (6): + The campaign may serve in the future. + MISCONFIGURED (7): + The campaign or its associated entities have + incorrect user-specified settings. + LIMITED (8): + The campaign or its associated entities are + limited by user-specified settings. + LEARNING (9): + The automated bidding system is adjusting to + user-specified changes to the campaign or + associated entities. + NOT_ELIGIBLE (10): + The campaign is not eligible to serve. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ELIGIBLE = 2 + PAUSED = 3 + REMOVED = 4 + ENDED = 5 + PENDING = 6 + MISCONFIGURED = 7 + LIMITED = 8 + LEARNING = 9 + NOT_ELIGIBLE = 10 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/campaign_primary_status_reason.py b/google/ads/googleads/v24/enums/types/campaign_primary_status_reason.py new file mode 100644 index 000000000..628c350b9 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/campaign_primary_status_reason.py @@ -0,0 +1,225 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignPrimaryStatusReasonEnum", + }, +) + + +class CampaignPrimaryStatusReasonEnum(proto.Message): + r"""Container for enum describing possible campaign primary + status reasons. + + """ + + class CampaignPrimaryStatusReason(proto.Enum): + r"""Enum describing the possible campaign primary status reasons. + Provides insight into why a campaign is not serving or not + serving optimally. These reasons are aggregated to determine an + overall campaign primary status. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CAMPAIGN_REMOVED (2): + The user-specified campaign status is + removed. + CAMPAIGN_PAUSED (3): + The user-specified campaign status is paused. + CAMPAIGN_PENDING (4): + The user-specified time for this campaign to + start is in the future. + CAMPAIGN_ENDED (5): + The user-specified time for this campaign to + end has passed. + CAMPAIGN_DRAFT (6): + The campaign is a draft. + BIDDING_STRATEGY_MISCONFIGURED (7): + The bidding strategy has incorrect + user-specified settings. + BIDDING_STRATEGY_LIMITED (8): + The bidding strategy is limited by + user-specified settings such as lack of data or + similar. + BIDDING_STRATEGY_LEARNING (9): + The automated bidding system is adjusting to + user-specified changes to the bidding strategy. + BIDDING_STRATEGY_CONSTRAINED (10): + Campaign could capture more conversion value + by adjusting CPA/ROAS targets. + BUDGET_CONSTRAINED (11): + The budget is limiting the campaign's ability + to serve. + BUDGET_MISCONFIGURED (12): + The budget has incorrect user-specified + settings. + SEARCH_VOLUME_LIMITED (13): + Campaign is not targeting all relevant + queries. + AD_GROUPS_PAUSED (14): + The user-specified ad group statuses are all + paused. + NO_AD_GROUPS (15): + No eligible ad groups exist in this campaign. + KEYWORDS_PAUSED (16): + The user-specified keyword statuses are all + paused. + NO_KEYWORDS (17): + No eligible keywords exist in this campaign. + AD_GROUP_ADS_PAUSED (18): + The user-specified ad group ad statuses are + all paused. + NO_AD_GROUP_ADS (19): + No eligible ad group ads exist in this + campaign. + HAS_ADS_LIMITED_BY_POLICY (20): + At least one ad in this campaign is limited + by policy. + HAS_ADS_DISAPPROVED (21): + At least one ad in this campaign is + disapproved. + MOST_ADS_UNDER_REVIEW (22): + Most ads in this campaign are pending review. + MISSING_LEAD_FORM_EXTENSION (23): + The campaign has a lead form goal, and the + lead form extension is missing. + MISSING_CALL_EXTENSION (24): + The campaign has a call goal, and the call + extension is missing. + LEAD_FORM_EXTENSION_UNDER_REVIEW (25): + The lead form extension is under review. + LEAD_FORM_EXTENSION_DISAPPROVED (26): + The lead extension is disapproved. + CALL_EXTENSION_UNDER_REVIEW (27): + The call extension is under review. + CALL_EXTENSION_DISAPPROVED (28): + The call extension is disapproved. + NO_MOBILE_APPLICATION_AD_GROUP_CRITERIA (29): + No eligible mobile application ad group + criteria exist in this campaign. + CAMPAIGN_GROUP_PAUSED (30): + The user-specified campaign group status is + paused. + CAMPAIGN_GROUP_ALL_GROUP_BUDGETS_ENDED (31): + The user-specified times of all group budgets + associated with the parent campaign group has + passed. + APP_NOT_RELEASED (32): + The app associated with this ACi campaign is + not released in the target countries of the + campaign. + APP_PARTIALLY_RELEASED (33): + The app associated with this ACi campaign is + partially released in the target countries of + the campaign. + HAS_ASSET_GROUPS_DISAPPROVED (34): + At least one asset group in this campaign is + disapproved. + HAS_ASSET_GROUPS_LIMITED_BY_POLICY (35): + At least one asset group in this campaign is + limited by policy. + MOST_ASSET_GROUPS_UNDER_REVIEW (36): + Most asset groups in this campaign are + pending review. + NO_ASSET_GROUPS (37): + No eligible asset groups exist in this + campaign. + ASSET_GROUPS_PAUSED (38): + All asset groups in this campaign are paused. + MISSING_LOCATION_TARGETING (39): + The campaign has location restrictions but + does not specify location targeting. + CAMPAIGN_NOT_BOOKED (40): + The campaign is a campaign with the FIXED_CPM bidding + strategy but is not booked. Contributes to + CampaignPrimaryStatus.NOT_ELIGIBLE when the campaign is not + paused, and CampaignPrimaryStatus.PAUSED when the campaign + is paused. + BOOKING_HOLD_EXPIRING (41): + The campaign is a campaign with the FIXED_CPM bidding + strategy for which inventory was held, with the hold + expiring. The hold expiry time can be read from + Campaign.booking_details.hold_expiration_date_time. + Contributes to CampaignPrimaryStatus.PAUSED. + BOOKING_HOLD_EXPIRED (42): + The campaign is a campaign with the FIXED_CPM bidding + strategy with the inventory hold expired. Contributes to + CampaignPrimaryStatus.PAUSED. + BOOKING_CANCELLED (43): + The campaign is a campaign with the FIXED_CPM bidding + strategy that has been auto-cancelled. Contributes to + CampaignPrimaryStatus.NOT_ELIGIBLE. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CAMPAIGN_REMOVED = 2 + CAMPAIGN_PAUSED = 3 + CAMPAIGN_PENDING = 4 + CAMPAIGN_ENDED = 5 + CAMPAIGN_DRAFT = 6 + BIDDING_STRATEGY_MISCONFIGURED = 7 + BIDDING_STRATEGY_LIMITED = 8 + BIDDING_STRATEGY_LEARNING = 9 + BIDDING_STRATEGY_CONSTRAINED = 10 + BUDGET_CONSTRAINED = 11 + BUDGET_MISCONFIGURED = 12 + SEARCH_VOLUME_LIMITED = 13 + AD_GROUPS_PAUSED = 14 + NO_AD_GROUPS = 15 + KEYWORDS_PAUSED = 16 + NO_KEYWORDS = 17 + AD_GROUP_ADS_PAUSED = 18 + NO_AD_GROUP_ADS = 19 + HAS_ADS_LIMITED_BY_POLICY = 20 + HAS_ADS_DISAPPROVED = 21 + MOST_ADS_UNDER_REVIEW = 22 + MISSING_LEAD_FORM_EXTENSION = 23 + MISSING_CALL_EXTENSION = 24 + LEAD_FORM_EXTENSION_UNDER_REVIEW = 25 + LEAD_FORM_EXTENSION_DISAPPROVED = 26 + CALL_EXTENSION_UNDER_REVIEW = 27 + CALL_EXTENSION_DISAPPROVED = 28 + NO_MOBILE_APPLICATION_AD_GROUP_CRITERIA = 29 + CAMPAIGN_GROUP_PAUSED = 30 + CAMPAIGN_GROUP_ALL_GROUP_BUDGETS_ENDED = 31 + APP_NOT_RELEASED = 32 + APP_PARTIALLY_RELEASED = 33 + HAS_ASSET_GROUPS_DISAPPROVED = 34 + HAS_ASSET_GROUPS_LIMITED_BY_POLICY = 35 + MOST_ASSET_GROUPS_UNDER_REVIEW = 36 + NO_ASSET_GROUPS = 37 + ASSET_GROUPS_PAUSED = 38 + MISSING_LOCATION_TARGETING = 39 + CAMPAIGN_NOT_BOOKED = 40 + BOOKING_HOLD_EXPIRING = 41 + BOOKING_HOLD_EXPIRED = 42 + BOOKING_CANCELLED = 43 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/campaign_serving_status.py b/google/ads/googleads/v24/enums/types/campaign_serving_status.py new file mode 100644 index 000000000..55d576ff8 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/campaign_serving_status.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignServingStatusEnum", + }, +) + + +class CampaignServingStatusEnum(proto.Message): + r"""Message describing Campaign serving statuses.""" + + class CampaignServingStatus(proto.Enum): + r"""Possible serving statuses of a campaign. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + SERVING (2): + Serving. + NONE (3): + None. + ENDED (4): + Ended. + PENDING (5): + Pending. + SUSPENDED (6): + Suspended. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SERVING = 2 + NONE = 3 + ENDED = 4 + PENDING = 5 + SUSPENDED = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/campaign_shared_set_status.py b/google/ads/googleads/v24/enums/types/campaign_shared_set_status.py new file mode 100644 index 000000000..244c0f100 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/campaign_shared_set_status.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignSharedSetStatusEnum", + }, +) + + +class CampaignSharedSetStatusEnum(proto.Message): + r"""Container for enum describing types of campaign shared set + statuses. + + """ + + class CampaignSharedSetStatus(proto.Enum): + r"""Enum listing the possible campaign shared set statuses. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + The campaign shared set is enabled. + REMOVED (3): + The campaign shared set is removed and can no + longer be used. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/campaign_status.py b/google/ads/googleads/v24/enums/types/campaign_status.py new file mode 100644 index 000000000..08f40c6b1 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/campaign_status.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignStatusEnum", + }, +) + + +class CampaignStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a + campaign. + + """ + + class CampaignStatus(proto.Enum): + r"""Possible statuses of a campaign. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + Campaign is active and can show ads. + PAUSED (3): + Campaign has been paused by the user. + REMOVED (4): + Campaign has been removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + PAUSED = 3 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/chain_relationship_type.py b/google/ads/googleads/v24/enums/types/chain_relationship_type.py new file mode 100644 index 000000000..2dead6989 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/chain_relationship_type.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ChainRelationshipTypeEnum", + }, +) + + +class ChainRelationshipTypeEnum(proto.Message): + r"""Container for enum describing possible types of a + relationship. + + """ + + class ChainRelationshipType(proto.Enum): + r"""Possible types of a relationship. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + AUTO_DEALERS (2): + Auto dealer relationship. + GENERAL_RETAILERS (3): + General retailer relationship. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AUTO_DEALERS = 2 + GENERAL_RETAILERS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/change_client_type.py b/google/ads/googleads/v24/enums/types/change_client_type.py new file mode 100644 index 000000000..40843ab6a --- /dev/null +++ b/google/ads/googleads/v24/enums/types/change_client_type.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ChangeClientTypeEnum", + }, +) + + +class ChangeClientTypeEnum(proto.Message): + r"""Container for enum describing the sources that the change + event resource was made through. + + """ + + class ChangeClientType(proto.Enum): + r"""The source that the change_event resource was made through. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + Used for return value only. Represents an + unclassified client type unknown in this + version. + GOOGLE_ADS_WEB_CLIENT (2): + Changes made through the "ads.google.com". + For example, changes made through campaign + management. + GOOGLE_ADS_AUTOMATED_RULE (3): + Changes made through Google Ads automated + rules. + GOOGLE_ADS_SCRIPTS (4): + Changes made through Google Ads scripts. + GOOGLE_ADS_BULK_UPLOAD (5): + Changes made by Google Ads bulk upload. + GOOGLE_ADS_API (6): + Changes made by Google Ads API. + GOOGLE_ADS_EDITOR (7): + Changes made by Google Ads Editor. This value + is a placeholder. The API does not return these + changes. + GOOGLE_ADS_MOBILE_APP (8): + Changes made by Google Ads mobile app. + GOOGLE_ADS_RECOMMENDATIONS (9): + Changes made through Google Ads + recommendations. + SEARCH_ADS_360_SYNC (10): + Changes made through Search Ads 360 Sync. + SEARCH_ADS_360_POST (11): + Changes made through Search Ads 360 Post. + INTERNAL_TOOL (12): + Changes made through internal tools. + For example, when a user sets a URL template on + an entity like a Campaign, it's automatically + wrapped with the SA360 Clickserver URL. + OTHER (13): + Types of changes that are not categorized, + for example, changes made by coupon redemption + through Google Ads. + GOOGLE_ADS_RECOMMENDATIONS_SUBSCRIPTION (14): + Changes made by subscribing to Google Ads + recommendations. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + GOOGLE_ADS_WEB_CLIENT = 2 + GOOGLE_ADS_AUTOMATED_RULE = 3 + GOOGLE_ADS_SCRIPTS = 4 + GOOGLE_ADS_BULK_UPLOAD = 5 + GOOGLE_ADS_API = 6 + GOOGLE_ADS_EDITOR = 7 + GOOGLE_ADS_MOBILE_APP = 8 + GOOGLE_ADS_RECOMMENDATIONS = 9 + SEARCH_ADS_360_SYNC = 10 + SEARCH_ADS_360_POST = 11 + INTERNAL_TOOL = 12 + OTHER = 13 + GOOGLE_ADS_RECOMMENDATIONS_SUBSCRIPTION = 14 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/change_event_resource_type.py b/google/ads/googleads/v24/enums/types/change_event_resource_type.py new file mode 100644 index 000000000..0708ada09 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/change_event_resource_type.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ChangeEventResourceTypeEnum", + }, +) + + +class ChangeEventResourceTypeEnum(proto.Message): + r"""Container for enum describing supported resource types for + the ChangeEvent resource. + + """ + + class ChangeEventResourceType(proto.Enum): + r"""Enum listing the resource types support by the ChangeEvent + resource. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + Used for return value only. Represents an + unclassified resource unknown in this version. + AD (2): + An Ad resource change. + AD_GROUP (3): + An AdGroup resource change. + AD_GROUP_CRITERION (4): + An AdGroupCriterion resource change. + CAMPAIGN (5): + A Campaign resource change. + CAMPAIGN_BUDGET (6): + A CampaignBudget resource change. + AD_GROUP_BID_MODIFIER (7): + An AdGroupBidModifier resource change. + CAMPAIGN_CRITERION (8): + A CampaignCriterion resource change. + FEED (9): + A Feed resource change. + FEED_ITEM (10): + A FeedItem resource change. + CAMPAIGN_FEED (11): + A CampaignFeed resource change. + AD_GROUP_FEED (12): + An AdGroupFeed resource change. + AD_GROUP_AD (13): + An AdGroupAd resource change. + ASSET (14): + An Asset resource change. + CUSTOMER_ASSET (15): + A CustomerAsset resource change. + CAMPAIGN_ASSET (16): + A CampaignAsset resource change. + AD_GROUP_ASSET (17): + An AdGroupAsset resource change. + ASSET_SET (18): + An AssetSet resource change. + ASSET_SET_ASSET (19): + An AssetSetAsset resource change. + CAMPAIGN_ASSET_SET (20): + A CampaignAssetSet resource change. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AD = 2 + AD_GROUP = 3 + AD_GROUP_CRITERION = 4 + CAMPAIGN = 5 + CAMPAIGN_BUDGET = 6 + AD_GROUP_BID_MODIFIER = 7 + CAMPAIGN_CRITERION = 8 + FEED = 9 + FEED_ITEM = 10 + CAMPAIGN_FEED = 11 + AD_GROUP_FEED = 12 + AD_GROUP_AD = 13 + ASSET = 14 + CUSTOMER_ASSET = 15 + CAMPAIGN_ASSET = 16 + AD_GROUP_ASSET = 17 + ASSET_SET = 18 + ASSET_SET_ASSET = 19 + CAMPAIGN_ASSET_SET = 20 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/change_status_operation.py b/google/ads/googleads/v24/enums/types/change_status_operation.py new file mode 100644 index 000000000..42fa4b639 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/change_status_operation.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ChangeStatusOperationEnum", + }, +) + + +class ChangeStatusOperationEnum(proto.Message): + r"""Container for enum describing operations for the ChangeStatus + resource. + + """ + + class ChangeStatusOperation(proto.Enum): + r"""Status of the changed resource + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + Used for return value only. Represents an + unclassified resource unknown in this version. + ADDED (2): + The resource was created. + CHANGED (3): + The resource was modified. + REMOVED (4): + The resource was removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ADDED = 2 + CHANGED = 3 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/change_status_resource_type.py b/google/ads/googleads/v24/enums/types/change_status_resource_type.py new file mode 100644 index 000000000..6aa6680f5 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/change_status_resource_type.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ChangeStatusResourceTypeEnum", + }, +) + + +class ChangeStatusResourceTypeEnum(proto.Message): + r"""Container for enum describing supported resource types for + the ChangeStatus resource. + + """ + + class ChangeStatusResourceType(proto.Enum): + r"""Enum listing the resource types support by the ChangeStatus + resource. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + Used for return value only. Represents an + unclassified resource unknown in this version. + AD_GROUP (3): + An AdGroup resource change. + AD_GROUP_AD (4): + An AdGroupAd resource change. + AD_GROUP_CRITERION (5): + An AdGroupCriterion resource change. + CAMPAIGN (6): + A Campaign resource change. + CAMPAIGN_CRITERION (7): + A CampaignCriterion resource change. + CAMPAIGN_BUDGET (8): + A CampaignBudget resource change. + FEED (9): + A Feed resource change. + FEED_ITEM (10): + A FeedItem resource change. + AD_GROUP_FEED (11): + An AdGroupFeed resource change. + CAMPAIGN_FEED (12): + A CampaignFeed resource change. + AD_GROUP_BID_MODIFIER (13): + An AdGroupBidModifier resource change. + SHARED_SET (14): + A SharedSet resource change. + CAMPAIGN_SHARED_SET (15): + A CampaignSharedSet resource change. + ASSET (16): + An Asset resource change. + CUSTOMER_ASSET (17): + A CustomerAsset resource change. + CAMPAIGN_ASSET (18): + A CampaignAsset resource change. + AD_GROUP_ASSET (19): + An AdGroupAsset resource change. + COMBINED_AUDIENCE (20): + A CombinedAudience resource change. + ASSET_GROUP (21): + An AssetGroup resource change. + ASSET_SET (22): + An AssetSet resource change. + CAMPAIGN_ASSET_SET (23): + A CampaignAssetSet resource change. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AD_GROUP = 3 + AD_GROUP_AD = 4 + AD_GROUP_CRITERION = 5 + CAMPAIGN = 6 + CAMPAIGN_CRITERION = 7 + CAMPAIGN_BUDGET = 8 + FEED = 9 + FEED_ITEM = 10 + AD_GROUP_FEED = 11 + CAMPAIGN_FEED = 12 + AD_GROUP_BID_MODIFIER = 13 + SHARED_SET = 14 + CAMPAIGN_SHARED_SET = 15 + ASSET = 16 + CUSTOMER_ASSET = 17 + CAMPAIGN_ASSET = 18 + AD_GROUP_ASSET = 19 + COMBINED_AUDIENCE = 20 + ASSET_GROUP = 21 + ASSET_SET = 22 + CAMPAIGN_ASSET_SET = 23 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/click_type.py b/google/ads/googleads/v24/enums/types/click_type.py new file mode 100644 index 000000000..3daa36851 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/click_type.py @@ -0,0 +1,244 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ClickTypeEnum", + }, +) + + +class ClickTypeEnum(proto.Message): + r"""Container for enumeration of Google Ads click types.""" + + class ClickType(proto.Enum): + r"""Enumerates Google Ads click types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + APP_DEEPLINK (2): + App engagement ad deep link. + BREADCRUMBS (3): + Breadcrumbs. + BROADBAND_PLAN (4): + Broadband Plan. + CALL_TRACKING (5): + Manually dialed phone calls. + CALLS (6): + Phone calls. + CLICK_ON_ENGAGEMENT_AD (7): + Click on engagement ad. + GET_DIRECTIONS (8): + Driving direction. + LOCATION_EXPANSION (9): + Get location details. + LOCATION_FORMAT_CALL (10): + Call. + LOCATION_FORMAT_DIRECTIONS (11): + Directions. + LOCATION_FORMAT_IMAGE (12): + Image(s). + LOCATION_FORMAT_LANDING_PAGE (13): + Go to landing page. + LOCATION_FORMAT_MAP (14): + Map. + LOCATION_FORMAT_STORE_INFO (15): + Go to store info. + LOCATION_FORMAT_TEXT (16): + Text. + MOBILE_CALL_TRACKING (17): + Mobile phone calls. + OFFER_PRINTS (18): + Print offer. + OTHER (19): + Other. + PRODUCT_EXTENSION_CLICKS (20): + Product plusbox offer. + PRODUCT_LISTING_AD_CLICKS (21): + Shopping - Product - Online. + SITELINKS (22): + Sitelink. + STORE_LOCATOR (23): + Show nearby locations. + URL_CLICKS (25): + Headline. + VIDEO_APP_STORE_CLICKS (26): + App store. + VIDEO_CALL_TO_ACTION_CLICKS (27): + Call-to-Action overlay. + VIDEO_CARD_ACTION_HEADLINE_CLICKS (28): + Cards. + VIDEO_END_CAP_CLICKS (29): + End cap. + VIDEO_WEBSITE_CLICKS (30): + Website. + VISUAL_SITELINKS (31): + Visual Sitelinks. + WIRELESS_PLAN (32): + Wireless Plan. + PRODUCT_LISTING_AD_LOCAL (33): + Shopping - Product - Local. + PRODUCT_LISTING_AD_MULTICHANNEL_LOCAL (34): + Shopping - Product - MultiChannel Local. + PRODUCT_LISTING_AD_MULTICHANNEL_ONLINE (35): + Shopping - Product - MultiChannel Online. + PRODUCT_LISTING_ADS_COUPON (36): + Shopping - Product - Coupon. + PRODUCT_LISTING_AD_TRANSACTABLE (37): + Shopping - Product - Sell on Google. + PRODUCT_AD_APP_DEEPLINK (38): + Shopping - Product - App engagement ad deep + link. + SHOWCASE_AD_CATEGORY_LINK (39): + Shopping - Showcase - Category. + SHOWCASE_AD_LOCAL_STOREFRONT_LINK (40): + Shopping - Showcase - Local storefront. + SHOWCASE_AD_ONLINE_PRODUCT_LINK (42): + Shopping - Showcase - Online product. + SHOWCASE_AD_LOCAL_PRODUCT_LINK (43): + Shopping - Showcase - Local product. + PROMOTION_EXTENSION (44): + Promotion Extension. + SWIPEABLE_GALLERY_AD_HEADLINE (45): + Ad Headline. + SWIPEABLE_GALLERY_AD_SWIPES (46): + Swipes. + SWIPEABLE_GALLERY_AD_SEE_MORE (47): + See More. + SWIPEABLE_GALLERY_AD_SITELINK_ONE (48): + Sitelink 1. + SWIPEABLE_GALLERY_AD_SITELINK_TWO (49): + Sitelink 2. + SWIPEABLE_GALLERY_AD_SITELINK_THREE (50): + Sitelink 3. + SWIPEABLE_GALLERY_AD_SITELINK_FOUR (51): + Sitelink 4. + SWIPEABLE_GALLERY_AD_SITELINK_FIVE (52): + Sitelink 5. + HOTEL_PRICE (53): + Hotel price. + PRICE_EXTENSION (54): + Price Extension. + HOTEL_BOOK_ON_GOOGLE_ROOM_SELECTION (55): + Book on Google hotel room selection. + SHOPPING_COMPARISON_LISTING (56): + Shopping - Comparison Listing. + CROSS_NETWORK (57): + Cross-network. From Performance Max and + Discovery Campaigns. + AD_IMAGE (58): + AD Images. + TRAVEL_ASSETS (59): + Travel Feed Assets. + VEHICLE_ASSETS (60): + Vehicle Feed Assets. + PRODUCT_ASSETS (61): + Product Feed Assets. + VIDEO_CHANNEL_CLICK (62): + Click on channel icon that navigates the user + to the corresponding YouTube channel. + VIDEO_RELATED_VIDEOS_CLICK (63): + Click on a related video that navigates the + user to the video watch page. + CLICK_TO_MESSAGE_THIRD_PARTY_CLICK (64): + Click on message button that navigates the + user to a third-party messaging app. If the app + is not installed, the ad will not show on + Android, and the button will redirect to the app + install page on iOS. + CLICK_TO_MESSAGE_LANDING_PAGE_CLICK (65): + Click on non-button surface of message ad + that navigates the user to the Google-hosted + landing page. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + APP_DEEPLINK = 2 + BREADCRUMBS = 3 + BROADBAND_PLAN = 4 + CALL_TRACKING = 5 + CALLS = 6 + CLICK_ON_ENGAGEMENT_AD = 7 + GET_DIRECTIONS = 8 + LOCATION_EXPANSION = 9 + LOCATION_FORMAT_CALL = 10 + LOCATION_FORMAT_DIRECTIONS = 11 + LOCATION_FORMAT_IMAGE = 12 + LOCATION_FORMAT_LANDING_PAGE = 13 + LOCATION_FORMAT_MAP = 14 + LOCATION_FORMAT_STORE_INFO = 15 + LOCATION_FORMAT_TEXT = 16 + MOBILE_CALL_TRACKING = 17 + OFFER_PRINTS = 18 + OTHER = 19 + PRODUCT_EXTENSION_CLICKS = 20 + PRODUCT_LISTING_AD_CLICKS = 21 + SITELINKS = 22 + STORE_LOCATOR = 23 + URL_CLICKS = 25 + VIDEO_APP_STORE_CLICKS = 26 + VIDEO_CALL_TO_ACTION_CLICKS = 27 + VIDEO_CARD_ACTION_HEADLINE_CLICKS = 28 + VIDEO_END_CAP_CLICKS = 29 + VIDEO_WEBSITE_CLICKS = 30 + VISUAL_SITELINKS = 31 + WIRELESS_PLAN = 32 + PRODUCT_LISTING_AD_LOCAL = 33 + PRODUCT_LISTING_AD_MULTICHANNEL_LOCAL = 34 + PRODUCT_LISTING_AD_MULTICHANNEL_ONLINE = 35 + PRODUCT_LISTING_ADS_COUPON = 36 + PRODUCT_LISTING_AD_TRANSACTABLE = 37 + PRODUCT_AD_APP_DEEPLINK = 38 + SHOWCASE_AD_CATEGORY_LINK = 39 + SHOWCASE_AD_LOCAL_STOREFRONT_LINK = 40 + SHOWCASE_AD_ONLINE_PRODUCT_LINK = 42 + SHOWCASE_AD_LOCAL_PRODUCT_LINK = 43 + PROMOTION_EXTENSION = 44 + SWIPEABLE_GALLERY_AD_HEADLINE = 45 + SWIPEABLE_GALLERY_AD_SWIPES = 46 + SWIPEABLE_GALLERY_AD_SEE_MORE = 47 + SWIPEABLE_GALLERY_AD_SITELINK_ONE = 48 + SWIPEABLE_GALLERY_AD_SITELINK_TWO = 49 + SWIPEABLE_GALLERY_AD_SITELINK_THREE = 50 + SWIPEABLE_GALLERY_AD_SITELINK_FOUR = 51 + SWIPEABLE_GALLERY_AD_SITELINK_FIVE = 52 + HOTEL_PRICE = 53 + PRICE_EXTENSION = 54 + HOTEL_BOOK_ON_GOOGLE_ROOM_SELECTION = 55 + SHOPPING_COMPARISON_LISTING = 56 + CROSS_NETWORK = 57 + AD_IMAGE = 58 + TRAVEL_ASSETS = 59 + VEHICLE_ASSETS = 60 + PRODUCT_ASSETS = 61 + VIDEO_CHANNEL_CLICK = 62 + VIDEO_RELATED_VIDEOS_CLICK = 63 + CLICK_TO_MESSAGE_THIRD_PARTY_CLICK = 64 + CLICK_TO_MESSAGE_LANDING_PAGE_CLICK = 65 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/combined_audience_status.py b/google/ads/googleads/v24/enums/types/combined_audience_status.py new file mode 100644 index 000000000..add0a7ad7 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/combined_audience_status.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CombinedAudienceStatusEnum", + }, +) + + +class CombinedAudienceStatusEnum(proto.Message): + r"""The status of combined audience.""" + + class CombinedAudienceStatus(proto.Enum): + r"""Enum containing possible combined audience status types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + Enabled status - combined audience is enabled + and can be targeted. + REMOVED (3): + Removed status - combined audience is removed + and cannot be used for targeting. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/consent_status.py b/google/ads/googleads/v24/enums/types/consent_status.py new file mode 100644 index 000000000..6d7c8a6aa --- /dev/null +++ b/google/ads/googleads/v24/enums/types/consent_status.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConsentStatusEnum", + }, +) + + +class ConsentStatusEnum(proto.Message): + r"""Enums represent consent status.""" + + class ConsentStatus(proto.Enum): + r"""Consent status + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Output-only. Represents a format not yet + defined in this enum. + GRANTED (2): + Granted. + DENIED (3): + Denied. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + GRANTED = 2 + DENIED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/content_label_type.py b/google/ads/googleads/v24/enums/types/content_label_type.py new file mode 100644 index 000000000..387bb02ba --- /dev/null +++ b/google/ads/googleads/v24/enums/types/content_label_type.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ContentLabelTypeEnum", + }, +) + + +class ContentLabelTypeEnum(proto.Message): + r"""Container for enum describing content label types in + ContentLabel. + + """ + + class ContentLabelType(proto.Enum): + r"""Enum listing the content label types supported by + ContentLabel criterion. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + SEXUALLY_SUGGESTIVE (2): + Sexually suggestive content. + BELOW_THE_FOLD (3): + Below the fold placement. + PARKED_DOMAIN (4): + Parked domain. + JUVENILE (6): + Juvenile, gross & bizarre content. + PROFANITY (7): + Profanity & rough language. + TRAGEDY (8): + Death & tragedy. + VIDEO (9): + Video. + VIDEO_RATING_DV_G (10): + Content rating: G. + VIDEO_RATING_DV_PG (11): + Content rating: PG. + VIDEO_RATING_DV_T (12): + Content rating: T. + VIDEO_RATING_DV_MA (13): + Content rating: MA. + VIDEO_NOT_YET_RATED (14): + Content rating: not yet rated. + EMBEDDED_VIDEO (15): + Embedded video. + LIVE_STREAMING_VIDEO (16): + Live streaming video. + SOCIAL_ISSUES (17): + Sensitive social issues. + BRAND_SUITABILITY_CONTENT_FOR_FAMILIES (18): + Content that's suitable for families to view + together, including Made for Kids videos on + YouTube. + BRAND_SUITABILITY_GAMES_FIGHTING (19): + Video games that simulate hand-to-hand + fighting or combat with the use of modern or + medieval weapons. + BRAND_SUITABILITY_GAMES_MATURE (20): + Video games that feature mature content, such + as violence, inappropriate language, or sexual + suggestiveness. + BRAND_SUITABILITY_HEALTH_SENSITIVE (21): + Health content that people might find + sensitive or upsetting, such as medical + procedures or images and descriptions of various + medical conditions. + BRAND_SUITABILITY_HEALTH_SOURCE_UNDETERMINED (22): + Health content from sources that may provide + accurate information but aren't as commonly + cited as other, more well-known sources. + BRAND_SUITABILITY_NEWS_RECENT (23): + News content that's been recently announced, + regardless of the themes or people being + reported on. + BRAND_SUITABILITY_NEWS_SENSITIVE (24): + News content that people might find sensitive + or upsetting, such as crimes, accidents, and + natural incidents, or commentary on potentially + controversial social and political issues. + BRAND_SUITABILITY_NEWS_SOURCE_NOT_FEATURED (25): + News content from sources that aren't + featured on Google News or YouTube News. + BRAND_SUITABILITY_POLITICS (26): + Political content, such as political + statements made by well-known politicians, + political elections, or events widely perceived + to be political in nature. + BRAND_SUITABILITY_RELIGION (27): + Content with religious themes, such as + religious teachings or customs, holy sites or + places of worship, well-known religious figures + or people dressed in religious attire, or + religious opinions on social and political + issues. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SEXUALLY_SUGGESTIVE = 2 + BELOW_THE_FOLD = 3 + PARKED_DOMAIN = 4 + JUVENILE = 6 + PROFANITY = 7 + TRAGEDY = 8 + VIDEO = 9 + VIDEO_RATING_DV_G = 10 + VIDEO_RATING_DV_PG = 11 + VIDEO_RATING_DV_T = 12 + VIDEO_RATING_DV_MA = 13 + VIDEO_NOT_YET_RATED = 14 + EMBEDDED_VIDEO = 15 + LIVE_STREAMING_VIDEO = 16 + SOCIAL_ISSUES = 17 + BRAND_SUITABILITY_CONTENT_FOR_FAMILIES = 18 + BRAND_SUITABILITY_GAMES_FIGHTING = 19 + BRAND_SUITABILITY_GAMES_MATURE = 20 + BRAND_SUITABILITY_HEALTH_SENSITIVE = 21 + BRAND_SUITABILITY_HEALTH_SOURCE_UNDETERMINED = 22 + BRAND_SUITABILITY_NEWS_RECENT = 23 + BRAND_SUITABILITY_NEWS_SENSITIVE = 24 + BRAND_SUITABILITY_NEWS_SOURCE_NOT_FEATURED = 25 + BRAND_SUITABILITY_POLITICS = 26 + BRAND_SUITABILITY_RELIGION = 27 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_action_category.py b/google/ads/googleads/v24/enums/types/conversion_action_category.py new file mode 100644 index 000000000..bdfadc822 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_action_category.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionActionCategoryEnum", + }, +) + + +class ConversionActionCategoryEnum(proto.Message): + r"""Container for enum describing the category of conversions + that are associated with a ConversionAction. + + """ + + class ConversionActionCategory(proto.Enum): + r"""The category of conversions that are associated with a + ConversionAction. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + DEFAULT (2): + Default category. + PAGE_VIEW (3): + User visiting a page. + PURCHASE (4): + Purchase, sales, or "order placed" event. + SIGNUP (5): + Signup user action. + DOWNLOAD (7): + Software download action (as for an app). + ADD_TO_CART (8): + The addition of items to a shopping cart or + bag on an advertiser site. + BEGIN_CHECKOUT (9): + When someone enters the checkout flow on an + advertiser site. + SUBSCRIBE_PAID (10): + The start of a paid subscription for a + product or service. + PHONE_CALL_LEAD (11): + A call to indicate interest in an + advertiser's offering. + IMPORTED_LEAD (12): + A lead conversion imported from an external + source into Google Ads. + SUBMIT_LEAD_FORM (13): + A submission of a form on an advertiser site + indicating business interest. + BOOK_APPOINTMENT (14): + A booking of an appointment with an + advertiser's business. + REQUEST_QUOTE (15): + A quote or price estimate request. + GET_DIRECTIONS (16): + A search for an advertiser's business + location with intention to visit. + OUTBOUND_CLICK (17): + A click to an advertiser's partner's site. + CONTACT (18): + A call, SMS, email, chat or other type of + contact to an advertiser. + ENGAGEMENT (19): + A website engagement event such as long site + time or a Google Analytics (GA) Smart Goal. + Intended to be used for GA, Firebase, GA Gold + goal imports. + STORE_VISIT (20): + A visit to a physical store location. + STORE_SALE (21): + A sale occurring in a physical store. + QUALIFIED_LEAD (22): + A lead conversion imported from an external + source into Google Ads, that has been further + qualified by the advertiser (marketing/sales + team). In the lead-to-sale journey, advertisers + get leads, then act on them by reaching out to + the consumer. If the consumer is interested and + may end up buying their product, the advertiser + marks such leads as "qualified leads". + CONVERTED_LEAD (23): + A lead conversion imported from an external + source into Google Ads, that has further + completed a chosen stage as defined by the lead + gen advertiser. + YOUTUBE_FOLLOW_ON_VIEWS (24): + User watches an ad from a channel and later + watches either the same video or a video from + the same channel as the ad. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DEFAULT = 2 + PAGE_VIEW = 3 + PURCHASE = 4 + SIGNUP = 5 + DOWNLOAD = 7 + ADD_TO_CART = 8 + BEGIN_CHECKOUT = 9 + SUBSCRIBE_PAID = 10 + PHONE_CALL_LEAD = 11 + IMPORTED_LEAD = 12 + SUBMIT_LEAD_FORM = 13 + BOOK_APPOINTMENT = 14 + REQUEST_QUOTE = 15 + GET_DIRECTIONS = 16 + OUTBOUND_CLICK = 17 + CONTACT = 18 + ENGAGEMENT = 19 + STORE_VISIT = 20 + STORE_SALE = 21 + QUALIFIED_LEAD = 22 + CONVERTED_LEAD = 23 + YOUTUBE_FOLLOW_ON_VIEWS = 24 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_action_counting_type.py b/google/ads/googleads/v24/enums/types/conversion_action_counting_type.py new file mode 100644 index 000000000..f458140ac --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_action_counting_type.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionActionCountingTypeEnum", + }, +) + + +class ConversionActionCountingTypeEnum(proto.Message): + r"""Container for enum describing the conversion deduplication + mode for conversion optimizer. + + """ + + class ConversionActionCountingType(proto.Enum): + r"""Indicates how conversions for this action will be counted. + For more information, see + https://support.google.com/google-ads/answer/3438531. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ONE_PER_CLICK (2): + Count only one conversion per click. + MANY_PER_CLICK (3): + Count all conversions per click. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ONE_PER_CLICK = 2 + MANY_PER_CLICK = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_action_status.py b/google/ads/googleads/v24/enums/types/conversion_action_status.py new file mode 100644 index 000000000..d32f8d3bc --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_action_status.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionActionStatusEnum", + }, +) + + +class ConversionActionStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a + conversion action. + + """ + + class ConversionActionStatus(proto.Enum): + r"""Possible statuses of a conversion action. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + Conversions will be recorded. + REMOVED (3): + Conversions will not be recorded. + HIDDEN (4): + Conversions will not be recorded and the + conversion action will not appear in the UI. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + HIDDEN = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_action_type.py b/google/ads/googleads/v24/enums/types/conversion_action_type.py new file mode 100644 index 000000000..bde9b9d86 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_action_type.py @@ -0,0 +1,269 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionActionTypeEnum", + }, +) + + +class ConversionActionTypeEnum(proto.Message): + r"""Container for enum describing possible types of a conversion + action. + + """ + + class ConversionActionType(proto.Enum): + r"""Possible types of a conversion action. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + AD_CALL (2): + Conversions that occur when a user clicks on + an ad's call extension. + CLICK_TO_CALL (3): + Conversions that occur when a user on a + mobile device clicks a phone number. + GOOGLE_PLAY_DOWNLOAD (4): + Conversions that occur when a user downloads + a mobile app from the Google Play Store. + GOOGLE_PLAY_IN_APP_PURCHASE (5): + Conversions that occur when a user makes a + purchase in an app through Android billing. + UPLOAD_CALLS (6): + Call conversions that are tracked by the + advertiser and uploaded. + UPLOAD_CLICKS (7): + Conversions that are tracked by the + advertiser and uploaded with attributed clicks. + WEBPAGE (8): + Conversions that occur on a webpage. + WEBSITE_CALL (9): + Conversions that occur when a user calls a + dynamically-generated phone number from an + advertiser's website. + STORE_SALES_DIRECT_UPLOAD (10): + Store Sales conversion based on first-party + or third-party merchant data uploads. + Only customers on the allowlist can use store + sales direct upload types. + STORE_SALES (11): + Store Sales conversion based on first-party + or third-party merchant data uploads and/or from + in-store purchases using cards from payment + networks. + Only customers on the allowlist can use store + sales types. Read only. + FIREBASE_ANDROID_FIRST_OPEN (12): + Android app first open conversions tracked + through Firebase. + FIREBASE_ANDROID_IN_APP_PURCHASE (13): + Android app in app purchase conversions + tracked through Firebase. + FIREBASE_ANDROID_CUSTOM (14): + Android app custom conversions tracked + through Firebase. + FIREBASE_IOS_FIRST_OPEN (15): + iOS app first open conversions tracked + through Firebase. + FIREBASE_IOS_IN_APP_PURCHASE (16): + iOS app in app purchase conversions tracked + through Firebase. + FIREBASE_IOS_CUSTOM (17): + iOS app custom conversions tracked through + Firebase. + THIRD_PARTY_APP_ANALYTICS_ANDROID_FIRST_OPEN (18): + Android app first open conversions tracked + through Third Party App Analytics. + THIRD_PARTY_APP_ANALYTICS_ANDROID_IN_APP_PURCHASE (19): + Android app in app purchase conversions + tracked through Third Party App Analytics. + THIRD_PARTY_APP_ANALYTICS_ANDROID_CUSTOM (20): + Android app custom conversions tracked + through Third Party App Analytics. + THIRD_PARTY_APP_ANALYTICS_IOS_FIRST_OPEN (21): + iOS app first open conversions tracked + through Third Party App Analytics. + THIRD_PARTY_APP_ANALYTICS_IOS_IN_APP_PURCHASE (22): + iOS app in app purchase conversions tracked + through Third Party App Analytics. + THIRD_PARTY_APP_ANALYTICS_IOS_CUSTOM (23): + iOS app custom conversions tracked through + Third Party App Analytics. + ANDROID_APP_PRE_REGISTRATION (24): + Conversions that occur when a user + pre-registers a mobile app from the Google Play + Store. Read only. + ANDROID_INSTALLS_ALL_OTHER_APPS (25): + Conversions that track all Google Play + downloads which aren't tracked by an + app-specific type. Read only. + FLOODLIGHT_ACTION (26): + Floodlight activity that counts the number of + times that users have visited a particular + webpage after seeing or clicking on one of an + advertiser's ads. Read only. + FLOODLIGHT_TRANSACTION (27): + Floodlight activity that tracks the number of + sales made or the number of items purchased. Can + also capture the total value of each sale. Read + only. + GOOGLE_HOSTED (28): + Conversions that track local actions from + Google's products and services after interacting + with an ad. Read only. + LEAD_FORM_SUBMIT (29): + Conversions reported when a user submits a + lead form. Read only. + SALESFORCE (30): + Deprecated: The Salesforce integration will + be going away and replaced with an improved way + to import your conversions from Salesforce. + - see + https://support.google.com/google-ads/answer/14728349 + SEARCH_ADS_360 (31): + Conversions imported from Search Ads 360 + Floodlight data. Read only. + SMART_CAMPAIGN_AD_CLICKS_TO_CALL (32): + Call conversions that occur on Smart campaign + Ads without call tracking setup, using Smart + campaign custom criteria. Read only. + SMART_CAMPAIGN_MAP_CLICKS_TO_CALL (33): + The user clicks on a call element within + Google Maps. Smart campaign only. Read only. + SMART_CAMPAIGN_MAP_DIRECTIONS (34): + The user requests directions to a business + location within Google Maps. Smart campaign + only. Read only. + SMART_CAMPAIGN_TRACKED_CALLS (35): + Call conversions that occur on Smart campaign + Ads with call tracking setup, using Smart + campaign custom criteria. Read only. + STORE_VISITS (36): + Conversions that occur when a user visits an + advertiser's retail store. Read only. + WEBPAGE_CODELESS (37): + Conversions created from website events (such + as form submissions or page loads), that don't + use individually coded event snippets. Read + only. + UNIVERSAL_ANALYTICS_GOAL (38): + Conversions that come from linked Universal + Analytics goals. + UNIVERSAL_ANALYTICS_TRANSACTION (39): + Conversions that come from linked Universal + Analytics transactions. + GOOGLE_ANALYTICS_4_CUSTOM (40): + Conversions that come from linked Google + Analytics 4 custom event conversions. + GOOGLE_ANALYTICS_4_PURCHASE (41): + Conversions that come from linked Google + Analytics 4 purchase conversions. + GOOGLE_ANALYTICS_4_GENERATE_LEAD (42): + Conversions that come from linked Google + Analytics 4 generate lead conversions. + GOOGLE_ANALYTICS_4_QUALIFY_LEAD (43): + Conversions that come from linked Google + Analytics 4 qualify lead conversions. + GOOGLE_ANALYTICS_4_CLOSE_CONVERT_LEAD (44): + Conversions that come from linked Google + Analytics 4 close convert lead conversions. + FIREBASE_ANDROID_GENERATE_LEAD (45): + Conversions that come from linked Firebase + Android generate lead conversions. + FIREBASE_ANDROID_QUALIFY_LEAD (46): + Conversions that come from linked Firebase + Android qualify lead conversions. + FIREBASE_ANDROID_CLOSE_CONVERT_LEAD (47): + Conversions that come from linked Firebase + Android close convert lead conversions. + FIREBASE_IOS_GENERATE_LEAD (48): + Conversions that come from linked Firebase + iOS generate lead conversions. + FIREBASE_IOS_QUALIFY_LEAD (49): + Conversions that come from linked Firebase + iOS qualify lead conversions. + FIREBASE_IOS_CLOSE_CONVERT_LEAD (50): + Conversions that come from linked Firebase + iOS close convert lead conversions. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AD_CALL = 2 + CLICK_TO_CALL = 3 + GOOGLE_PLAY_DOWNLOAD = 4 + GOOGLE_PLAY_IN_APP_PURCHASE = 5 + UPLOAD_CALLS = 6 + UPLOAD_CLICKS = 7 + WEBPAGE = 8 + WEBSITE_CALL = 9 + STORE_SALES_DIRECT_UPLOAD = 10 + STORE_SALES = 11 + FIREBASE_ANDROID_FIRST_OPEN = 12 + FIREBASE_ANDROID_IN_APP_PURCHASE = 13 + FIREBASE_ANDROID_CUSTOM = 14 + FIREBASE_IOS_FIRST_OPEN = 15 + FIREBASE_IOS_IN_APP_PURCHASE = 16 + FIREBASE_IOS_CUSTOM = 17 + THIRD_PARTY_APP_ANALYTICS_ANDROID_FIRST_OPEN = 18 + THIRD_PARTY_APP_ANALYTICS_ANDROID_IN_APP_PURCHASE = 19 + THIRD_PARTY_APP_ANALYTICS_ANDROID_CUSTOM = 20 + THIRD_PARTY_APP_ANALYTICS_IOS_FIRST_OPEN = 21 + THIRD_PARTY_APP_ANALYTICS_IOS_IN_APP_PURCHASE = 22 + THIRD_PARTY_APP_ANALYTICS_IOS_CUSTOM = 23 + ANDROID_APP_PRE_REGISTRATION = 24 + ANDROID_INSTALLS_ALL_OTHER_APPS = 25 + FLOODLIGHT_ACTION = 26 + FLOODLIGHT_TRANSACTION = 27 + GOOGLE_HOSTED = 28 + LEAD_FORM_SUBMIT = 29 + SALESFORCE = 30 + SEARCH_ADS_360 = 31 + SMART_CAMPAIGN_AD_CLICKS_TO_CALL = 32 + SMART_CAMPAIGN_MAP_CLICKS_TO_CALL = 33 + SMART_CAMPAIGN_MAP_DIRECTIONS = 34 + SMART_CAMPAIGN_TRACKED_CALLS = 35 + STORE_VISITS = 36 + WEBPAGE_CODELESS = 37 + UNIVERSAL_ANALYTICS_GOAL = 38 + UNIVERSAL_ANALYTICS_TRANSACTION = 39 + GOOGLE_ANALYTICS_4_CUSTOM = 40 + GOOGLE_ANALYTICS_4_PURCHASE = 41 + GOOGLE_ANALYTICS_4_GENERATE_LEAD = 42 + GOOGLE_ANALYTICS_4_QUALIFY_LEAD = 43 + GOOGLE_ANALYTICS_4_CLOSE_CONVERT_LEAD = 44 + FIREBASE_ANDROID_GENERATE_LEAD = 45 + FIREBASE_ANDROID_QUALIFY_LEAD = 46 + FIREBASE_ANDROID_CLOSE_CONVERT_LEAD = 47 + FIREBASE_IOS_GENERATE_LEAD = 48 + FIREBASE_IOS_QUALIFY_LEAD = 49 + FIREBASE_IOS_CLOSE_CONVERT_LEAD = 50 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_adjustment_type.py b/google/ads/googleads/v24/enums/types/conversion_adjustment_type.py new file mode 100644 index 000000000..07dca32ed --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_adjustment_type.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionAdjustmentTypeEnum", + }, +) + + +class ConversionAdjustmentTypeEnum(proto.Message): + r"""Container for enum describing conversion adjustment types.""" + + class ConversionAdjustmentType(proto.Enum): + r"""The different actions advertisers can take to adjust the + conversions that they already reported. Retractions negate a + conversion. Restatements change the value of a conversion. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Represents value unknown in this version. + RETRACTION (2): + Negates a conversion so that its total value + and count are both zero. + RESTATEMENT (3): + Changes the value of a conversion. + ENHANCEMENT (4): + Supplements an existing conversion with + provided user identifiers and user agent, which + can be used by Google to enhance the conversion + count. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + RETRACTION = 2 + RESTATEMENT = 3 + ENHANCEMENT = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_attribution_event_type.py b/google/ads/googleads/v24/enums/types/conversion_attribution_event_type.py new file mode 100644 index 000000000..ecd077e25 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_attribution_event_type.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionAttributionEventTypeEnum", + }, +) + + +class ConversionAttributionEventTypeEnum(proto.Message): + r"""Container for enum indicating the event type the conversion + is attributed to. + + """ + + class ConversionAttributionEventType(proto.Enum): + r"""The event type of conversions that are attributed to. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Represents value unknown in this version. + IMPRESSION (2): + The conversion is attributed to an + impression. + INTERACTION (3): + The conversion is attributed to an + interaction. + ENGAGED_VIEW (4): + The conversion is attributed to a 10s engaged + view. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + IMPRESSION = 2 + INTERACTION = 3 + ENGAGED_VIEW = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_custom_variable_status.py b/google/ads/googleads/v24/enums/types/conversion_custom_variable_status.py new file mode 100644 index 000000000..fc14b7ee9 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_custom_variable_status.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionCustomVariableStatusEnum", + }, +) + + +class ConversionCustomVariableStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a + conversion custom variable. + + """ + + class ConversionCustomVariableStatus(proto.Enum): + r"""Possible statuses of a conversion custom variable. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ACTIVATION_NEEDED (2): + The conversion custom variable is pending + activation and will not accrue stats until set + to ENABLED. + + This status can't be used in CREATE and UPDATE + requests. + ENABLED (3): + The conversion custom variable is enabled and + will accrue stats. + PAUSED (4): + The conversion custom variable is paused and + will not accrue stats until set to ENABLED + again. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ACTIVATION_NEEDED = 2 + ENABLED = 3 + PAUSED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_customer_type.py b/google/ads/googleads/v24/enums/types/conversion_customer_type.py new file mode 100644 index 000000000..7778aafc7 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_customer_type.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionCustomerTypeEnum", + }, +) + + +class ConversionCustomerTypeEnum(proto.Message): + r"""Container for enumeration of conversion customer types.""" + + class ConversionCustomerType(proto.Enum): + r"""Enumerates conversion customer types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + NEW (2): + Converting user is new to the advertiser. + RETURNING (3): + Converting user is returning to the + advertiser. Definition of returning differs + among conversion types, such as a second store + visit versus a second online purchase. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NEW = 2 + RETURNING = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_environment_enum.py b/google/ads/googleads/v24/enums/types/conversion_environment_enum.py new file mode 100644 index 000000000..95f9938a3 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_environment_enum.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionEnvironmentEnum", + }, +) + + +class ConversionEnvironmentEnum(proto.Message): + r"""Container for enum representing the conversion environment an + uploaded conversion was recorded on, for example, App or Web. + + """ + + class ConversionEnvironment(proto.Enum): + r"""Conversion environment of the uploaded conversion. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + APP (2): + The conversion was recorded on an app. + WEB (3): + The conversion was recorded on a website. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + APP = 2 + WEB = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_lag_bucket.py b/google/ads/googleads/v24/enums/types/conversion_lag_bucket.py new file mode 100644 index 000000000..d3a2cfac0 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_lag_bucket.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionLagBucketEnum", + }, +) + + +class ConversionLagBucketEnum(proto.Message): + r"""Container for enum representing the number of days between + impression and conversion. + + """ + + class ConversionLagBucket(proto.Enum): + r"""Enum representing the number of days between impression and + conversion. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + LESS_THAN_ONE_DAY (2): + Conversion lag bucket from 0 to 1 day. 0 day + is included, 1 day is not. + ONE_TO_TWO_DAYS (3): + Conversion lag bucket from 1 to 2 days. 1 day + is included, 2 days is not. + TWO_TO_THREE_DAYS (4): + Conversion lag bucket from 2 to 3 days. 2 + days is included, 3 days is not. + THREE_TO_FOUR_DAYS (5): + Conversion lag bucket from 3 to 4 days. 3 + days is included, 4 days is not. + FOUR_TO_FIVE_DAYS (6): + Conversion lag bucket from 4 to 5 days. 4 + days is included, 5 days is not. + FIVE_TO_SIX_DAYS (7): + Conversion lag bucket from 5 to 6 days. 5 + days is included, 6 days is not. + SIX_TO_SEVEN_DAYS (8): + Conversion lag bucket from 6 to 7 days. 6 + days is included, 7 days is not. + SEVEN_TO_EIGHT_DAYS (9): + Conversion lag bucket from 7 to 8 days. 7 + days is included, 8 days is not. + EIGHT_TO_NINE_DAYS (10): + Conversion lag bucket from 8 to 9 days. 8 + days is included, 9 days is not. + NINE_TO_TEN_DAYS (11): + Conversion lag bucket from 9 to 10 days. 9 + days is included, 10 days is not. + TEN_TO_ELEVEN_DAYS (12): + Conversion lag bucket from 10 to 11 days. 10 + days is included, 11 days is not. + ELEVEN_TO_TWELVE_DAYS (13): + Conversion lag bucket from 11 to 12 days. 11 + days is included, 12 days is not. + TWELVE_TO_THIRTEEN_DAYS (14): + Conversion lag bucket from 12 to 13 days. 12 + days is included, 13 days is not. + THIRTEEN_TO_FOURTEEN_DAYS (15): + Conversion lag bucket from 13 to 14 days. 13 + days is included, 14 days is not. + FOURTEEN_TO_TWENTY_ONE_DAYS (16): + Conversion lag bucket from 14 to 21 days. 14 + days is included, 21 days is not. + TWENTY_ONE_TO_THIRTY_DAYS (17): + Conversion lag bucket from 21 to 30 days. 21 + days is included, 30 days is not. + THIRTY_TO_FORTY_FIVE_DAYS (18): + Conversion lag bucket from 30 to 45 days. 30 + days is included, 45 days is not. + FORTY_FIVE_TO_SIXTY_DAYS (19): + Conversion lag bucket from 45 to 60 days. 45 + days is included, 60 days is not. + SIXTY_TO_NINETY_DAYS (20): + Conversion lag bucket from 60 to 90 days. 60 + days is included, 90 days is not. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LESS_THAN_ONE_DAY = 2 + ONE_TO_TWO_DAYS = 3 + TWO_TO_THREE_DAYS = 4 + THREE_TO_FOUR_DAYS = 5 + FOUR_TO_FIVE_DAYS = 6 + FIVE_TO_SIX_DAYS = 7 + SIX_TO_SEVEN_DAYS = 8 + SEVEN_TO_EIGHT_DAYS = 9 + EIGHT_TO_NINE_DAYS = 10 + NINE_TO_TEN_DAYS = 11 + TEN_TO_ELEVEN_DAYS = 12 + ELEVEN_TO_TWELVE_DAYS = 13 + TWELVE_TO_THIRTEEN_DAYS = 14 + THIRTEEN_TO_FOURTEEN_DAYS = 15 + FOURTEEN_TO_TWENTY_ONE_DAYS = 16 + TWENTY_ONE_TO_THIRTY_DAYS = 17 + THIRTY_TO_FORTY_FIVE_DAYS = 18 + FORTY_FIVE_TO_SIXTY_DAYS = 19 + SIXTY_TO_NINETY_DAYS = 20 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_or_adjustment_lag_bucket.py b/google/ads/googleads/v24/enums/types/conversion_or_adjustment_lag_bucket.py new file mode 100644 index 000000000..bd6a4851e --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_or_adjustment_lag_bucket.py @@ -0,0 +1,221 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionOrAdjustmentLagBucketEnum", + }, +) + + +class ConversionOrAdjustmentLagBucketEnum(proto.Message): + r"""Container for enum representing the number of days between + the impression and the conversion or between the impression and + adjustments to the conversion. + + """ + + class ConversionOrAdjustmentLagBucket(proto.Enum): + r"""Enum representing the number of days between the impression + and the conversion or between the impression and adjustments to + the conversion. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CONVERSION_LESS_THAN_ONE_DAY (2): + Conversion lag bucket from 0 to 1 day. 0 day + is included, 1 day is not. + CONVERSION_ONE_TO_TWO_DAYS (3): + Conversion lag bucket from 1 to 2 days. 1 day + is included, 2 days is not. + CONVERSION_TWO_TO_THREE_DAYS (4): + Conversion lag bucket from 2 to 3 days. 2 + days is included, 3 days is not. + CONVERSION_THREE_TO_FOUR_DAYS (5): + Conversion lag bucket from 3 to 4 days. 3 + days is included, 4 days is not. + CONVERSION_FOUR_TO_FIVE_DAYS (6): + Conversion lag bucket from 4 to 5 days. 4 + days is included, 5 days is not. + CONVERSION_FIVE_TO_SIX_DAYS (7): + Conversion lag bucket from 5 to 6 days. 5 + days is included, 6 days is not. + CONVERSION_SIX_TO_SEVEN_DAYS (8): + Conversion lag bucket from 6 to 7 days. 6 + days is included, 7 days is not. + CONVERSION_SEVEN_TO_EIGHT_DAYS (9): + Conversion lag bucket from 7 to 8 days. 7 + days is included, 8 days is not. + CONVERSION_EIGHT_TO_NINE_DAYS (10): + Conversion lag bucket from 8 to 9 days. 8 + days is included, 9 days is not. + CONVERSION_NINE_TO_TEN_DAYS (11): + Conversion lag bucket from 9 to 10 days. 9 + days is included, 10 days is not. + CONVERSION_TEN_TO_ELEVEN_DAYS (12): + Conversion lag bucket from 10 to 11 days. 10 + days is included, 11 days is not. + CONVERSION_ELEVEN_TO_TWELVE_DAYS (13): + Conversion lag bucket from 11 to 12 days. 11 + days is included, 12 days is not. + CONVERSION_TWELVE_TO_THIRTEEN_DAYS (14): + Conversion lag bucket from 12 to 13 days. 12 + days is included, 13 days is not. + CONVERSION_THIRTEEN_TO_FOURTEEN_DAYS (15): + Conversion lag bucket from 13 to 14 days. 13 + days is included, 14 days is not. + CONVERSION_FOURTEEN_TO_TWENTY_ONE_DAYS (16): + Conversion lag bucket from 14 to 21 days. 14 + days is included, 21 days is not. + CONVERSION_TWENTY_ONE_TO_THIRTY_DAYS (17): + Conversion lag bucket from 21 to 30 days. 21 + days is included, 30 days is not. + CONVERSION_THIRTY_TO_FORTY_FIVE_DAYS (18): + Conversion lag bucket from 30 to 45 days. 30 + days is included, 45 days is not. + CONVERSION_FORTY_FIVE_TO_SIXTY_DAYS (19): + Conversion lag bucket from 45 to 60 days. 45 + days is included, 60 days is not. + CONVERSION_SIXTY_TO_NINETY_DAYS (20): + Conversion lag bucket from 60 to 90 days. 60 + days is included, 90 days is not. + ADJUSTMENT_LESS_THAN_ONE_DAY (21): + Conversion adjustment lag bucket from 0 to 1 + day. 0 day is included, 1 day is not. + ADJUSTMENT_ONE_TO_TWO_DAYS (22): + Conversion adjustment lag bucket from 1 to 2 + days. 1 day is included, 2 days is not. + ADJUSTMENT_TWO_TO_THREE_DAYS (23): + Conversion adjustment lag bucket from 2 to 3 + days. 2 days is included, 3 days is not. + ADJUSTMENT_THREE_TO_FOUR_DAYS (24): + Conversion adjustment lag bucket from 3 to 4 + days. 3 days is included, 4 days is not. + ADJUSTMENT_FOUR_TO_FIVE_DAYS (25): + Conversion adjustment lag bucket from 4 to 5 + days. 4 days is included, 5 days is not. + ADJUSTMENT_FIVE_TO_SIX_DAYS (26): + Conversion adjustment lag bucket from 5 to 6 + days. 5 days is included, 6 days is not. + ADJUSTMENT_SIX_TO_SEVEN_DAYS (27): + Conversion adjustment lag bucket from 6 to 7 + days. 6 days is included, 7 days is not. + ADJUSTMENT_SEVEN_TO_EIGHT_DAYS (28): + Conversion adjustment lag bucket from 7 to 8 + days. 7 days is included, 8 days is not. + ADJUSTMENT_EIGHT_TO_NINE_DAYS (29): + Conversion adjustment lag bucket from 8 to 9 + days. 8 days is included, 9 days is not. + ADJUSTMENT_NINE_TO_TEN_DAYS (30): + Conversion adjustment lag bucket from 9 to 10 + days. 9 days is included, 10 days is not. + ADJUSTMENT_TEN_TO_ELEVEN_DAYS (31): + Conversion adjustment lag bucket from 10 to + 11 days. 10 days is included, 11 days is not. + ADJUSTMENT_ELEVEN_TO_TWELVE_DAYS (32): + Conversion adjustment lag bucket from 11 to + 12 days. 11 days is included, 12 days is not. + ADJUSTMENT_TWELVE_TO_THIRTEEN_DAYS (33): + Conversion adjustment lag bucket from 12 to + 13 days. 12 days is included, 13 days is not. + ADJUSTMENT_THIRTEEN_TO_FOURTEEN_DAYS (34): + Conversion adjustment lag bucket from 13 to + 14 days. 13 days is included, 14 days is not. + ADJUSTMENT_FOURTEEN_TO_TWENTY_ONE_DAYS (35): + Conversion adjustment lag bucket from 14 to + 21 days. 14 days is included, 21 days is not. + ADJUSTMENT_TWENTY_ONE_TO_THIRTY_DAYS (36): + Conversion adjustment lag bucket from 21 to + 30 days. 21 days is included, 30 days is not. + ADJUSTMENT_THIRTY_TO_FORTY_FIVE_DAYS (37): + Conversion adjustment lag bucket from 30 to + 45 days. 30 days is included, 45 days is not. + ADJUSTMENT_FORTY_FIVE_TO_SIXTY_DAYS (38): + Conversion adjustment lag bucket from 45 to + 60 days. 45 days is included, 60 days is not. + ADJUSTMENT_SIXTY_TO_NINETY_DAYS (39): + Conversion adjustment lag bucket from 60 to + 90 days. 60 days is included, 90 days is not. + ADJUSTMENT_NINETY_TO_ONE_HUNDRED_AND_FORTY_FIVE_DAYS (40): + Conversion adjustment lag bucket from 90 to + 145 days. 90 days is included, 145 days is not. + CONVERSION_UNKNOWN (41): + Conversion lag bucket UNKNOWN. This is for + dates before conversion lag bucket was available + in Google Ads. + ADJUSTMENT_UNKNOWN (42): + Conversion adjustment lag bucket UNKNOWN. + This is for dates before conversion adjustment + lag bucket was available in Google Ads. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CONVERSION_LESS_THAN_ONE_DAY = 2 + CONVERSION_ONE_TO_TWO_DAYS = 3 + CONVERSION_TWO_TO_THREE_DAYS = 4 + CONVERSION_THREE_TO_FOUR_DAYS = 5 + CONVERSION_FOUR_TO_FIVE_DAYS = 6 + CONVERSION_FIVE_TO_SIX_DAYS = 7 + CONVERSION_SIX_TO_SEVEN_DAYS = 8 + CONVERSION_SEVEN_TO_EIGHT_DAYS = 9 + CONVERSION_EIGHT_TO_NINE_DAYS = 10 + CONVERSION_NINE_TO_TEN_DAYS = 11 + CONVERSION_TEN_TO_ELEVEN_DAYS = 12 + CONVERSION_ELEVEN_TO_TWELVE_DAYS = 13 + CONVERSION_TWELVE_TO_THIRTEEN_DAYS = 14 + CONVERSION_THIRTEEN_TO_FOURTEEN_DAYS = 15 + CONVERSION_FOURTEEN_TO_TWENTY_ONE_DAYS = 16 + CONVERSION_TWENTY_ONE_TO_THIRTY_DAYS = 17 + CONVERSION_THIRTY_TO_FORTY_FIVE_DAYS = 18 + CONVERSION_FORTY_FIVE_TO_SIXTY_DAYS = 19 + CONVERSION_SIXTY_TO_NINETY_DAYS = 20 + ADJUSTMENT_LESS_THAN_ONE_DAY = 21 + ADJUSTMENT_ONE_TO_TWO_DAYS = 22 + ADJUSTMENT_TWO_TO_THREE_DAYS = 23 + ADJUSTMENT_THREE_TO_FOUR_DAYS = 24 + ADJUSTMENT_FOUR_TO_FIVE_DAYS = 25 + ADJUSTMENT_FIVE_TO_SIX_DAYS = 26 + ADJUSTMENT_SIX_TO_SEVEN_DAYS = 27 + ADJUSTMENT_SEVEN_TO_EIGHT_DAYS = 28 + ADJUSTMENT_EIGHT_TO_NINE_DAYS = 29 + ADJUSTMENT_NINE_TO_TEN_DAYS = 30 + ADJUSTMENT_TEN_TO_ELEVEN_DAYS = 31 + ADJUSTMENT_ELEVEN_TO_TWELVE_DAYS = 32 + ADJUSTMENT_TWELVE_TO_THIRTEEN_DAYS = 33 + ADJUSTMENT_THIRTEEN_TO_FOURTEEN_DAYS = 34 + ADJUSTMENT_FOURTEEN_TO_TWENTY_ONE_DAYS = 35 + ADJUSTMENT_TWENTY_ONE_TO_THIRTY_DAYS = 36 + ADJUSTMENT_THIRTY_TO_FORTY_FIVE_DAYS = 37 + ADJUSTMENT_FORTY_FIVE_TO_SIXTY_DAYS = 38 + ADJUSTMENT_SIXTY_TO_NINETY_DAYS = 39 + ADJUSTMENT_NINETY_TO_ONE_HUNDRED_AND_FORTY_FIVE_DAYS = 40 + CONVERSION_UNKNOWN = 41 + ADJUSTMENT_UNKNOWN = 42 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_origin.py b/google/ads/googleads/v24/enums/types/conversion_origin.py new file mode 100644 index 000000000..0d43162b3 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_origin.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionOriginEnum", + }, +) + + +class ConversionOriginEnum(proto.Message): + r"""Container for enum describing possible conversion origins.""" + + class ConversionOrigin(proto.Enum): + r"""The possible places where a conversion can occur. + + Values: + UNSPECIFIED (0): + The conversion origin has not been specified. + UNKNOWN (1): + The conversion origin is not known in this + version. + WEBSITE (2): + Conversion that occurs when a user visits a + website or takes an action there after viewing + an ad. + GOOGLE_HOSTED (3): + Conversions reported by an offline pipeline + which collects local actions from Google-hosted + pages (for example, Google Maps, Google Place + Page, etc) and attributes them to relevant ad + events. + APP (4): + Conversion that occurs when a user performs + an action through any app platforms. + CALL_FROM_ADS (5): + Conversion that occurs when a user makes a + call from ads. + STORE (6): + Conversion that occurs when a user visits or + makes a purchase at a physical store. + YOUTUBE_HOSTED (7): + Conversion that occurs on YouTube. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + WEBSITE = 2 + GOOGLE_HOSTED = 3 + APP = 4 + CALL_FROM_ADS = 5 + STORE = 6 + YOUTUBE_HOSTED = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_tracking_status_enum.py b/google/ads/googleads/v24/enums/types/conversion_tracking_status_enum.py new file mode 100644 index 000000000..0d2651156 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_tracking_status_enum.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionTrackingStatusEnum", + }, +) + + +class ConversionTrackingStatusEnum(proto.Message): + r"""Container for enum representing the conversion tracking + status of the customer. + + """ + + class ConversionTrackingStatus(proto.Enum): + r"""Conversion Tracking status of the customer. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + NOT_CONVERSION_TRACKED (2): + Customer does not use any conversion + tracking. + CONVERSION_TRACKING_MANAGED_BY_SELF (3): + The conversion actions are created and + managed by this customer. + CONVERSION_TRACKING_MANAGED_BY_THIS_MANAGER (4): + The conversion actions are created and managed by the + manager specified in the request's ``login-customer-id``. + CONVERSION_TRACKING_MANAGED_BY_ANOTHER_MANAGER (5): + The conversion actions are created and managed by a manager + different from the customer or manager specified in the + request's ``login-customer-id``. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NOT_CONVERSION_TRACKED = 2 + CONVERSION_TRACKING_MANAGED_BY_SELF = 3 + CONVERSION_TRACKING_MANAGED_BY_THIS_MANAGER = 4 + CONVERSION_TRACKING_MANAGED_BY_ANOTHER_MANAGER = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_value_rule_primary_dimension.py b/google/ads/googleads/v24/enums/types/conversion_value_rule_primary_dimension.py new file mode 100644 index 000000000..db664edbe --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_value_rule_primary_dimension.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionValueRulePrimaryDimensionEnum", + }, +) + + +class ConversionValueRulePrimaryDimensionEnum(proto.Message): + r"""Container for enum describing value rule primary dimension + for stats. + + """ + + class ConversionValueRulePrimaryDimension(proto.Enum): + r"""Identifies the primary dimension for conversion value rule + stats. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + NO_RULE_APPLIED (2): + For no-value-rule-applied conversions after + value rule is enabled. + ORIGINAL (3): + Below are for value-rule-applied conversions: + The original stats. + NEW_VS_RETURNING_USER (4): + When a new or returning customer condition is + satisfied. + GEO_LOCATION (5): + When a query-time Geo location condition is + satisfied. + DEVICE (6): + When a query-time browsing device condition + is satisfied. + AUDIENCE (7): + When a query-time audience condition is + satisfied. + MULTIPLE (8): + When multiple rules are applied. + ITINERARY (9): + When a query-time itinerary condition is + satisfied. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NO_RULE_APPLIED = 2 + ORIGINAL = 3 + NEW_VS_RETURNING_USER = 4 + GEO_LOCATION = 5 + DEVICE = 6 + AUDIENCE = 7 + MULTIPLE = 8 + ITINERARY = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_value_rule_set_status.py b/google/ads/googleads/v24/enums/types/conversion_value_rule_set_status.py new file mode 100644 index 000000000..bed38c333 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_value_rule_set_status.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionValueRuleSetStatusEnum", + }, +) + + +class ConversionValueRuleSetStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a + conversion value rule set. + + """ + + class ConversionValueRuleSetStatus(proto.Enum): + r"""Possible statuses of a conversion value rule set. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + Conversion Value Rule Set is enabled and can + be applied. + REMOVED (3): + Conversion Value Rule Set is permanently + deleted and can't be applied. + PAUSED (4): + Conversion Value Rule Set is paused and won't + be applied. It can be enabled again. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + PAUSED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/conversion_value_rule_status.py b/google/ads/googleads/v24/enums/types/conversion_value_rule_status.py new file mode 100644 index 000000000..b3e3539c4 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/conversion_value_rule_status.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionValueRuleStatusEnum", + }, +) + + +class ConversionValueRuleStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a + conversion value rule. + + """ + + class ConversionValueRuleStatus(proto.Enum): + r"""Possible statuses of a conversion value rule. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + Conversion Value Rule is enabled and can be + applied. + REMOVED (3): + Conversion Value Rule is permanently deleted + and can't be applied. + PAUSED (4): + Conversion Value Rule is paused, but can be + re-enabled. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + PAUSED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/converting_user_prior_engagement_type_and_ltv_bucket.py b/google/ads/googleads/v24/enums/types/converting_user_prior_engagement_type_and_ltv_bucket.py new file mode 100644 index 000000000..5070099eb --- /dev/null +++ b/google/ads/googleads/v24/enums/types/converting_user_prior_engagement_type_and_ltv_bucket.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ConvertingUserPriorEngagementTypeAndLtvBucketEnum", + }, +) + + +class ConvertingUserPriorEngagementTypeAndLtvBucketEnum(proto.Message): + r"""Container for enumeration of converting user prior engagement + types and lifetime-value bucket. + + """ + + class ConvertingUserPriorEngagementTypeAndLtvBucket(proto.Enum): + r"""Enumerates converting user prior engagement types and + lifetime-value bucket + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + NEW (2): + Converting user is new to the advertiser. + RETURNING (3): + Converting user is returning to the + advertiser. Definition of returning differs + among conversion types, such as a second store + visit versus a second online purchase. + NEW_AND_HIGH_LTV (4): + Converting user is new to the advertiser and + has high lifetime value. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NEW = 2 + RETURNING = 3 + NEW_AND_HIGH_LTV = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/criterion_category_channel_availability_mode.py b/google/ads/googleads/v24/enums/types/criterion_category_channel_availability_mode.py new file mode 100644 index 000000000..5ab764f89 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/criterion_category_channel_availability_mode.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CriterionCategoryChannelAvailabilityModeEnum", + }, +) + + +class CriterionCategoryChannelAvailabilityModeEnum(proto.Message): + r"""Describes channel availability mode for a criterion + availability - whether the availability is meant to include all + advertising channels, or a particular channel with all its + channel subtypes, or a channel with a certain subset of channel + subtypes. + + """ + + class CriterionCategoryChannelAvailabilityMode(proto.Enum): + r"""Enum containing the possible + CriterionCategoryChannelAvailabilityMode. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ALL_CHANNELS (2): + The category is available to campaigns of all + channel types and subtypes. + CHANNEL_TYPE_AND_ALL_SUBTYPES (3): + The category is available to campaigns of a + specific channel type, including all subtypes + under it. + CHANNEL_TYPE_AND_SUBSET_SUBTYPES (4): + The category is available to campaigns of a + specific channel type and subtype(s). + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ALL_CHANNELS = 2 + CHANNEL_TYPE_AND_ALL_SUBTYPES = 3 + CHANNEL_TYPE_AND_SUBSET_SUBTYPES = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/criterion_category_locale_availability_mode.py b/google/ads/googleads/v24/enums/types/criterion_category_locale_availability_mode.py new file mode 100644 index 000000000..0e4dd94e7 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/criterion_category_locale_availability_mode.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CriterionCategoryLocaleAvailabilityModeEnum", + }, +) + + +class CriterionCategoryLocaleAvailabilityModeEnum(proto.Message): + r"""Describes locale availability mode for a criterion + availability - whether it's available globally, or a particular + country with all languages, or a particular language with all + countries, or a country-language pair. + + """ + + class CriterionCategoryLocaleAvailabilityMode(proto.Enum): + r"""Enum containing the possible + CriterionCategoryLocaleAvailabilityMode. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ALL_LOCALES (2): + The category is available to campaigns of all + locales. + COUNTRY_AND_ALL_LANGUAGES (3): + The category is available to campaigns within + a list of countries, regardless of language. + LANGUAGE_AND_ALL_COUNTRIES (4): + The category is available to campaigns within + a list of languages, regardless of country. + COUNTRY_AND_LANGUAGE (5): + The category is available to campaigns within + a list of country, language pairs. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ALL_LOCALES = 2 + COUNTRY_AND_ALL_LANGUAGES = 3 + LANGUAGE_AND_ALL_COUNTRIES = 4 + COUNTRY_AND_LANGUAGE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/criterion_system_serving_status.py b/google/ads/googleads/v24/enums/types/criterion_system_serving_status.py new file mode 100644 index 000000000..cfd556981 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/criterion_system_serving_status.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CriterionSystemServingStatusEnum", + }, +) + + +class CriterionSystemServingStatusEnum(proto.Message): + r"""Container for enum describing possible criterion system + serving statuses. + + """ + + class CriterionSystemServingStatus(proto.Enum): + r"""Enumerates criterion system serving statuses. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + ELIGIBLE (2): + Eligible. + RARELY_SERVED (3): + Low search volume. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ELIGIBLE = 2 + RARELY_SERVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/criterion_type.py b/google/ads/googleads/v24/enums/types/criterion_type.py new file mode 100644 index 000000000..a7158b9cb --- /dev/null +++ b/google/ads/googleads/v24/enums/types/criterion_type.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CriterionTypeEnum", + }, +) + + +class CriterionTypeEnum(proto.Message): + r"""The possible types of a criterion.""" + + class CriterionType(proto.Enum): + r"""Enum describing possible criterion types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + KEYWORD (2): + Keyword, for example, 'mars cruise'. + PLACEMENT (3): + Placement, also known as Website, for + example, 'www.flowers4sale.com' + MOBILE_APP_CATEGORY (4): + Mobile application categories to target. + MOBILE_APPLICATION (5): + Mobile applications to target. + DEVICE (6): + Devices to target. + LOCATION (7): + Locations to target. + LISTING_GROUP (8): + Listing groups to target. + AD_SCHEDULE (9): + Ad Schedule. + AGE_RANGE (10): + Age range. + GENDER (11): + Gender. + INCOME_RANGE (12): + Income Range. + PARENTAL_STATUS (13): + Parental status. + YOUTUBE_VIDEO (14): + YouTube Video. + YOUTUBE_CHANNEL (15): + YouTube Channel. + USER_LIST (16): + User list. + PROXIMITY (17): + Proximity. + TOPIC (18): + A topic target on the display network (for + example, "Pets & Animals"). + LISTING_SCOPE (19): + Listing scope to target. + LANGUAGE (20): + Language. + IP_BLOCK (21): + IpBlock. + CONTENT_LABEL (22): + Content Label for category exclusion. + CARRIER (23): + Carrier. + USER_INTEREST (24): + A category the user is interested in. + WEBPAGE (25): + Webpage criterion for dynamic search ads. + OPERATING_SYSTEM_VERSION (26): + Operating system version. + APP_PAYMENT_MODEL (27): + App payment model. + MOBILE_DEVICE (28): + Mobile device. + CUSTOM_AFFINITY (29): + Custom affinity. + CUSTOM_INTENT (30): + Custom intent. + LOCATION_GROUP (31): + Location group. + CUSTOM_AUDIENCE (32): + Custom audience + COMBINED_AUDIENCE (33): + Combined audience + KEYWORD_THEME (34): + Smart Campaign keyword theme + AUDIENCE (35): + Audience + NEGATIVE_KEYWORD_LIST (36): + Negative Keyword List + LOCAL_SERVICE_ID (37): + Local Services Ads Service ID. + SEARCH_THEME (38): + Search Theme. + BRAND (39): + Brand + BRAND_LIST (40): + Brand List + LIFE_EVENT (41): + Life Event + WEBPAGE_LIST (42): + Webpage List + VIDEO_LINEUP (43): + Video lineup + PLACEMENT_LIST (44): + Placement List + VERTICAL_ADS_ITEM_GROUP_RULE_LIST (45): + A list of rules for item groups in Vertical + Ads. + VERTICAL_ADS_ITEM_GROUP_RULE (46): + A rule for an item group in Vertical Ads. + RETAIL_FILTER_BUNDLE (180): + Retail Filter Bundle for linking a retail + filter shared set to an ad group. + RETAIL_FILTER (181): + Retail Filter for defining individual tag + rules or expressions within a shared set. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + KEYWORD = 2 + PLACEMENT = 3 + MOBILE_APP_CATEGORY = 4 + MOBILE_APPLICATION = 5 + DEVICE = 6 + LOCATION = 7 + LISTING_GROUP = 8 + AD_SCHEDULE = 9 + AGE_RANGE = 10 + GENDER = 11 + INCOME_RANGE = 12 + PARENTAL_STATUS = 13 + YOUTUBE_VIDEO = 14 + YOUTUBE_CHANNEL = 15 + USER_LIST = 16 + PROXIMITY = 17 + TOPIC = 18 + LISTING_SCOPE = 19 + LANGUAGE = 20 + IP_BLOCK = 21 + CONTENT_LABEL = 22 + CARRIER = 23 + USER_INTEREST = 24 + WEBPAGE = 25 + OPERATING_SYSTEM_VERSION = 26 + APP_PAYMENT_MODEL = 27 + MOBILE_DEVICE = 28 + CUSTOM_AFFINITY = 29 + CUSTOM_INTENT = 30 + LOCATION_GROUP = 31 + CUSTOM_AUDIENCE = 32 + COMBINED_AUDIENCE = 33 + KEYWORD_THEME = 34 + AUDIENCE = 35 + NEGATIVE_KEYWORD_LIST = 36 + LOCAL_SERVICE_ID = 37 + SEARCH_THEME = 38 + BRAND = 39 + BRAND_LIST = 40 + LIFE_EVENT = 41 + WEBPAGE_LIST = 42 + VIDEO_LINEUP = 43 + PLACEMENT_LIST = 44 + VERTICAL_ADS_ITEM_GROUP_RULE_LIST = 45 + VERTICAL_ADS_ITEM_GROUP_RULE = 46 + RETAIL_FILTER_BUNDLE = 180 + RETAIL_FILTER = 181 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/custom_audience_member_type.py b/google/ads/googleads/v24/enums/types/custom_audience_member_type.py new file mode 100644 index 000000000..8483bf658 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/custom_audience_member_type.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomAudienceMemberTypeEnum", + }, +) + + +class CustomAudienceMemberTypeEnum(proto.Message): + r"""The type of custom audience member.""" + + class CustomAudienceMemberType(proto.Enum): + r"""Enum containing possible custom audience member types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + KEYWORD (2): + Users whose interests or actions are + described by a keyword. + URL (3): + Users who have interests related to the + website's content. + PLACE_CATEGORY (4): + Users who visit place types described by a + place category. + APP (5): + Users who have installed a mobile app. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + KEYWORD = 2 + URL = 3 + PLACE_CATEGORY = 4 + APP = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/custom_audience_status.py b/google/ads/googleads/v24/enums/types/custom_audience_status.py new file mode 100644 index 000000000..10634f3ac --- /dev/null +++ b/google/ads/googleads/v24/enums/types/custom_audience_status.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomAudienceStatusEnum", + }, +) + + +class CustomAudienceStatusEnum(proto.Message): + r"""The status of custom audience.""" + + class CustomAudienceStatus(proto.Enum): + r"""Enum containing possible custom audience statuses. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + Enabled status - custom audience is enabled + and can be targeted. + REMOVED (3): + Removed status - custom audience is removed + and cannot be used for targeting. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/custom_audience_type.py b/google/ads/googleads/v24/enums/types/custom_audience_type.py new file mode 100644 index 000000000..b7de9d413 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/custom_audience_type.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomAudienceTypeEnum", + }, +) + + +class CustomAudienceTypeEnum(proto.Message): + r"""The types of custom audience.""" + + class CustomAudienceType(proto.Enum): + r"""Enum containing possible custom audience types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + AUTO (2): + Google Ads will auto-select the best + interpretation at serving time. + INTEREST (3): + Matches users by their interests. + PURCHASE_INTENT (4): + Matches users by topics they are researching + or products they are considering for purchase. + SEARCH (5): + Matches users by what they searched on Google + Search. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AUTO = 2 + INTEREST = 3 + PURCHASE_INTENT = 4 + SEARCH = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/custom_conversion_goal_status.py b/google/ads/googleads/v24/enums/types/custom_conversion_goal_status.py new file mode 100644 index 000000000..73d715633 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/custom_conversion_goal_status.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomConversionGoalStatusEnum", + }, +) + + +class CustomConversionGoalStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a custom + conversion goal. + + """ + + class CustomConversionGoalStatus(proto.Enum): + r"""The possible statuses of a custom conversion goal. + + Values: + UNSPECIFIED (0): + The status has not been specified. + UNKNOWN (1): + The received value is not known in this + version. + ENABLED (2): + The custom conversion goal is enabled. + REMOVED (3): + The custom conversion goal is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/custom_interest_member_type.py b/google/ads/googleads/v24/enums/types/custom_interest_member_type.py new file mode 100644 index 000000000..07abd9351 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/custom_interest_member_type.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomInterestMemberTypeEnum", + }, +) + + +class CustomInterestMemberTypeEnum(proto.Message): + r"""The types of custom interest member, either KEYWORD or URL.""" + + class CustomInterestMemberType(proto.Enum): + r"""Enum containing possible custom interest member types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + KEYWORD (2): + Custom interest member type KEYWORD. + URL (3): + Custom interest member type URL. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + KEYWORD = 2 + URL = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/custom_interest_status.py b/google/ads/googleads/v24/enums/types/custom_interest_status.py new file mode 100644 index 000000000..f4dfebcb7 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/custom_interest_status.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomInterestStatusEnum", + }, +) + + +class CustomInterestStatusEnum(proto.Message): + r"""The status of custom interest.""" + + class CustomInterestStatus(proto.Enum): + r"""Enum containing possible custom interest types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + Enabled status - custom interest is enabled + and can be targeted to. + REMOVED (3): + Removed status - custom interest is removed + and cannot be used for targeting. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/custom_interest_type.py b/google/ads/googleads/v24/enums/types/custom_interest_type.py new file mode 100644 index 000000000..9fd979d60 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/custom_interest_type.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomInterestTypeEnum", + }, +) + + +class CustomInterestTypeEnum(proto.Message): + r"""The types of custom interest.""" + + class CustomInterestType(proto.Enum): + r"""Enum containing possible custom interest types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CUSTOM_AFFINITY (2): + Allows brand advertisers to define custom + affinity audience lists. + CUSTOM_INTENT (3): + Allows advertisers to define custom intent + audience lists. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOM_AFFINITY = 2 + CUSTOM_INTENT = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/customer_acquisition_optimization_mode.py b/google/ads/googleads/v24/enums/types/customer_acquisition_optimization_mode.py new file mode 100644 index 000000000..c25b212d4 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/customer_acquisition_optimization_mode.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerAcquisitionOptimizationModeEnum", + }, +) + + +class CustomerAcquisitionOptimizationModeEnum(proto.Message): + r"""Container for enum describing possible optimization mode of a + customer acquisition goal of a campaign. + + """ + + class CustomerAcquisitionOptimizationMode(proto.Enum): + r"""Possible optimization mode of a customer acquisition goal. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + TARGET_ALL_EQUALLY (2): + The mode is used when campaign is optimizing + equally for existing and new customers, which is + the default value. + BID_HIGHER_FOR_NEW_CUSTOMER (3): + The mode is used when campaign is bidding + higher for new customers than existing customer. + TARGET_NEW_CUSTOMER (4): + The mode is used when campaign is only + optimizing for new customers. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + TARGET_ALL_EQUALLY = 2 + BID_HIGHER_FOR_NEW_CUSTOMER = 3 + TARGET_NEW_CUSTOMER = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/customer_lifecycle_optimization_mode.py b/google/ads/googleads/v24/enums/types/customer_lifecycle_optimization_mode.py new file mode 100644 index 000000000..381b9af38 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/customer_lifecycle_optimization_mode.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerLifecycleOptimizationModeEnum", + }, +) + + +class CustomerLifecycleOptimizationModeEnum(proto.Message): + r"""Container for enum describing possible customer lifecycle + optimization modes. + + """ + + class CustomerLifecycleOptimizationMode(proto.Enum): + r"""Possible customer acquisition goal optimization modes. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + TARGET_ALL (2): + The mode is used when the campaign optimizes + for all customers, which is the default value. + TARGET_SPECIFIC (3): + This mode configures the campaign to target + only customers who have previously interacted + but are now lapsed or disengaged. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + TARGET_ALL = 2 + TARGET_SPECIFIC = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/customer_match_upload_key_type.py b/google/ads/googleads/v24/enums/types/customer_match_upload_key_type.py new file mode 100644 index 000000000..5edd59898 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/customer_match_upload_key_type.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerMatchUploadKeyTypeEnum", + }, +) + + +class CustomerMatchUploadKeyTypeEnum(proto.Message): + r"""Indicates what type of data are the user list's members + matched from. + + """ + + class CustomerMatchUploadKeyType(proto.Enum): + r"""Enum describing possible customer match upload key types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CONTACT_INFO (2): + Members are matched from customer info such + as email address, phone number or physical + address. + CRM_ID (3): + Members are matched from a user id generated + and assigned by the advertiser. + MOBILE_ADVERTISING_ID (4): + Members are matched from mobile advertising + ids. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CONTACT_INFO = 2 + CRM_ID = 3 + MOBILE_ADVERTISING_ID = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/customer_pay_per_conversion_eligibility_failure_reason.py b/google/ads/googleads/v24/enums/types/customer_pay_per_conversion_eligibility_failure_reason.py new file mode 100644 index 000000000..28fe1da79 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/customer_pay_per_conversion_eligibility_failure_reason.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerPayPerConversionEligibilityFailureReasonEnum", + }, +) + + +class CustomerPayPerConversionEligibilityFailureReasonEnum(proto.Message): + r"""Container for enum describing reasons why a customer is not + eligible to use PaymentMode.CONVERSIONS. + + """ + + class CustomerPayPerConversionEligibilityFailureReason(proto.Enum): + r"""Enum describing possible reasons a customer is not eligible + to use PaymentMode.CONVERSIONS. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + NOT_ENOUGH_CONVERSIONS (2): + Customer does not have enough conversions. + CONVERSION_LAG_TOO_HIGH (3): + Customer's conversion lag is too high. + HAS_CAMPAIGN_WITH_SHARED_BUDGET (4): + Customer uses shared budgets. + HAS_UPLOAD_CLICKS_CONVERSION (5): + Customer has conversions with + ConversionActionType.UPLOAD_CLICKS. + AVERAGE_DAILY_SPEND_TOO_HIGH (6): + Customer's average daily spend is too high. + ANALYSIS_NOT_COMPLETE (7): + Customer's eligibility has not yet been + calculated by the Google Ads backend. Check back + soon. + OTHER (8): + Customer is not eligible due to other + reasons. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NOT_ENOUGH_CONVERSIONS = 2 + CONVERSION_LAG_TOO_HIGH = 3 + HAS_CAMPAIGN_WITH_SHARED_BUDGET = 4 + HAS_UPLOAD_CLICKS_CONVERSION = 5 + AVERAGE_DAILY_SPEND_TOO_HIGH = 6 + ANALYSIS_NOT_COMPLETE = 7 + OTHER = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/customer_status.py b/google/ads/googleads/v24/enums/types/customer_status.py new file mode 100644 index 000000000..36e16026b --- /dev/null +++ b/google/ads/googleads/v24/enums/types/customer_status.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerStatusEnum", + }, +) + + +class CustomerStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a + customer. + + """ + + class CustomerStatus(proto.Enum): + r"""Possible statuses of a customer. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + Indicates an active account able to serve + ads. + CANCELED (3): + Indicates a canceled account unable to serve + ads. Can be reactivated by an admin user. + SUSPENDED (4): + Indicates a suspended account unable to serve + ads. May only be activated by Google support. + CLOSED (5): + Indicates a closed account unable to serve + ads. Test account will also have CLOSED status. + Status is permanent and may not be reopened. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + CANCELED = 3 + SUSPENDED = 4 + CLOSED = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/customizer_attribute_status.py b/google/ads/googleads/v24/enums/types/customizer_attribute_status.py new file mode 100644 index 000000000..a599eebe2 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/customizer_attribute_status.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomizerAttributeStatusEnum", + }, +) + + +class CustomizerAttributeStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a + customizer attribute. + + """ + + class CustomizerAttributeStatus(proto.Enum): + r"""The possible statuses of a customizer attribute. + + Values: + UNSPECIFIED (0): + The status has not been specified. + UNKNOWN (1): + The received value is not known in this + version. + ENABLED (2): + The customizer attribute is enabled. + REMOVED (3): + The customizer attribute is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/customizer_attribute_type.py b/google/ads/googleads/v24/enums/types/customizer_attribute_type.py new file mode 100644 index 000000000..4b5228f7f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/customizer_attribute_type.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomizerAttributeTypeEnum", + }, +) + + +class CustomizerAttributeTypeEnum(proto.Message): + r"""Container for enum describing possible types of a customizer + attribute. + + """ + + class CustomizerAttributeType(proto.Enum): + r"""The possible types of a customizer attribute. + + Values: + UNSPECIFIED (0): + The status has not been specified. + UNKNOWN (1): + The received value is not known in this + version. + TEXT (2): + Text customizer. + NUMBER (3): + Number customizer. + PRICE (4): + Price customizer consisting of a number and a + currency. + PERCENT (5): + Percentage customizer consisting of a number + and a '%'. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + TEXT = 2 + NUMBER = 3 + PRICE = 4 + PERCENT = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/customizer_value_status.py b/google/ads/googleads/v24/enums/types/customizer_value_status.py new file mode 100644 index 000000000..177d2347e --- /dev/null +++ b/google/ads/googleads/v24/enums/types/customizer_value_status.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "CustomizerValueStatusEnum", + }, +) + + +class CustomizerValueStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a + customizer value. + + """ + + class CustomizerValueStatus(proto.Enum): + r"""The possible statuses of a customizer value. + + Values: + UNSPECIFIED (0): + The status has not been specified. + UNKNOWN (1): + The received value is not known in this + version. + ENABLED (2): + The customizer value is enabled. + REMOVED (3): + The customizer value is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/data_driven_model_status.py b/google/ads/googleads/v24/enums/types/data_driven_model_status.py new file mode 100644 index 000000000..02c5ed042 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/data_driven_model_status.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "DataDrivenModelStatusEnum", + }, +) + + +class DataDrivenModelStatusEnum(proto.Message): + r"""Container for enum indicating data driven model status.""" + + class DataDrivenModelStatus(proto.Enum): + r"""Enumerates data driven model statuses. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + AVAILABLE (2): + The data driven model is available. + STALE (3): + The data driven model is stale. It hasn't + been updated for at least 7 days. It is still + being used, but will become expired if it does + not get updated for 30 days. + EXPIRED (4): + The data driven model expired. It hasn't been + updated for at least 30 days and cannot be used. + Most commonly this is because there hasn't been + the required number of events in a recent 30-day + period. + NEVER_GENERATED (5): + The data driven model has never been + generated. Most commonly this is because there + has never been the required number of events in + any 30-day period. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AVAILABLE = 2 + STALE = 3 + EXPIRED = 4 + NEVER_GENERATED = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/data_link_status.py b/google/ads/googleads/v24/enums/types/data_link_status.py new file mode 100644 index 000000000..3c6522726 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/data_link_status.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "DataLinkStatusEnum", + }, +) + + +class DataLinkStatusEnum(proto.Message): + r"""Container for enum describing different types of data links.""" + + class DataLinkStatus(proto.Enum): + r"""Describes the possible data link statuses. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + REQUESTED (2): + Link has been requested by one party, but not + confirmed by the other party. + PENDING_APPROVAL (3): + Link is waiting for the customer to approve. + ENABLED (4): + Link is established and can be used as + needed. + DISABLED (5): + Link is no longer valid and should be + ignored. + REVOKED (6): + Link request has been cancelled by the + requester and further cleanup may be needed. + REJECTED (7): + Link request has been rejected by the + approver. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + REQUESTED = 2 + PENDING_APPROVAL = 3 + ENABLED = 4 + DISABLED = 5 + REVOKED = 6 + REJECTED = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/data_link_type.py b/google/ads/googleads/v24/enums/types/data_link_type.py new file mode 100644 index 000000000..9fc3eb969 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/data_link_type.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "DataLinkTypeEnum", + }, +) + + +class DataLinkTypeEnum(proto.Message): + r"""Container for enum describing different types of data links.""" + + class DataLinkType(proto.Enum): + r"""Describes the possible data link types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + VIDEO (2): + A data link to YouTube video. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + VIDEO = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/day_of_week.py b/google/ads/googleads/v24/enums/types/day_of_week.py new file mode 100644 index 000000000..c1177331b --- /dev/null +++ b/google/ads/googleads/v24/enums/types/day_of_week.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "DayOfWeekEnum", + }, +) + + +class DayOfWeekEnum(proto.Message): + r"""Container for enumeration of days of the week, for example, + "Monday". + + """ + + class DayOfWeek(proto.Enum): + r"""Enumerates days of the week, for example, "Monday". + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + MONDAY (2): + Monday. + TUESDAY (3): + Tuesday. + WEDNESDAY (4): + Wednesday. + THURSDAY (5): + Thursday. + FRIDAY (6): + Friday. + SATURDAY (7): + Saturday. + SUNDAY (8): + Sunday. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MONDAY = 2 + TUESDAY = 3 + WEDNESDAY = 4 + THURSDAY = 5 + FRIDAY = 6 + SATURDAY = 7 + SUNDAY = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/demand_gen_channel_config.py b/google/ads/googleads/v24/enums/types/demand_gen_channel_config.py new file mode 100644 index 000000000..80e9f921f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/demand_gen_channel_config.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "DemandGenChannelConfigEnum", + }, +) + + +class DemandGenChannelConfigEnum(proto.Message): + r"""Container for the channel config enum.""" + + class DemandGenChannelConfig(proto.Enum): + r"""This value indicates which field within the 'oneof' group + (where only one option can be active) is used in the channel + controls for a Demand Gen ad group. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + CHANNEL_STRATEGY (2): + The channel controls configuration uses a + general channel strategy; individual channels + are not configured separately. + SELECTED_CHANNELS (3): + The channel controls configuration explicitly + defines the selected channels. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CHANNEL_STRATEGY = 2 + SELECTED_CHANNELS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/demand_gen_channel_strategy.py b/google/ads/googleads/v24/enums/types/demand_gen_channel_strategy.py new file mode 100644 index 000000000..98691b012 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/demand_gen_channel_strategy.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "DemandGenChannelStrategyEnum", + }, +) + + +class DemandGenChannelStrategyEnum(proto.Message): + r"""Container for the channel strategy enum.""" + + class DemandGenChannelStrategy(proto.Enum): + r"""The channel strategy defines a general grouping of channels + to enable in the Demand Gen channel controls. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + ALL_CHANNELS (2): + All channels are enabled. + ALL_OWNED_AND_OPERATED_CHANNELS (3): + All Google-owned and operated channels are + enabled; third-party channels (e.g., Display) + are disabled. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ALL_CHANNELS = 2 + ALL_OWNED_AND_OPERATED_CHANNELS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/device.py b/google/ads/googleads/v24/enums/types/device.py new file mode 100644 index 000000000..085c981a2 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/device.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "DeviceEnum", + }, +) + + +class DeviceEnum(proto.Message): + r"""Container for enumeration of Google Ads devices available for + targeting. + + """ + + class Device(proto.Enum): + r"""Enumerates Google Ads devices available for targeting. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + MOBILE (2): + Mobile devices with full browsers. + TABLET (3): + Tablets with full browsers. + DESKTOP (4): + Computers. + CONNECTED_TV (6): + Smart TVs and game consoles. + OTHER (5): + Other device types. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MOBILE = 2 + TABLET = 3 + DESKTOP = 4 + CONNECTED_TV = 6 + OTHER = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/display_ad_format_setting.py b/google/ads/googleads/v24/enums/types/display_ad_format_setting.py new file mode 100644 index 000000000..995160e78 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/display_ad_format_setting.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "DisplayAdFormatSettingEnum", + }, +) + + +class DisplayAdFormatSettingEnum(proto.Message): + r"""Container for display ad format settings.""" + + class DisplayAdFormatSetting(proto.Enum): + r"""Enumerates display ad format settings. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + ALL_FORMATS (2): + Text, image and native formats. + NON_NATIVE (3): + Text and image formats. + NATIVE (4): + Native format, for example, the format + rendering is controlled by the publisher and not + by Google. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ALL_FORMATS = 2 + NON_NATIVE = 3 + NATIVE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/display_upload_product_type.py b/google/ads/googleads/v24/enums/types/display_upload_product_type.py new file mode 100644 index 000000000..8179952a7 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/display_upload_product_type.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "DisplayUploadProductTypeEnum", + }, +) + + +class DisplayUploadProductTypeEnum(proto.Message): + r"""Container for display upload product types. Product types + that have the word "DYNAMIC" in them must be associated with a + campaign that has a dynamic remarketing feed. See + https://support.google.com/google-ads/answer/6053288 for more + info about dynamic remarketing. Other product types are regarded + as "static" and do not have this requirement. + + """ + + class DisplayUploadProductType(proto.Enum): + r"""Enumerates display upload product types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + HTML5_UPLOAD_AD (2): + HTML5 upload ad. This product type requires the + upload_media_bundle field in DisplayUploadAdInfo to be set. + DYNAMIC_HTML5_EDUCATION_AD (3): + Dynamic HTML5 education ad. This product type requires the + upload_media_bundle field in DisplayUploadAdInfo to be set. + Can only be used in an education campaign. + DYNAMIC_HTML5_FLIGHT_AD (4): + Dynamic HTML5 flight ad. This product type requires the + upload_media_bundle field in DisplayUploadAdInfo to be set. + Can only be used in a flight campaign. + DYNAMIC_HTML5_HOTEL_RENTAL_AD (5): + Dynamic HTML5 hotel and rental ad. This product type + requires the upload_media_bundle field in + DisplayUploadAdInfo to be set. Can only be used in a hotel + campaign. + DYNAMIC_HTML5_JOB_AD (6): + Dynamic HTML5 job ad. This product type requires the + upload_media_bundle field in DisplayUploadAdInfo to be set. + Can only be used in a job campaign. + DYNAMIC_HTML5_LOCAL_AD (7): + Dynamic HTML5 local ad. This product type requires the + upload_media_bundle field in DisplayUploadAdInfo to be set. + Can only be used in a local campaign. + DYNAMIC_HTML5_REAL_ESTATE_AD (8): + Dynamic HTML5 real estate ad. This product type requires the + upload_media_bundle field in DisplayUploadAdInfo to be set. + Can only be used in a real estate campaign. + DYNAMIC_HTML5_CUSTOM_AD (9): + Dynamic HTML5 custom ad. This product type requires the + upload_media_bundle field in DisplayUploadAdInfo to be set. + Can only be used in a custom campaign. + DYNAMIC_HTML5_TRAVEL_AD (10): + Dynamic HTML5 travel ad. This product type requires the + upload_media_bundle field in DisplayUploadAdInfo to be set. + Can only be used in a travel campaign. + DYNAMIC_HTML5_HOTEL_AD (11): + Dynamic HTML5 hotel ad. This product type requires the + upload_media_bundle field in DisplayUploadAdInfo to be set. + Can only be used in a hotel campaign. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + HTML5_UPLOAD_AD = 2 + DYNAMIC_HTML5_EDUCATION_AD = 3 + DYNAMIC_HTML5_FLIGHT_AD = 4 + DYNAMIC_HTML5_HOTEL_RENTAL_AD = 5 + DYNAMIC_HTML5_JOB_AD = 6 + DYNAMIC_HTML5_LOCAL_AD = 7 + DYNAMIC_HTML5_REAL_ESTATE_AD = 8 + DYNAMIC_HTML5_CUSTOM_AD = 9 + DYNAMIC_HTML5_TRAVEL_AD = 10 + DYNAMIC_HTML5_HOTEL_AD = 11 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/distance_bucket.py b/google/ads/googleads/v24/enums/types/distance_bucket.py new file mode 100644 index 000000000..0e79c5e95 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/distance_bucket.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "DistanceBucketEnum", + }, +) + + +class DistanceBucketEnum(proto.Message): + r"""Container for distance buckets of a user's distance from an + advertiser's location extension. + + """ + + class DistanceBucket(proto.Enum): + r"""The distance bucket for a user's distance from an + advertiser's location extension. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + WITHIN_700M (2): + User was within 700m of the location. + WITHIN_1KM (3): + User was within 1KM of the location. + WITHIN_5KM (4): + User was within 5KM of the location. + WITHIN_10KM (5): + User was within 10KM of the location. + WITHIN_15KM (6): + User was within 15KM of the location. + WITHIN_20KM (7): + User was within 20KM of the location. + WITHIN_25KM (8): + User was within 25KM of the location. + WITHIN_30KM (9): + User was within 30KM of the location. + WITHIN_35KM (10): + User was within 35KM of the location. + WITHIN_40KM (11): + User was within 40KM of the location. + WITHIN_45KM (12): + User was within 45KM of the location. + WITHIN_50KM (13): + User was within 50KM of the location. + WITHIN_55KM (14): + User was within 55KM of the location. + WITHIN_60KM (15): + User was within 60KM of the location. + WITHIN_65KM (16): + User was within 65KM of the location. + BEYOND_65KM (17): + User was beyond 65KM of the location. + WITHIN_0_7MILES (18): + User was within 0.7 miles of the location. + WITHIN_1MILE (19): + User was within 1 mile of the location. + WITHIN_5MILES (20): + User was within 5 miles of the location. + WITHIN_10MILES (21): + User was within 10 miles of the location. + WITHIN_15MILES (22): + User was within 15 miles of the location. + WITHIN_20MILES (23): + User was within 20 miles of the location. + WITHIN_25MILES (24): + User was within 25 miles of the location. + WITHIN_30MILES (25): + User was within 30 miles of the location. + WITHIN_35MILES (26): + User was within 35 miles of the location. + WITHIN_40MILES (27): + User was within 40 miles of the location. + BEYOND_40MILES (28): + User was beyond 40 miles of the location. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + WITHIN_700M = 2 + WITHIN_1KM = 3 + WITHIN_5KM = 4 + WITHIN_10KM = 5 + WITHIN_15KM = 6 + WITHIN_20KM = 7 + WITHIN_25KM = 8 + WITHIN_30KM = 9 + WITHIN_35KM = 10 + WITHIN_40KM = 11 + WITHIN_45KM = 12 + WITHIN_50KM = 13 + WITHIN_55KM = 14 + WITHIN_60KM = 15 + WITHIN_65KM = 16 + BEYOND_65KM = 17 + WITHIN_0_7MILES = 18 + WITHIN_1MILE = 19 + WITHIN_5MILES = 20 + WITHIN_10MILES = 21 + WITHIN_15MILES = 22 + WITHIN_20MILES = 23 + WITHIN_25MILES = 24 + WITHIN_30MILES = 25 + WITHIN_35MILES = 26 + WITHIN_40MILES = 27 + BEYOND_40MILES = 28 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/eu_political_advertising_status.py b/google/ads/googleads/v24/enums/types/eu_political_advertising_status.py new file mode 100644 index 000000000..213c452da --- /dev/null +++ b/google/ads/googleads/v24/enums/types/eu_political_advertising_status.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "EuPoliticalAdvertisingStatusEnum", + }, +) + + +class EuPoliticalAdvertisingStatusEnum(proto.Message): + r"""Container for enum describing whether or not the campaign + contains political advertising targeted towards the European + Union. + + """ + + class EuPoliticalAdvertisingStatus(proto.Enum): + r"""Possible values describing whether or not the campaign + contains political advertising targeted towards the European + Union. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CONTAINS_EU_POLITICAL_ADVERTISING (2): + The campaign contains political advertising + targeted towards the EU. The campaign will be + restricted from serving ads in the EU. + DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING (3): + The campaign does not contain political + advertising targeted towards the EU. No + additional serving restrictions will apply. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CONTAINS_EU_POLITICAL_ADVERTISING = 2 + DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/experiment_metric.py b/google/ads/googleads/v24/enums/types/experiment_metric.py new file mode 100644 index 000000000..2a1d914b1 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/experiment_metric.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ExperimentMetricEnum", + }, +) + + +class ExperimentMetricEnum(proto.Message): + r"""Container for enum describing the type of experiment metric.""" + + class ExperimentMetric(proto.Enum): + r"""The type of experiment metric. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + CLICKS (2): + The goal of the experiment is clicks. + IMPRESSIONS (3): + The goal of the experiment is impressions. + COST (4): + The goal of the experiment is cost. + CONVERSIONS_PER_INTERACTION_RATE (5): + The goal of the experiment is conversion + rate. + COST_PER_CONVERSION (6): + The goal of the experiment is cost per + conversion. + CONVERSIONS_VALUE_PER_COST (7): + The goal of the experiment is conversion + value per cost. + AVERAGE_CPC (8): + The goal of the experiment is avg cpc. + CTR (9): + The goal of the experiment is ctr. + INCREMENTAL_CONVERSIONS (10): + The goal of the experiment is incremental + conversions. + COMPLETED_VIDEO_VIEWS (11): + The goal of the experiment is completed video + views. + CUSTOM_ALGORITHMS (12): + The goal of the experiment is custom + algorithms. + CONVERSIONS (13): + The goal of the experiment is conversions. + CONVERSION_VALUE (14): + The goal of the experiment is conversion + value. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CLICKS = 2 + IMPRESSIONS = 3 + COST = 4 + CONVERSIONS_PER_INTERACTION_RATE = 5 + COST_PER_CONVERSION = 6 + CONVERSIONS_VALUE_PER_COST = 7 + AVERAGE_CPC = 8 + CTR = 9 + INCREMENTAL_CONVERSIONS = 10 + COMPLETED_VIDEO_VIEWS = 11 + CUSTOM_ALGORITHMS = 12 + CONVERSIONS = 13 + CONVERSION_VALUE = 14 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/experiment_metric_direction.py b/google/ads/googleads/v24/enums/types/experiment_metric_direction.py new file mode 100644 index 000000000..ebbf6669c --- /dev/null +++ b/google/ads/googleads/v24/enums/types/experiment_metric_direction.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ExperimentMetricDirectionEnum", + }, +) + + +class ExperimentMetricDirectionEnum(proto.Message): + r"""Container for enum describing the type of experiment metric + direction. + + """ + + class ExperimentMetricDirection(proto.Enum): + r"""The type of experiment metric direction. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + NO_CHANGE (2): + The goal of the experiment is to not change + the metric. + INCREASE (3): + The goal of the experiment is to increate the + metric. + DECREASE (4): + The goal of the experiment is to decrease the + metric. + NO_CHANGE_OR_INCREASE (5): + The goal of the experiment is to either not + change or increase the metric. + NO_CHANGE_OR_DECREASE (6): + The goal of the experiment is to either not + change or decrease the metric. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NO_CHANGE = 2 + INCREASE = 3 + DECREASE = 4 + NO_CHANGE_OR_INCREASE = 5 + NO_CHANGE_OR_DECREASE = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/experiment_status.py b/google/ads/googleads/v24/enums/types/experiment_status.py new file mode 100644 index 000000000..614f44039 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/experiment_status.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ExperimentStatusEnum", + }, +) + + +class ExperimentStatusEnum(proto.Message): + r"""Container for enum describing the experiment status.""" + + class ExperimentStatus(proto.Enum): + r"""The status of the experiment. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + ENABLED (2): + The experiment is enabled. + REMOVED (3): + The experiment has been removed. + HALTED (4): + The experiment has been halted. + This status can be set from ENABLED status + through API. + PROMOTED (5): + The experiment will be promoted out of + experimental status. + SETUP (6): + Initial status of the experiment. + INITIATED (7): + The experiment's campaigns are pending + materialization. This status can be set from + SETUP status through API. + GRADUATED (8): + The experiment has been graduated. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + HALTED = 4 + PROMOTED = 5 + SETUP = 6 + INITIATED = 7 + GRADUATED = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/experiment_type.py b/google/ads/googleads/v24/enums/types/experiment_type.py new file mode 100644 index 000000000..a713b9fe3 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/experiment_type.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ExperimentTypeEnum", + }, +) + + +class ExperimentTypeEnum(proto.Message): + r"""Container for enum describing the type of experiment.""" + + class ExperimentType(proto.Enum): + r"""The type of the experiment. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + DISPLAY_AND_VIDEO_360 (2): + This is a DISPLAY_AND_VIDEO_360 experiment. + AD_VARIATION (3): + This is an ad variation experiment. + YOUTUBE_CUSTOM (5): + A custom experiment consisting of Video + campaigns. + DISPLAY_CUSTOM (6): + A custom experiment consisting of display + campaigns. + SEARCH_CUSTOM (7): + A custom experiment consisting of search + campaigns. + DISPLAY_AUTOMATED_BIDDING_STRATEGY (8): + An experiment that compares bidding + strategies for display campaigns. + SEARCH_AUTOMATED_BIDDING_STRATEGY (9): + An experiment that compares bidding + strategies for search campaigns.". + SHOPPING_AUTOMATED_BIDDING_STRATEGY (10): + An experiment that compares bidding + strategies for shopping campaigns. + SMART_MATCHING (11): + DEPRECATED. A smart matching experiment with + search campaigns. + HOTEL_CUSTOM (12): + A custom experiment consisting of hotel + campaigns. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DISPLAY_AND_VIDEO_360 = 2 + AD_VARIATION = 3 + YOUTUBE_CUSTOM = 5 + DISPLAY_CUSTOM = 6 + SEARCH_CUSTOM = 7 + DISPLAY_AUTOMATED_BIDDING_STRATEGY = 8 + SEARCH_AUTOMATED_BIDDING_STRATEGY = 9 + SHOPPING_AUTOMATED_BIDDING_STRATEGY = 10 + SMART_MATCHING = 11 + HOTEL_CUSTOM = 12 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/external_conversion_source.py b/google/ads/googleads/v24/enums/types/external_conversion_source.py new file mode 100644 index 000000000..d921dee05 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/external_conversion_source.py @@ -0,0 +1,193 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ExternalConversionSourceEnum", + }, +) + + +class ExternalConversionSourceEnum(proto.Message): + r"""Container for enum describing the external conversion source + that is associated with a ConversionAction. + + """ + + class ExternalConversionSource(proto.Enum): + r"""The external conversion source that is associated with a + ConversionAction. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Represents value unknown in this version. + WEBPAGE (2): + Conversion that occurs when a user navigates + to a particular webpage after viewing an ad; + Displayed in Google Ads UI as 'Website'. + ANALYTICS (3): + Conversion that comes from linked Google + Analytics goal or transaction; Displayed in + Google Ads UI as 'Analytics'. + UPLOAD (4): + Website conversion that is uploaded through + ConversionUploadService; Displayed in Google Ads + UI as 'Import from clicks'. + AD_CALL_METRICS (5): + Conversion that occurs when a user clicks on + a call extension directly on an ad; Displayed in + Google Ads UI as 'Calls from ads'. + WEBSITE_CALL_METRICS (6): + Conversion that occurs when a user calls a + dynamically-generated phone number (by installed + javascript) from an advertiser's website after + clicking on an ad; Displayed in Google Ads UI as + 'Calls from website'. + STORE_VISITS (7): + Conversion that occurs when a user visits an + advertiser's retail store after clicking on a + Google ad; Displayed in Google Ads UI as 'Store + visits'. + ANDROID_IN_APP (8): + Conversion that occurs when a user takes an + in-app action such as a purchase in an Android + app; Displayed in Google Ads UI as 'Android + in-app action'. + IOS_IN_APP (9): + Conversion that occurs when a user takes an + in-app action such as a purchase in an iOS app; + Displayed in Google Ads UI as 'iOS in-app + action'. + IOS_FIRST_OPEN (10): + Conversion that occurs when a user opens an + iOS app for the first time; Displayed in Google + Ads UI as 'iOS app install (first open)'. + APP_UNSPECIFIED (11): + Legacy app conversions that do not have an + AppPlatform provided; Displayed in Google Ads UI + as 'Mobile app'. + ANDROID_FIRST_OPEN (12): + Conversion that occurs when a user opens an + Android app for the first time; Displayed in + Google Ads UI as 'Android app install (first + open)'. + UPLOAD_CALLS (13): + Call conversion that is uploaded through + ConversionUploadService; Displayed in Google Ads + UI as 'Import from calls'. + FIREBASE (14): + Conversion that comes from a linked Firebase + event; Displayed in Google Ads UI as 'Firebase'. + CLICK_TO_CALL (15): + Conversion that occurs when a user clicks on + a mobile phone number; Displayed in Google Ads + UI as 'Phone number clicks'. + SALESFORCE (16): + Conversion that comes from Salesforce; + Displayed in Google Ads UI as 'Salesforce.com'. + STORE_SALES_CRM (17): + Conversion that comes from in-store purchases + recorded by CRM; Displayed in Google Ads UI as + 'Store sales (data partner)'. + STORE_SALES_PAYMENT_NETWORK (18): + Conversion that comes from in-store purchases + from payment network; Displayed in Google Ads UI + as 'Store sales (payment network)'. + GOOGLE_PLAY (19): + Codeless Google Play conversion; + Displayed in Google Ads UI as 'Google Play'. + THIRD_PARTY_APP_ANALYTICS (20): + Conversion that comes from a linked + third-party app analytics event; Displayed in + Google Ads UI as 'Third-party app analytics'. + GOOGLE_ATTRIBUTION (21): + Conversion that is controlled by Google + Attribution. + STORE_SALES_DIRECT_UPLOAD (23): + Store Sales conversion based on first-party + or third-party merchant data uploads. Displayed + in Google Ads UI as 'Store sales (direct + upload)'. + STORE_SALES (24): + Store Sales conversion based on first-party + or third-party merchant data uploads and/or from + in-store purchases using cards from payment + networks. Displayed in Google Ads UI as 'Store + sales'. + SEARCH_ADS_360 (25): + Conversions imported from Search Ads 360 + Floodlight data. + GOOGLE_HOSTED (27): + Conversions that track local actions from + Google's products and services after interacting + with an ad. + FLOODLIGHT (29): + Conversions reported by Floodlight tags. + ANALYTICS_SEARCH_ADS_360 (31): + Conversions that come from Google Analytics + specifically for Search Ads + 360. Displayed in Google Ads UI as Analytics + (SA360). + FIREBASE_SEARCH_ADS_360 (33): + Conversion that comes from a linked Firebase + event for Search Ads 360. + DISPLAY_AND_VIDEO_360_FLOODLIGHT (34): + Conversion that is reported by Floodlight for + DV360. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + WEBPAGE = 2 + ANALYTICS = 3 + UPLOAD = 4 + AD_CALL_METRICS = 5 + WEBSITE_CALL_METRICS = 6 + STORE_VISITS = 7 + ANDROID_IN_APP = 8 + IOS_IN_APP = 9 + IOS_FIRST_OPEN = 10 + APP_UNSPECIFIED = 11 + ANDROID_FIRST_OPEN = 12 + UPLOAD_CALLS = 13 + FIREBASE = 14 + CLICK_TO_CALL = 15 + SALESFORCE = 16 + STORE_SALES_CRM = 17 + STORE_SALES_PAYMENT_NETWORK = 18 + GOOGLE_PLAY = 19 + THIRD_PARTY_APP_ANALYTICS = 20 + GOOGLE_ATTRIBUTION = 21 + STORE_SALES_DIRECT_UPLOAD = 23 + STORE_SALES = 24 + SEARCH_ADS_360 = 25 + GOOGLE_HOSTED = 27 + FLOODLIGHT = 29 + ANALYTICS_SEARCH_ADS_360 = 31 + FIREBASE_SEARCH_ADS_360 = 33 + DISPLAY_AND_VIDEO_360_FLOODLIGHT = 34 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/fixed_cpm_goal.py b/google/ads/googleads/v24/enums/types/fixed_cpm_goal.py new file mode 100644 index 000000000..b6492912d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/fixed_cpm_goal.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "FixedCpmGoalEnum", + }, +) + + +class FixedCpmGoalEnum(proto.Message): + r"""Container for describing the goal of the Fixed CPM bidding + strategy. + + """ + + class FixedCpmGoal(proto.Enum): + r"""Enum describing the goal of the Fixed CPM bidding strategy. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + REACH (2): + Maximize reach, that is the number of users + who saw the ads in this campaign. + TARGET_FREQUENCY (3): + Target Frequency CPM bidder. Optimize bidding + to reach a single user with the requested + frequency. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + REACH = 2 + TARGET_FREQUENCY = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/fixed_cpm_target_frequency_time_unit.py b/google/ads/googleads/v24/enums/types/fixed_cpm_target_frequency_time_unit.py new file mode 100644 index 000000000..85be021f7 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/fixed_cpm_target_frequency_time_unit.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "FixedCpmTargetFrequencyTimeUnitEnum", + }, +) + + +class FixedCpmTargetFrequencyTimeUnitEnum(proto.Message): + r"""Container for enum describing bidding goal target frequency + time units. + + """ + + class FixedCpmTargetFrequencyTimeUnit(proto.Enum): + r"""An enum describing the time window over which the bidding is + optimized to meet the target frequency when using Fixed CPM + bidding strategy. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + MONTHLY (2): + Optimize bidding to reach target frequency in + 30 days. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MONTHLY = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/frequency_cap_event_type.py b/google/ads/googleads/v24/enums/types/frequency_cap_event_type.py new file mode 100644 index 000000000..89cab6730 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/frequency_cap_event_type.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "FrequencyCapEventTypeEnum", + }, +) + + +class FrequencyCapEventTypeEnum(proto.Message): + r"""Container for enum describing the type of event that the cap + applies to. + + """ + + class FrequencyCapEventType(proto.Enum): + r"""The type of event that the cap applies to (for example, + impression). + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + IMPRESSION (2): + The cap applies on ad impressions. + VIDEO_VIEW (3): + The cap applies on video ad views. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + IMPRESSION = 2 + VIDEO_VIEW = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/frequency_cap_level.py b/google/ads/googleads/v24/enums/types/frequency_cap_level.py new file mode 100644 index 000000000..14df109a3 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/frequency_cap_level.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "FrequencyCapLevelEnum", + }, +) + + +class FrequencyCapLevelEnum(proto.Message): + r"""Container for enum describing the level on which the cap is + to be applied. + + """ + + class FrequencyCapLevel(proto.Enum): + r"""The level on which the cap is to be applied (e.g ad group ad, + ad group). Cap is applied to all the resources of this level. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + AD_GROUP_AD (2): + The cap is applied at the ad group ad level. + AD_GROUP (3): + The cap is applied at the ad group level. + CAMPAIGN (4): + The cap is applied at the campaign level. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AD_GROUP_AD = 2 + AD_GROUP = 3 + CAMPAIGN = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/frequency_cap_time_unit.py b/google/ads/googleads/v24/enums/types/frequency_cap_time_unit.py new file mode 100644 index 000000000..45c42cfd0 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/frequency_cap_time_unit.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "FrequencyCapTimeUnitEnum", + }, +) + + +class FrequencyCapTimeUnitEnum(proto.Message): + r"""Container for enum describing the unit of time the cap is + defined at. + + """ + + class FrequencyCapTimeUnit(proto.Enum): + r"""Unit of time the cap is defined at (for example, day, week). + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + DAY (2): + The cap would define limit per one day. + WEEK (3): + The cap would define limit per one week. + MONTH (4): + The cap would define limit per one month. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DAY = 2 + WEEK = 3 + MONTH = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/gender_type.py b/google/ads/googleads/v24/enums/types/gender_type.py new file mode 100644 index 000000000..963381174 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/gender_type.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "GenderTypeEnum", + }, +) + + +class GenderTypeEnum(proto.Message): + r"""Container for enum describing the type of demographic + genders. + + """ + + class GenderType(proto.Enum): + r"""The type of demographic genders (for example, female). + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + MALE (10): + Male. + FEMALE (11): + Female. + UNDETERMINED (20): + Undetermined gender. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MALE = 10 + FEMALE = 11 + UNDETERMINED = 20 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/geo_target_constant_status.py b/google/ads/googleads/v24/enums/types/geo_target_constant_status.py new file mode 100644 index 000000000..279f2519c --- /dev/null +++ b/google/ads/googleads/v24/enums/types/geo_target_constant_status.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "GeoTargetConstantStatusEnum", + }, +) + + +class GeoTargetConstantStatusEnum(proto.Message): + r"""Container for describing the status of a geo target constant.""" + + class GeoTargetConstantStatus(proto.Enum): + r"""The possible statuses of a geo target constant. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + ENABLED (2): + The geo target constant is valid. + REMOVAL_PLANNED (3): + The geo target constant is obsolete and will + be removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVAL_PLANNED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/geo_targeting_type.py b/google/ads/googleads/v24/enums/types/geo_targeting_type.py new file mode 100644 index 000000000..c1f54aa61 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/geo_targeting_type.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "GeoTargetingTypeEnum", + }, +) + + +class GeoTargetingTypeEnum(proto.Message): + r"""Container for enum describing possible geo targeting types.""" + + class GeoTargetingType(proto.Enum): + r"""The possible geo targeting types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + AREA_OF_INTEREST (2): + Location the user is interested in while + making the query. + LOCATION_OF_PRESENCE (3): + Location of the user issuing the query. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AREA_OF_INTEREST = 2 + LOCATION_OF_PRESENCE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/goal_config_level.py b/google/ads/googleads/v24/enums/types/goal_config_level.py new file mode 100644 index 000000000..2caa64c99 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/goal_config_level.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "GoalConfigLevelEnum", + }, +) + + +class GoalConfigLevelEnum(proto.Message): + r"""Container for enum describing possible goal config levels.""" + + class GoalConfigLevel(proto.Enum): + r"""The possible goal config levels. Campaigns automatically + inherit the effective conversion account's customer goals unless + they have been configured with their own set of campaign goals. + + Values: + UNSPECIFIED (0): + The goal config level has not been specified. + UNKNOWN (1): + The goal config level is not known in this + version. + CUSTOMER (2): + The goal config is defined at the customer + level. + CAMPAIGN (3): + The goal config is defined at the campaign + level. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER = 2 + CAMPAIGN = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/goal_optimization_eligibility.py b/google/ads/googleads/v24/enums/types/goal_optimization_eligibility.py new file mode 100644 index 000000000..3138dfa60 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/goal_optimization_eligibility.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "GoalOptimizationEligibilityEnum", + }, +) + + +class GoalOptimizationEligibilityEnum(proto.Message): + r"""Container for enum describing possible goal optimization + eligibility. + + """ + + class GoalOptimizationEligibility(proto.Enum): + r"""The possible goal optimization eligibility. + + Values: + UNSPECIFIED (0): + The goal optimization status has not been + specified. + UNKNOWN (1): + The goal optimization status is not known in + this version. + ELIGIBLE (2): + The goal is eligible for campaign + optimization. + INELIGIBLE (3): + The goal is not eligible for campaign + optimization. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ELIGIBLE = 2 + INELIGIBLE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/goal_type.py b/google/ads/googleads/v24/enums/types/goal_type.py new file mode 100644 index 000000000..956f46caa --- /dev/null +++ b/google/ads/googleads/v24/enums/types/goal_type.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "GoalTypeEnum", + }, +) + + +class GoalTypeEnum(proto.Message): + r"""Container for enum describing goal types.""" + + class GoalType(proto.Enum): + r"""The possible value of goal types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CUSTOMER_RETENTION (3): + Retention goal, which allows advertisers to + optimize campaigns to win back lapsed customers. + (https://support.google.com/google-ads/answer/14792043?hl=en) + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER_RETENTION = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/google_ads_field_category.py b/google/ads/googleads/v24/enums/types/google_ads_field_category.py new file mode 100644 index 000000000..5c9152230 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/google_ads_field_category.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "GoogleAdsFieldCategoryEnum", + }, +) + + +class GoogleAdsFieldCategoryEnum(proto.Message): + r"""Container for enum that determines if the described artifact + is a resource or a field, and if it is a field, when it segments + search queries. + + """ + + class GoogleAdsFieldCategory(proto.Enum): + r"""The category of the artifact. + + Values: + UNSPECIFIED (0): + Unspecified + UNKNOWN (1): + Unknown + RESOURCE (2): + The described artifact is a resource. + ATTRIBUTE (3): + The described artifact is a field and is an + attribute of a resource. Including a resource + attribute field in a query may segment the query + if the resource to which it is attributed + segments the resource found in the FROM clause. + SEGMENT (5): + The described artifact is a field and always + segments search queries. + METRIC (6): + The described artifact is a field and is a + metric. It never segments search queries. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + RESOURCE = 2 + ATTRIBUTE = 3 + SEGMENT = 5 + METRIC = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/google_ads_field_data_type.py b/google/ads/googleads/v24/enums/types/google_ads_field_data_type.py new file mode 100644 index 000000000..0f9d20ac1 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/google_ads_field_data_type.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "GoogleAdsFieldDataTypeEnum", + }, +) + + +class GoogleAdsFieldDataTypeEnum(proto.Message): + r"""Container holding the various data types.""" + + class GoogleAdsFieldDataType(proto.Enum): + r"""These are the various types a GoogleAdsService artifact may + take on. + + Values: + UNSPECIFIED (0): + Unspecified + UNKNOWN (1): + Unknown + BOOLEAN (2): + Maps to google.protobuf.BoolValue + + Applicable operators: =, != + DATE (3): + Maps to google.protobuf.StringValue. It can + be compared using the set of operators specific + to dates however. + + Applicable operators: =, <, >, <=, >=, BETWEEN, + DURING, and IN + DOUBLE (4): + Maps to google.protobuf.DoubleValue + + Applicable operators: =, !=, <, >, IN, NOT IN + ENUM (5): + Maps to an enum. It's specific definition can be found at + type_url. + + Applicable operators: =, !=, IN, NOT IN + FLOAT (6): + Maps to google.protobuf.FloatValue + + Applicable operators: =, !=, <, >, IN, NOT IN + INT32 (7): + Maps to google.protobuf.Int32Value + + Applicable operators: =, !=, <, >, <=, >=, + BETWEEN, IN, NOT IN + INT64 (8): + Maps to google.protobuf.Int64Value + + Applicable operators: =, !=, <, >, <=, >=, + BETWEEN, IN, NOT IN + MESSAGE (9): + Maps to a protocol buffer message type. The data type's + details can be found in type_url. + + No operators work with MESSAGE fields. + RESOURCE_NAME (10): + Maps to google.protobuf.StringValue. Represents the resource + name (unique id) of a resource or one of its foreign keys. + + No operators work with RESOURCE_NAME fields. + STRING (11): + Maps to google.protobuf.StringValue. + + Applicable operators: =, !=, LIKE, NOT LIKE, + IN, NOT IN + UINT64 (12): + Maps to google.protobuf.UInt64Value + + Applicable operators: =, !=, <, >, <=, >=, + BETWEEN, IN, NOT IN + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BOOLEAN = 2 + DATE = 3 + DOUBLE = 4 + ENUM = 5 + FLOAT = 6 + INT32 = 7 + INT64 = 8 + MESSAGE = 9 + RESOURCE_NAME = 10 + STRING = 11 + UINT64 = 12 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/google_voice_call_status.py b/google/ads/googleads/v24/enums/types/google_voice_call_status.py new file mode 100644 index 000000000..8b6b1ff25 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/google_voice_call_status.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "GoogleVoiceCallStatusEnum", + }, +) + + +class GoogleVoiceCallStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a google + voice call. + + """ + + class GoogleVoiceCallStatus(proto.Enum): + r"""Possible statuses of a google voice call. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + MISSED (2): + The call was missed. + RECEIVED (3): + The call was received. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MISSED = 2 + RECEIVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/hotel_asset_suggestion_status.py b/google/ads/googleads/v24/enums/types/hotel_asset_suggestion_status.py new file mode 100644 index 000000000..a267c2c16 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/hotel_asset_suggestion_status.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "HotelAssetSuggestionStatusEnum", + }, +) + + +class HotelAssetSuggestionStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a hotel + asset suggestion. + + """ + + class HotelAssetSuggestionStatus(proto.Enum): + r"""Possible statuses of a hotel asset suggestion. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + SUCCESS (2): + The hotel asset suggestion was successfully + retrieved. + HOTEL_NOT_FOUND (3): + A hotel look up returns nothing. + INVALID_PLACE_ID (4): + A Google Places ID is invalid and cannot be + decoded. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SUCCESS = 2 + HOTEL_NOT_FOUND = 3 + INVALID_PLACE_ID = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/hotel_date_selection_type.py b/google/ads/googleads/v24/enums/types/hotel_date_selection_type.py new file mode 100644 index 000000000..149fd5184 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/hotel_date_selection_type.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "HotelDateSelectionTypeEnum", + }, +) + + +class HotelDateSelectionTypeEnum(proto.Message): + r"""Container for enum describing possible hotel date selection + types + + """ + + class HotelDateSelectionType(proto.Enum): + r"""Enum describing possible hotel date selection types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + DEFAULT_SELECTION (50): + Dates selected by default. + USER_SELECTED (51): + Dates selected by the user. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DEFAULT_SELECTION = 50 + USER_SELECTED = 51 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/hotel_price_bucket.py b/google/ads/googleads/v24/enums/types/hotel_price_bucket.py new file mode 100644 index 000000000..6bd4ed28e --- /dev/null +++ b/google/ads/googleads/v24/enums/types/hotel_price_bucket.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "HotelPriceBucketEnum", + }, +) + + +class HotelPriceBucketEnum(proto.Message): + r"""Container for enum describing hotel price bucket for a hotel + itinerary. + + """ + + class HotelPriceBucket(proto.Enum): + r"""Enum describing possible hotel price buckets. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + LOWEST_UNIQUE (2): + Uniquely lowest price. Partner has the lowest + price, and no other partners are within a small + variance of that price. + LOWEST_TIED (3): + Tied for lowest price. Partner is within a + small variance of the lowest price. + NOT_LOWEST (4): + Not lowest price. Partner is not within a + small variance of the lowest price. + ONLY_PARTNER_SHOWN (5): + Partner was the only one shown. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LOWEST_UNIQUE = 2 + LOWEST_TIED = 3 + NOT_LOWEST = 4 + ONLY_PARTNER_SHOWN = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/hotel_rate_type.py b/google/ads/googleads/v24/enums/types/hotel_rate_type.py new file mode 100644 index 000000000..148e929f6 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/hotel_rate_type.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "HotelRateTypeEnum", + }, +) + + +class HotelRateTypeEnum(proto.Message): + r"""Container for enum describing possible hotel rate types.""" + + class HotelRateType(proto.Enum): + r"""Enum describing possible hotel rate types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + UNAVAILABLE (2): + Rate type information is unavailable. + PUBLIC_RATE (3): + Rates available to everyone. + QUALIFIED_RATE (4): + A membership program rate is available and + satisfies basic requirements like having a + public rate available. UI treatment will + strikethrough the public rate and indicate that + a discount is available to the user. For more on + Qualified Rates, visit + https://developers.google.com/hotels/hotel-ads/dev-guide/qualified-rates + PRIVATE_RATE (5): + Rates available to users that satisfy some + eligibility criteria, for example, all signed-in + users, 20% of mobile users, all mobile users in + Canada, etc. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UNAVAILABLE = 2 + PUBLIC_RATE = 3 + QUALIFIED_RATE = 4 + PRIVATE_RATE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/hotel_reconciliation_status.py b/google/ads/googleads/v24/enums/types/hotel_reconciliation_status.py new file mode 100644 index 000000000..72480744a --- /dev/null +++ b/google/ads/googleads/v24/enums/types/hotel_reconciliation_status.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "HotelReconciliationStatusEnum", + }, +) + + +class HotelReconciliationStatusEnum(proto.Message): + r"""Container for HotelReconciliationStatus.""" + + class HotelReconciliationStatus(proto.Enum): + r"""Status of the hotel booking reconciliation. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + RESERVATION_ENABLED (2): + Bookings are for a future date, or a stay is + underway but the check-out date hasn't passed. + An active reservation can't be reconciled. + RECONCILIATION_NEEDED (3): + Check-out has already taken place, or the + booked dates have passed without cancellation. + Bookings that are not reconciled within 45 days + of the check-out date are billed based on the + original booking price. + RECONCILED (4): + These bookings have been reconciled. + Reconciled bookings are billed 45 days after the + check-out date. + CANCELED (5): + This booking was marked as canceled. Canceled + stays with a value greater than zero (due to + minimum stay rules or cancellation fees) are + billed 45 days after the check-out date. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + RESERVATION_ENABLED = 2 + RECONCILIATION_NEEDED = 3 + RECONCILED = 4 + CANCELED = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/identity_verification_program.py b/google/ads/googleads/v24/enums/types/identity_verification_program.py new file mode 100644 index 000000000..d899216f4 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/identity_verification_program.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "IdentityVerificationProgramEnum", + }, +) + + +class IdentityVerificationProgramEnum(proto.Message): + r"""Container for IdentityVerificationProgram.""" + + class IdentityVerificationProgram(proto.Enum): + r"""Type of identity verification program. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + ADVERTISER_IDENTITY_VERIFICATION (2): + Advertiser submits documents to verify their + identity. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ADVERTISER_IDENTITY_VERIFICATION = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/identity_verification_program_status.py b/google/ads/googleads/v24/enums/types/identity_verification_program_status.py new file mode 100644 index 000000000..2a193ae37 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/identity_verification_program_status.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "IdentityVerificationProgramStatusEnum", + }, +) + + +class IdentityVerificationProgramStatusEnum(proto.Message): + r"""Container for IdentityVerificationProgramStatus.""" + + class IdentityVerificationProgramStatus(proto.Enum): + r"""Program status of identity verification. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + PENDING_USER_ACTION (2): + Verification is pending on user action to + proceed. + PENDING_REVIEW (3): + Verification is pending on review. + SUCCESS (4): + Verification succeeded. + FAILURE (5): + Verification failed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING_USER_ACTION = 2 + PENDING_REVIEW = 3 + SUCCESS = 4 + FAILURE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/incentive_state.py b/google/ads/googleads/v24/enums/types/incentive_state.py new file mode 100644 index 000000000..b0afce19f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/incentive_state.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "IncentiveStateEnum", + }, +) + + +class IncentiveStateEnum(proto.Message): + r"""Container for the incentive state enum.""" + + class IncentiveState(proto.Enum): + r"""The possible states of a redeemed incentive. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + REDEEMED (2): + The incentive has been redeemed but the + requirements are not yet met. + FULFILLED (3): + The incentive's requirements have been met + but the reward has not yet been granted. + REWARD_GRANTED (4): + The reward for the incentive has been + granted. + EXPIRED (5): + The incentive expired before the requirements + were met. + REWARD_EXPIRED (6): + The granted reward has expired. + INVALIDATED (7): + The incentive was marked as invalid after + redemption. + REWARD_EXHAUSTED (8): + The granted reward has been fully used. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + REDEEMED = 2 + FULFILLED = 3 + REWARD_GRANTED = 4 + EXPIRED = 5 + REWARD_EXPIRED = 6 + INVALIDATED = 7 + REWARD_EXHAUSTED = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/income_range_type.py b/google/ads/googleads/v24/enums/types/income_range_type.py new file mode 100644 index 000000000..ecedc92ab --- /dev/null +++ b/google/ads/googleads/v24/enums/types/income_range_type.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "IncomeRangeTypeEnum", + }, +) + + +class IncomeRangeTypeEnum(proto.Message): + r"""Container for enum describing the type of demographic income + ranges. + + """ + + class IncomeRangeType(proto.Enum): + r"""The type of demographic income ranges (for example, between + 0% to 50%). + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + INCOME_RANGE_0_50 (510001): + 0%-50%. + INCOME_RANGE_50_60 (510002): + 50% to 60%. + INCOME_RANGE_60_70 (510003): + 60% to 70%. + INCOME_RANGE_70_80 (510004): + 70% to 80%. + INCOME_RANGE_80_90 (510005): + 80% to 90%. + INCOME_RANGE_90_UP (510006): + Greater than 90%. + INCOME_RANGE_UNDETERMINED (510000): + Undetermined income range. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INCOME_RANGE_0_50 = 510001 + INCOME_RANGE_50_60 = 510002 + INCOME_RANGE_60_70 = 510003 + INCOME_RANGE_70_80 = 510004 + INCOME_RANGE_80_90 = 510005 + INCOME_RANGE_90_UP = 510006 + INCOME_RANGE_UNDETERMINED = 510000 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/insights_knowledge_graph_entity_capabilities.py b/google/ads/googleads/v24/enums/types/insights_knowledge_graph_entity_capabilities.py new file mode 100644 index 000000000..08beb769c --- /dev/null +++ b/google/ads/googleads/v24/enums/types/insights_knowledge_graph_entity_capabilities.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "InsightsKnowledgeGraphEntityCapabilitiesEnum", + }, +) + + +class InsightsKnowledgeGraphEntityCapabilitiesEnum(proto.Message): + r"""Container for enum describing the capabilities of an entity + related to ContentCreatorInsightsService. + + """ + + class InsightsKnowledgeGraphEntityCapabilities(proto.Enum): + r"""The capabilities of an entity. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + CONTENT_TRENDING_INSIGHTS (2): + An entity that is supported to use as a trending topic in + [ContentCreatorInsightsService.GenerateTrendingInsights][google.ads.googleads.v24.services.ContentCreatorInsightsService.GenerateTrendingInsights]. + CREATOR_ATTRIBUTE (3): + An entity that is supported to use as a creator attribute in + [ContentCreatorInsightsService.GenerateCreatorInsights][google.ads.googleads.v24.services.ContentCreatorInsightsService.GenerateCreatorInsights]. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CONTENT_TRENDING_INSIGHTS = 2 + CREATOR_ATTRIBUTE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/insights_trend.py b/google/ads/googleads/v24/enums/types/insights_trend.py new file mode 100644 index 000000000..a27e81622 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/insights_trend.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "InsightsTrendEnum", + }, +) + + +class InsightsTrendEnum(proto.Message): + r"""Container for enum describing a trend.""" + + class InsightsTrend(proto.Enum): + r"""Describes which direction a trend is moving. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + EMERGING (2): + This is a new trend. + RISING (3): + This trend has increased recently. + SUSTAINED (4): + This trend has remained stable. + DECLINING (5): + This trend is declining. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EMERGING = 2 + RISING = 3 + SUSTAINED = 4 + DECLINING = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/interaction_event_type.py b/google/ads/googleads/v24/enums/types/interaction_event_type.py new file mode 100644 index 000000000..758a86351 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/interaction_event_type.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "InteractionEventTypeEnum", + }, +) + + +class InteractionEventTypeEnum(proto.Message): + r"""Container for enum describing types of payable and free + interactions. + + """ + + class InteractionEventType(proto.Enum): + r"""Enum describing possible types of payable and free + interactions. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CLICK (2): + Click to site. In most cases, this + interaction navigates to an external location, + usually the advertiser's landing page. This is + also the default InteractionEventType for click + events. + ENGAGEMENT (3): + The user's expressed intent to engage with + the ad in-place. + VIDEO_VIEW (4): + User viewed a video ad. + NONE (5): + The default InteractionEventType for ad + conversion events. This is used when an ad + conversion row does NOT indicate that the free + interactions (for example, the ad conversions) + should be 'promoted' and reported as part of the + core metrics. These are simply other (ad) + conversions. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CLICK = 2 + ENGAGEMENT = 3 + VIDEO_VIEW = 4 + NONE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/interaction_type.py b/google/ads/googleads/v24/enums/types/interaction_type.py new file mode 100644 index 000000000..358af9407 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/interaction_type.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "InteractionTypeEnum", + }, +) + + +class InteractionTypeEnum(proto.Message): + r"""Container for enum describing possible interaction types.""" + + class InteractionType(proto.Enum): + r"""Enum describing possible interaction types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CALLS (8000): + Calls. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CALLS = 8000 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/invoice_type.py b/google/ads/googleads/v24/enums/types/invoice_type.py new file mode 100644 index 000000000..354f20f6a --- /dev/null +++ b/google/ads/googleads/v24/enums/types/invoice_type.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "InvoiceTypeEnum", + }, +) + + +class InvoiceTypeEnum(proto.Message): + r"""Container for enum describing the type of invoices.""" + + class InvoiceType(proto.Enum): + r"""The possible type of invoices. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CREDIT_MEMO (2): + An invoice with a negative amount. The + account receives a credit. + INVOICE (3): + An invoice with a positive amount. The + account owes a balance. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CREDIT_MEMO = 2 + INVOICE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/keyword_match_type.py b/google/ads/googleads/v24/enums/types/keyword_match_type.py new file mode 100644 index 000000000..687878533 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/keyword_match_type.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordMatchTypeEnum", + }, +) + + +class KeywordMatchTypeEnum(proto.Message): + r"""Message describing Keyword match types.""" + + class KeywordMatchType(proto.Enum): + r"""Possible Keyword match types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + EXACT (2): + Exact match. + PHRASE (3): + Phrase match. + BROAD (4): + Broad match. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EXACT = 2 + PHRASE = 3 + BROAD = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/keyword_plan_aggregate_metric_type.py b/google/ads/googleads/v24/enums/types/keyword_plan_aggregate_metric_type.py new file mode 100644 index 000000000..ddb281387 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/keyword_plan_aggregate_metric_type.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanAggregateMetricTypeEnum", + }, +) + + +class KeywordPlanAggregateMetricTypeEnum(proto.Message): + r"""The enumeration of keyword plan aggregate metric types.""" + + class KeywordPlanAggregateMetricType(proto.Enum): + r"""Aggregate fields. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + DEVICE (2): + The device breakdown of aggregate search + volume. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DEVICE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/keyword_plan_competition_level.py b/google/ads/googleads/v24/enums/types/keyword_plan_competition_level.py new file mode 100644 index 000000000..1f39b9703 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/keyword_plan_competition_level.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanCompetitionLevelEnum", + }, +) + + +class KeywordPlanCompetitionLevelEnum(proto.Message): + r"""Container for enumeration of keyword competition levels. The + competition level indicates how competitive ad placement is for + a keyword and is determined by the number of advertisers bidding + on that keyword relative to all keywords across Google. The + competition level can depend on the location and Search Network + targeting options you've selected. + + """ + + class KeywordPlanCompetitionLevel(proto.Enum): + r"""Competition level of a keyword. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + LOW (2): + Low competition. The Competition Index range for this is [0, + 33]. + MEDIUM (3): + Medium competition. The Competition Index range for this is + [34, 66]. + HIGH (4): + High competition. The Competition Index range for this is + [67, 100]. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LOW = 2 + MEDIUM = 3 + HIGH = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/keyword_plan_concept_group_type.py b/google/ads/googleads/v24/enums/types/keyword_plan_concept_group_type.py new file mode 100644 index 000000000..b9d2cee09 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/keyword_plan_concept_group_type.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanConceptGroupTypeEnum", + }, +) + + +class KeywordPlanConceptGroupTypeEnum(proto.Message): + r"""Container for enumeration of keyword plan concept group + types. + + """ + + class KeywordPlanConceptGroupType(proto.Enum): + r"""Enumerates keyword plan concept group types. + + Values: + UNSPECIFIED (0): + The concept group classification different + from brand/non-brand. This is a catch all bucket + for all classifications that are none of the + below. + UNKNOWN (1): + The value is unknown in this version. + BRAND (2): + The concept group classification is based on + BRAND. + OTHER_BRANDS (3): + The concept group classification based on + BRAND, that didn't fit well with the BRAND + classifications. These are generally outliers + and can have very few keywords in this type of + classification. + NON_BRAND (4): + These concept group classification is not + based on BRAND. This is returned for generic + keywords that don't have a brand association. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BRAND = 2 + OTHER_BRANDS = 3 + NON_BRAND = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/keyword_plan_forecast_interval.py b/google/ads/googleads/v24/enums/types/keyword_plan_forecast_interval.py new file mode 100644 index 000000000..383a1ceeb --- /dev/null +++ b/google/ads/googleads/v24/enums/types/keyword_plan_forecast_interval.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanForecastIntervalEnum", + }, +) + + +class KeywordPlanForecastIntervalEnum(proto.Message): + r"""Container for enumeration of forecast intervals.""" + + class KeywordPlanForecastInterval(proto.Enum): + r"""Forecast intervals. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + NEXT_WEEK (3): + The next week date range for keyword plan. + The next week is based on the default locale of + the user's account and is mostly SUN-SAT or + MON-SUN. + This can be different from next-7 days. + NEXT_MONTH (4): + The next month date range for keyword plan. + NEXT_QUARTER (5): + The next quarter date range for keyword plan. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NEXT_WEEK = 3 + NEXT_MONTH = 4 + NEXT_QUARTER = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/keyword_plan_keyword_annotation.py b/google/ads/googleads/v24/enums/types/keyword_plan_keyword_annotation.py new file mode 100644 index 000000000..ad5238ffc --- /dev/null +++ b/google/ads/googleads/v24/enums/types/keyword_plan_keyword_annotation.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanKeywordAnnotationEnum", + }, +) + + +class KeywordPlanKeywordAnnotationEnum(proto.Message): + r"""Container for enumeration of keyword plan keyword + annotations. + + """ + + class KeywordPlanKeywordAnnotation(proto.Enum): + r"""Enumerates keyword plan annotations that can be requested. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + KEYWORD_CONCEPT (2): + Return the keyword concept and concept group + data. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + KEYWORD_CONCEPT = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/keyword_plan_network.py b/google/ads/googleads/v24/enums/types/keyword_plan_network.py new file mode 100644 index 000000000..bce1913e6 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/keyword_plan_network.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanNetworkEnum", + }, +) + + +class KeywordPlanNetworkEnum(proto.Message): + r"""Container for enumeration of keyword plan forecastable + network types. + + """ + + class KeywordPlanNetwork(proto.Enum): + r"""Enumerates keyword plan forecastable network types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + GOOGLE_SEARCH (2): + Google Search. + GOOGLE_SEARCH_AND_PARTNERS (3): + Google Search + Search partners. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + GOOGLE_SEARCH = 2 + GOOGLE_SEARCH_AND_PARTNERS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/label_status.py b/google/ads/googleads/v24/enums/types/label_status.py new file mode 100644 index 000000000..44abc0ec8 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/label_status.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LabelStatusEnum", + }, +) + + +class LabelStatusEnum(proto.Message): + r"""Container for enum describing possible status of a label.""" + + class LabelStatus(proto.Enum): + r"""Possible statuses of a label. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + Label is enabled. + REMOVED (3): + Label is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/landing_page_source.py b/google/ads/googleads/v24/enums/types/landing_page_source.py new file mode 100644 index 000000000..0145e9ae6 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/landing_page_source.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LandingPageSourceEnum", + }, +) + + +class LandingPageSourceEnum(proto.Message): + r"""Container for enum describing the source of a landing page in + the landing page report. + + """ + + class LandingPageSource(proto.Enum): + r"""The source of a landing page in the landing page report. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ADVERTISER (2): + The landing page was explicitly provided by + the advertiser. + AUTOMATIC (3): + The landing page was selected automatically. + This could happen when the advertiser enables AI + Max or other features that automatically select + landing pages and Google selects the best + landing page for the query. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ADVERTISER = 2 + AUTOMATIC = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/lead_form_call_to_action_type.py b/google/ads/googleads/v24/enums/types/lead_form_call_to_action_type.py new file mode 100644 index 000000000..edb7e3d5f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/lead_form_call_to_action_type.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LeadFormCallToActionTypeEnum", + }, +) + + +class LeadFormCallToActionTypeEnum(proto.Message): + r"""Describes the type of call-to-action phrases in a lead form.""" + + class LeadFormCallToActionType(proto.Enum): + r"""Enum describing the type of call-to-action phrases in a lead + form. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + LEARN_MORE (2): + Learn more. + GET_QUOTE (3): + Get quote. + APPLY_NOW (4): + Apply now. + SIGN_UP (5): + Sign Up. + CONTACT_US (6): + Contact us. + SUBSCRIBE (7): + Subscribe. + DOWNLOAD (8): + Download. + BOOK_NOW (9): + Book now. + GET_OFFER (10): + Get offer. + REGISTER (11): + Register. + GET_INFO (12): + Get info. + REQUEST_DEMO (13): + Request a demo. + JOIN_NOW (14): + Join now. + GET_STARTED (15): + Get started. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LEARN_MORE = 2 + GET_QUOTE = 3 + APPLY_NOW = 4 + SIGN_UP = 5 + CONTACT_US = 6 + SUBSCRIBE = 7 + DOWNLOAD = 8 + BOOK_NOW = 9 + GET_OFFER = 10 + REGISTER = 11 + GET_INFO = 12 + REQUEST_DEMO = 13 + JOIN_NOW = 14 + GET_STARTED = 15 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/lead_form_desired_intent.py b/google/ads/googleads/v24/enums/types/lead_form_desired_intent.py new file mode 100644 index 000000000..03533adbd --- /dev/null +++ b/google/ads/googleads/v24/enums/types/lead_form_desired_intent.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LeadFormDesiredIntentEnum", + }, +) + + +class LeadFormDesiredIntentEnum(proto.Message): + r"""Describes the chosen level of intent of generated leads.""" + + class LeadFormDesiredIntent(proto.Enum): + r"""Enum describing the chosen level of intent of generated + leads. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + LOW_INTENT (2): + Deliver more leads at a potentially lower + quality. + HIGH_INTENT (3): + Deliver leads that are more qualified. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LOW_INTENT = 2 + HIGH_INTENT = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/lead_form_field_user_input_type.py b/google/ads/googleads/v24/enums/types/lead_form_field_user_input_type.py new file mode 100644 index 000000000..196342c8a --- /dev/null +++ b/google/ads/googleads/v24/enums/types/lead_form_field_user_input_type.py @@ -0,0 +1,704 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LeadFormFieldUserInputTypeEnum", + }, +) + + +class LeadFormFieldUserInputTypeEnum(proto.Message): + r"""Describes the input type of a lead form field.""" + + class LeadFormFieldUserInputType(proto.Enum): + r"""Enum describing the input type of a lead form field. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + FULL_NAME (2): + The user will be asked to fill in their given and family + name. This field cannot be set at the same time as + GIVEN_NAME or FAMILY_NAME. + EMAIL (3): + The user will be asked to fill in their email + address. + PHONE_NUMBER (4): + The user will be asked to fill in their phone + number. + POSTAL_CODE (5): + The user will be asked to fill in their zip + code. + STREET_ADDRESS (8): + The user will be asked to fill in their + street address. + CITY (9): + The user will be asked to fill in their city. + REGION (10): + The user will be asked to fill in their + region part of the address (for example, state + for US, province for Canada). + COUNTRY (11): + The user will be asked to fill in their + country. + WORK_EMAIL (12): + The user will be asked to fill in their work + email address. + COMPANY_NAME (13): + The user will be asked to fill in their + company name. + WORK_PHONE (14): + The user will be asked to fill in their work + phone. + JOB_TITLE (15): + The user will be asked to fill in their job + title. + GOVERNMENT_ISSUED_ID_CPF_BR (16): + The user will be asked to fill in their CPF + for Brazil users. + GOVERNMENT_ISSUED_ID_DNI_AR (17): + The user will be asked to fill in their DNI + for Argentina users. + GOVERNMENT_ISSUED_ID_DNI_PE (18): + The user will be asked to fill in their DNI + for Peru users. + GOVERNMENT_ISSUED_ID_RUT_CL (19): + The user will be asked to fill in their RUT + for Chile users. + GOVERNMENT_ISSUED_ID_CC_CO (20): + The user will be asked to fill in their CC + for Colombia users. + GOVERNMENT_ISSUED_ID_CI_EC (21): + The user will be asked to fill in their CI + for Ecuador users. + GOVERNMENT_ISSUED_ID_RFC_MX (22): + The user will be asked to fill in their RFC + for Mexico users. + FIRST_NAME (23): + The user will be asked to fill in their first name. This + field can not be set at the same time as FULL_NAME. + LAST_NAME (24): + The user will be asked to fill in their last name. This + field can not be set at the same time as FULL_NAME. + VEHICLE_MODEL (1001): + Question: "Which model are you interested in?" Category: + "Auto" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + VEHICLE_TYPE (1002): + Question: "Which type of vehicle are you interested in?" + Category: "Auto" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + PREFERRED_DEALERSHIP (1003): + Question: "What is your preferred dealership?" Category: + "Auto" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + VEHICLE_PURCHASE_TIMELINE (1004): + Question: "When do you plan on purchasing a vehicle?" + Category: "Auto" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + VEHICLE_OWNERSHIP (1005): + Question: "Do you own a vehicle?" Category: "Auto" This + field is subject to a limit of 5 qualifying questions per + form and cannot be used if values are set using + custom_question_fields. + VEHICLE_PAYMENT_TYPE (1009): + Question: "What vehicle ownership option are you interested + in?" Category: "Auto" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + VEHICLE_CONDITION (1010): + Question: "What type of vehicle condition are you interested + in?" Category: "Auto" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + COMPANY_SIZE (1006): + Question: "What size is your company?" Category: "Business" + This field is subject to a limit of 5 qualifying questions + per form and cannot be used if values are set using + custom_question_fields. + ANNUAL_SALES (1007): + Question: "What is your annual sales volume?" Category: + "Business" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + YEARS_IN_BUSINESS (1008): + Question: "How many years have you been in business?" + Category: "Business" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + JOB_DEPARTMENT (1011): + Question: "What is your job department?" Category: + "Business" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + JOB_ROLE (1012): + Question: "What is your job role?" Category: "Business" This + field is subject to a limit of 5 qualifying questions per + form and cannot be used if values are set using + custom_question_fields. + OVER_18_AGE (1078): + Question: "Are you over 18 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_19_AGE (1079): + Question: "Are you over 19 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_20_AGE (1080): + Question: "Are you over 20 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_21_AGE (1081): + Question: "Are you over 21 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_22_AGE (1082): + Question: "Are you over 22 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_23_AGE (1083): + Question: "Are you over 23 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_24_AGE (1084): + Question: "Are you over 24 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_25_AGE (1085): + Question: "Are you over 25 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_26_AGE (1086): + Question: "Are you over 26 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_27_AGE (1087): + Question: "Are you over 27 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_28_AGE (1088): + Question: "Are you over 28 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_29_AGE (1089): + Question: "Are you over 29 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_30_AGE (1090): + Question: "Are you over 30 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_31_AGE (1091): + Question: "Are you over 31 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_32_AGE (1092): + Question: "Are you over 32 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_33_AGE (1093): + Question: "Are you over 33 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_34_AGE (1094): + Question: "Are you over 34 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_35_AGE (1095): + Question: "Are you over 35 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_36_AGE (1096): + Question: "Are you over 36 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_37_AGE (1097): + Question: "Are you over 37 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_38_AGE (1098): + Question: "Are you over 38 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_39_AGE (1099): + Question: "Are you over 39 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_40_AGE (1100): + Question: "Are you over 40 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_41_AGE (1101): + Question: "Are you over 41 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_42_AGE (1102): + Question: "Are you over 42 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_43_AGE (1103): + Question: "Are you over 43 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_44_AGE (1104): + Question: "Are you over 44 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_45_AGE (1105): + Question: "Are you over 45 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_46_AGE (1106): + Question: "Are you over 46 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_47_AGE (1107): + Question: "Are you over 47 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_48_AGE (1108): + Question: "Are you over 48 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_49_AGE (1109): + Question: "Are you over 49 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_50_AGE (1110): + Question: "Are you over 50 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_51_AGE (1111): + Question: "Are you over 51 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_52_AGE (1112): + Question: "Are you over 52 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_53_AGE (1113): + Question: "Are you over 53 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_54_AGE (1114): + Question: "Are you over 54 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_55_AGE (1115): + Question: "Are you over 55 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_56_AGE (1116): + Question: "Are you over 56 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_57_AGE (1117): + Question: "Are you over 57 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_58_AGE (1118): + Question: "Are you over 58 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_59_AGE (1119): + Question: "Are you over 59 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_60_AGE (1120): + Question: "Are you over 60 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_61_AGE (1121): + Question: "Are you over 61 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_62_AGE (1122): + Question: "Are you over 62 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_63_AGE (1123): + Question: "Are you over 63 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_64_AGE (1124): + Question: "Are you over 64 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + OVER_65_AGE (1125): + Question: "Are you over 65 years of age?" Category: + "Demographics" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + EDUCATION_PROGRAM (1013): + Question: "Which program are you interested in?" Category: + "Education" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + EDUCATION_COURSE (1014): + Question: "Which course are you interested in?" Category: + "Education" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + PRODUCT (1016): + Question: "Which product are you interested in?" Category: + "General" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + SERVICE (1017): + Question: "Which service are you interested in?" Category: + "General" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + OFFER (1018): + Question: "Which offer are you interested in?" Category: + "General" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + CATEGORY (1019): + Question: "Which category are you interested in?" Category: + "General" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + PREFERRED_CONTACT_METHOD (1020): + Question: "What is your preferred method of contact?" + Category: "General" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + PREFERRED_LOCATION (1021): + Question: "What is your preferred location?" Category: + "General" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + PREFERRED_CONTACT_TIME (1022): + Question: "What is the best time to contact you?" Category: + "General" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + PURCHASE_TIMELINE (1023): + Question: "When are you looking to make a purchase?" + Category: "General" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + YEARS_OF_EXPERIENCE (1048): + Question: "How many years of work experience do you have?" + Category: "Jobs" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + JOB_INDUSTRY (1049): + Question: "What industry do you work in?" Category: "Jobs" + This field is subject to a limit of 5 qualifying questions + per form and cannot be used if values are set using + custom_question_fields. + LEVEL_OF_EDUCATION (1050): + Question: "What is your highest level of education?" + Category: "Jobs" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + PROPERTY_TYPE (1024): + Question: "What type of property are you looking for?" + Category: "Real Estate" This field is subject to a limit of + 5 qualifying questions per form and cannot be used if values + are set using custom_question_fields. + REALTOR_HELP_GOAL (1025): + Question: "What do you need a realtor's help with?" + Category: "Real Estate" This field is subject to a limit of + 5 qualifying questions per form and cannot be used if values + are set using custom_question_fields. + PROPERTY_COMMUNITY (1026): + Question: "What neighborhood are you interested in?" + Category: "Real Estate" This field is subject to a limit of + 5 qualifying questions per form and cannot be used if values + are set using custom_question_fields. + PRICE_RANGE (1027): + Question: "What price range are you looking for?" Category: + "Real Estate" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + NUMBER_OF_BEDROOMS (1028): + Question: "How many bedrooms are you looking for?" Category: + "Real Estate" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + FURNISHED_PROPERTY (1029): + Question: "Are you looking for a fully furnished property?" + Category: "Real Estate" This field is subject to a limit of + 5 qualifying questions per form and cannot be used if values + are set using custom_question_fields. + PETS_ALLOWED_PROPERTY (1030): + Question: "Are you looking for properties that allow pets?" + Category: "Real Estate" This field is subject to a limit of + 5 qualifying questions per form and cannot be used if values + are set using custom_question_fields. + NEXT_PLANNED_PURCHASE (1031): + Question: "What is the next product you plan to purchase?" + Category: "Retail" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + EVENT_SIGNUP_INTEREST (1033): + Question: "Would you like to sign up for an event?" + Category: "Retail" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + PREFERRED_SHOPPING_PLACES (1034): + Question: "Where are you interested in shopping?" Category: + "Retail" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + FAVORITE_BRAND (1035): + Question: "What is your favorite brand?" Category: "Retail" + This field is subject to a limit of 5 qualifying questions + per form and cannot be used if values are set using + custom_question_fields. + TRANSPORTATION_COMMERCIAL_LICENSE_TYPE (1036): + Question: "Which type of valid commercial license do you + have?" Category: "Transportation" This field is subject to a + limit of 5 qualifying questions per form and cannot be used + if values are set using custom_question_fields. + EVENT_BOOKING_INTEREST (1038): + Question: "Interested in booking an event?" Category: + "Travel" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + DESTINATION_COUNTRY (1039): + Question: "What is your destination country?" Category: + "Travel" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + DESTINATION_CITY (1040): + Question: "What is your destination city?" Category: + "Travel" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + DEPARTURE_COUNTRY (1041): + Question: "What is your departure country?" Category: + "Travel" This field is subject to a limit of 5 qualifying + questions per form and cannot be used if values are set + using custom_question_fields. + DEPARTURE_CITY (1042): + Question: "What is your departure city?" Category: "Travel" + This field is subject to a limit of 5 qualifying questions + per form and cannot be used if values are set using + custom_question_fields. + DEPARTURE_DATE (1043): + Question: "What is your departure date?" Category: "Travel" + This field is subject to a limit of 5 qualifying questions + per form and cannot be used if values are set using + custom_question_fields. + RETURN_DATE (1044): + Question: "What is your return date?" Category: "Travel" + This field is subject to a limit of 5 qualifying questions + per form and cannot be used if values are set using + custom_question_fields. + NUMBER_OF_TRAVELERS (1045): + Question: "How many people are you traveling with?" + Category: "Travel" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + TRAVEL_BUDGET (1046): + Question: "What is your travel budget?" Category: "Travel" + This field is subject to a limit of 5 qualifying questions + per form and cannot be used if values are set using + custom_question_fields. + TRAVEL_ACCOMMODATION (1047): + Question: "Where do you want to stay during your travel?" + Category: "Travel" This field is subject to a limit of 5 + qualifying questions per form and cannot be used if values + are set using custom_question_fields. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + FULL_NAME = 2 + EMAIL = 3 + PHONE_NUMBER = 4 + POSTAL_CODE = 5 + STREET_ADDRESS = 8 + CITY = 9 + REGION = 10 + COUNTRY = 11 + WORK_EMAIL = 12 + COMPANY_NAME = 13 + WORK_PHONE = 14 + JOB_TITLE = 15 + GOVERNMENT_ISSUED_ID_CPF_BR = 16 + GOVERNMENT_ISSUED_ID_DNI_AR = 17 + GOVERNMENT_ISSUED_ID_DNI_PE = 18 + GOVERNMENT_ISSUED_ID_RUT_CL = 19 + GOVERNMENT_ISSUED_ID_CC_CO = 20 + GOVERNMENT_ISSUED_ID_CI_EC = 21 + GOVERNMENT_ISSUED_ID_RFC_MX = 22 + FIRST_NAME = 23 + LAST_NAME = 24 + VEHICLE_MODEL = 1001 + VEHICLE_TYPE = 1002 + PREFERRED_DEALERSHIP = 1003 + VEHICLE_PURCHASE_TIMELINE = 1004 + VEHICLE_OWNERSHIP = 1005 + VEHICLE_PAYMENT_TYPE = 1009 + VEHICLE_CONDITION = 1010 + COMPANY_SIZE = 1006 + ANNUAL_SALES = 1007 + YEARS_IN_BUSINESS = 1008 + JOB_DEPARTMENT = 1011 + JOB_ROLE = 1012 + OVER_18_AGE = 1078 + OVER_19_AGE = 1079 + OVER_20_AGE = 1080 + OVER_21_AGE = 1081 + OVER_22_AGE = 1082 + OVER_23_AGE = 1083 + OVER_24_AGE = 1084 + OVER_25_AGE = 1085 + OVER_26_AGE = 1086 + OVER_27_AGE = 1087 + OVER_28_AGE = 1088 + OVER_29_AGE = 1089 + OVER_30_AGE = 1090 + OVER_31_AGE = 1091 + OVER_32_AGE = 1092 + OVER_33_AGE = 1093 + OVER_34_AGE = 1094 + OVER_35_AGE = 1095 + OVER_36_AGE = 1096 + OVER_37_AGE = 1097 + OVER_38_AGE = 1098 + OVER_39_AGE = 1099 + OVER_40_AGE = 1100 + OVER_41_AGE = 1101 + OVER_42_AGE = 1102 + OVER_43_AGE = 1103 + OVER_44_AGE = 1104 + OVER_45_AGE = 1105 + OVER_46_AGE = 1106 + OVER_47_AGE = 1107 + OVER_48_AGE = 1108 + OVER_49_AGE = 1109 + OVER_50_AGE = 1110 + OVER_51_AGE = 1111 + OVER_52_AGE = 1112 + OVER_53_AGE = 1113 + OVER_54_AGE = 1114 + OVER_55_AGE = 1115 + OVER_56_AGE = 1116 + OVER_57_AGE = 1117 + OVER_58_AGE = 1118 + OVER_59_AGE = 1119 + OVER_60_AGE = 1120 + OVER_61_AGE = 1121 + OVER_62_AGE = 1122 + OVER_63_AGE = 1123 + OVER_64_AGE = 1124 + OVER_65_AGE = 1125 + EDUCATION_PROGRAM = 1013 + EDUCATION_COURSE = 1014 + PRODUCT = 1016 + SERVICE = 1017 + OFFER = 1018 + CATEGORY = 1019 + PREFERRED_CONTACT_METHOD = 1020 + PREFERRED_LOCATION = 1021 + PREFERRED_CONTACT_TIME = 1022 + PURCHASE_TIMELINE = 1023 + YEARS_OF_EXPERIENCE = 1048 + JOB_INDUSTRY = 1049 + LEVEL_OF_EDUCATION = 1050 + PROPERTY_TYPE = 1024 + REALTOR_HELP_GOAL = 1025 + PROPERTY_COMMUNITY = 1026 + PRICE_RANGE = 1027 + NUMBER_OF_BEDROOMS = 1028 + FURNISHED_PROPERTY = 1029 + PETS_ALLOWED_PROPERTY = 1030 + NEXT_PLANNED_PURCHASE = 1031 + EVENT_SIGNUP_INTEREST = 1033 + PREFERRED_SHOPPING_PLACES = 1034 + FAVORITE_BRAND = 1035 + TRANSPORTATION_COMMERCIAL_LICENSE_TYPE = 1036 + EVENT_BOOKING_INTEREST = 1038 + DESTINATION_COUNTRY = 1039 + DESTINATION_CITY = 1040 + DEPARTURE_COUNTRY = 1041 + DEPARTURE_CITY = 1042 + DEPARTURE_DATE = 1043 + RETURN_DATE = 1044 + NUMBER_OF_TRAVELERS = 1045 + TRAVEL_BUDGET = 1046 + TRAVEL_ACCOMMODATION = 1047 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/lead_form_post_submit_call_to_action_type.py b/google/ads/googleads/v24/enums/types/lead_form_post_submit_call_to_action_type.py new file mode 100644 index 000000000..bc77ae0e9 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/lead_form_post_submit_call_to_action_type.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LeadFormPostSubmitCallToActionTypeEnum", + }, +) + + +class LeadFormPostSubmitCallToActionTypeEnum(proto.Message): + r"""Describes the type of post-submit call-to-action phrases for + a lead form. + + """ + + class LeadFormPostSubmitCallToActionType(proto.Enum): + r"""Enum describing the type of post-submit call-to-action + phrases for a lead form. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + VISIT_SITE (2): + Visit site. + DOWNLOAD (3): + Download. + LEARN_MORE (4): + Learn more. + SHOP_NOW (5): + Shop now. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + VISIT_SITE = 2 + DOWNLOAD = 3 + LEARN_MORE = 4 + SHOP_NOW = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/legacy_app_install_ad_app_store.py b/google/ads/googleads/v24/enums/types/legacy_app_install_ad_app_store.py new file mode 100644 index 000000000..37e579545 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/legacy_app_install_ad_app_store.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LegacyAppInstallAdAppStoreEnum", + }, +) + + +class LegacyAppInstallAdAppStoreEnum(proto.Message): + r"""Container for enum describing app store type in a legacy app + install ad. + + """ + + class LegacyAppInstallAdAppStore(proto.Enum): + r"""App store type in a legacy app install ad. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + APPLE_APP_STORE (2): + Apple iTunes. + GOOGLE_PLAY (3): + Google Play. + WINDOWS_STORE (4): + Windows Store. + WINDOWS_PHONE_STORE (5): + Windows Phone Store. + CN_APP_STORE (6): + The app is hosted in a Chinese app store. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + APPLE_APP_STORE = 2 + GOOGLE_PLAY = 3 + WINDOWS_STORE = 4 + WINDOWS_PHONE_STORE = 5 + CN_APP_STORE = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/linked_account_type.py b/google/ads/googleads/v24/enums/types/linked_account_type.py new file mode 100644 index 000000000..cfb788eee --- /dev/null +++ b/google/ads/googleads/v24/enums/types/linked_account_type.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LinkedAccountTypeEnum", + }, +) + + +class LinkedAccountTypeEnum(proto.Message): + r"""Container for enum describing different types of Linked + accounts. + + """ + + class LinkedAccountType(proto.Enum): + r"""Describes the possible link types between a Google Ads + customer and another account. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + THIRD_PARTY_APP_ANALYTICS (2): + A link to provide third party app analytics + data. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + THIRD_PARTY_APP_ANALYTICS = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/linked_product_type.py b/google/ads/googleads/v24/enums/types/linked_product_type.py new file mode 100644 index 000000000..15d1c6d27 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/linked_product_type.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LinkedProductTypeEnum", + }, +) + + +class LinkedProductTypeEnum(proto.Message): + r"""Container for enum describing different types of linked + products. + + """ + + class LinkedProductType(proto.Enum): + r"""Describes the possible link types for a link between a Google + Ads customer and another product. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + DATA_PARTNER (2): + A link to Data partner. + GOOGLE_ADS (3): + A link to Google Ads. + HOTEL_CENTER (7): + A link to Hotel Center. + MERCHANT_CENTER (8): + A link to Google Merchant Center. + ADVERTISING_PARTNER (9): + A link to the Google Ads account of the + advertising partner. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DATA_PARTNER = 2 + GOOGLE_ADS = 3 + HOTEL_CENTER = 7 + MERCHANT_CENTER = 8 + ADVERTISING_PARTNER = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/listing_group_filter_custom_attribute_index.py b/google/ads/googleads/v24/enums/types/listing_group_filter_custom_attribute_index.py new file mode 100644 index 000000000..c80c6d2ef --- /dev/null +++ b/google/ads/googleads/v24/enums/types/listing_group_filter_custom_attribute_index.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ListingGroupFilterCustomAttributeIndexEnum", + }, +) + + +class ListingGroupFilterCustomAttributeIndexEnum(proto.Message): + r"""Container for enum describing the indexes of custom attribute + used in ListingGroupFilterDimension. + + """ + + class ListingGroupFilterCustomAttributeIndex(proto.Enum): + r"""The index of customer attributes. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + INDEX0 (2): + First listing group filter custom attribute. + INDEX1 (3): + Second listing group filter custom attribute. + INDEX2 (4): + Third listing group filter custom attribute. + INDEX3 (5): + Fourth listing group filter custom attribute. + INDEX4 (6): + Fifth listing group filter custom attribute. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INDEX0 = 2 + INDEX1 = 3 + INDEX2 = 4 + INDEX3 = 5 + INDEX4 = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/listing_group_filter_listing_source.py b/google/ads/googleads/v24/enums/types/listing_group_filter_listing_source.py new file mode 100644 index 000000000..19c87e270 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/listing_group_filter_listing_source.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ListingGroupFilterListingSourceEnum", + }, +) + + +class ListingGroupFilterListingSourceEnum(proto.Message): + r"""Container for enum describing the source of listings filtered + by a listing group filter node. + + """ + + class ListingGroupFilterListingSource(proto.Enum): + r"""The source of listings filtered by a listing group filter + node. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + SHOPPING (2): + Listings from a Shopping source, like + products from Google Merchant Center. + WEBPAGE (3): + Listings from a webpage source, like URLs + from a page feed or from the advertiser web + domain. + RETAIL (4): + Used for Retail Product Tags. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SHOPPING = 2 + WEBPAGE = 3 + RETAIL = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/listing_group_filter_product_category_level.py b/google/ads/googleads/v24/enums/types/listing_group_filter_product_category_level.py new file mode 100644 index 000000000..1e494e572 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/listing_group_filter_product_category_level.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ListingGroupFilterProductCategoryLevelEnum", + }, +) + + +class ListingGroupFilterProductCategoryLevelEnum(proto.Message): + r"""Container for enum describing the levels of product category + used in ListingGroupFilterDimension. + + """ + + class ListingGroupFilterProductCategoryLevel(proto.Enum): + r"""The level of the listing group filter product category. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + LEVEL1 (2): + Level 1. + LEVEL2 (3): + Level 2. + LEVEL3 (4): + Level 3. + LEVEL4 (5): + Level 4. + LEVEL5 (6): + Level 5. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LEVEL1 = 2 + LEVEL2 = 3 + LEVEL3 = 4 + LEVEL4 = 5 + LEVEL5 = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/listing_group_filter_product_channel.py b/google/ads/googleads/v24/enums/types/listing_group_filter_product_channel.py new file mode 100644 index 000000000..cc09603a2 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/listing_group_filter_product_channel.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ListingGroupFilterProductChannelEnum", + }, +) + + +class ListingGroupFilterProductChannelEnum(proto.Message): + r"""Locality of a product offer.""" + + class ListingGroupFilterProductChannel(proto.Enum): + r"""Enum describing the locality of a product offer. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ONLINE (2): + The item is sold online. + LOCAL (3): + The item is sold in local stores. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ONLINE = 2 + LOCAL = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/listing_group_filter_product_condition.py b/google/ads/googleads/v24/enums/types/listing_group_filter_product_condition.py new file mode 100644 index 000000000..ec0e9600c --- /dev/null +++ b/google/ads/googleads/v24/enums/types/listing_group_filter_product_condition.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ListingGroupFilterProductConditionEnum", + }, +) + + +class ListingGroupFilterProductConditionEnum(proto.Message): + r"""Condition of a product offer.""" + + class ListingGroupFilterProductCondition(proto.Enum): + r"""Enum describing the condition of a product offer. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + NEW (2): + The product condition is new. + REFURBISHED (3): + The product condition is refurbished. + USED (4): + The product condition is used. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NEW = 2 + REFURBISHED = 3 + USED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/listing_group_filter_product_type_level.py b/google/ads/googleads/v24/enums/types/listing_group_filter_product_type_level.py new file mode 100644 index 000000000..a3ce3efb0 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/listing_group_filter_product_type_level.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ListingGroupFilterProductTypeLevelEnum", + }, +) + + +class ListingGroupFilterProductTypeLevelEnum(proto.Message): + r"""Level of the type of a product offer.""" + + class ListingGroupFilterProductTypeLevel(proto.Enum): + r"""Enum describing the level of the type of a product offer. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + LEVEL1 (2): + Level 1. + LEVEL2 (3): + Level 2. + LEVEL3 (4): + Level 3. + LEVEL4 (5): + Level 4. + LEVEL5 (6): + Level 5. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LEVEL1 = 2 + LEVEL2 = 3 + LEVEL3 = 4 + LEVEL4 = 5 + LEVEL5 = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/listing_group_filter_type_enum.py b/google/ads/googleads/v24/enums/types/listing_group_filter_type_enum.py new file mode 100644 index 000000000..6a0d70949 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/listing_group_filter_type_enum.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ListingGroupFilterTypeEnum", + }, +) + + +class ListingGroupFilterTypeEnum(proto.Message): + r"""Container for enum describing the type of the listing group + filter node. + + """ + + class ListingGroupFilterType(proto.Enum): + r"""The type of the listing group filter. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + SUBDIVISION (2): + Subdivision of products along some listing + dimensions. + UNIT_INCLUDED (3): + An included listing group filter leaf node. + UNIT_EXCLUDED (4): + An excluded listing group filter leaf node. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SUBDIVISION = 2 + UNIT_INCLUDED = 3 + UNIT_EXCLUDED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/listing_group_type.py b/google/ads/googleads/v24/enums/types/listing_group_type.py new file mode 100644 index 000000000..c7501eb6d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/listing_group_type.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ListingGroupTypeEnum", + }, +) + + +class ListingGroupTypeEnum(proto.Message): + r"""Container for enum describing the type of the listing group.""" + + class ListingGroupType(proto.Enum): + r"""The type of the listing group. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + SUBDIVISION (2): + Subdivision of products along some listing + dimension. These nodes are not used by serving + to target listing entries, but is purely to + define the structure of the tree. + UNIT (3): + Listing group unit that defines a bid. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SUBDIVISION = 2 + UNIT = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/listing_type.py b/google/ads/googleads/v24/enums/types/listing_type.py new file mode 100644 index 000000000..7c49156a3 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/listing_type.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ListingTypeEnum", + }, +) + + +class ListingTypeEnum(proto.Message): + r"""Container for enum describing possible listing types.""" + + class ListingType(proto.Enum): + r"""Possible listing types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + VEHICLES (2): + This campaign serves vehicle ads. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + VEHICLES = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_business_registration_check_rejection_reason.py b/google/ads/googleads/v24/enums/types/local_services_business_registration_check_rejection_reason.py new file mode 100644 index 000000000..da5086683 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_business_registration_check_rejection_reason.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesBusinessRegistrationCheckRejectionReasonEnum", + }, +) + + +class LocalServicesBusinessRegistrationCheckRejectionReasonEnum(proto.Message): + r"""Container for enum describing the rejection reason of a local + services business registration check verification artifact. + + """ + + class LocalServicesBusinessRegistrationCheckRejectionReason(proto.Enum): + r"""Enums describing possible rejection reasons of a local + services business registration check verification artifact. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BUSINESS_NAME_MISMATCH (2): + Business name doesn't match business name for + the Local Services Ad. + BUSINESS_DETAILS_MISMATCH (3): + Business details mismatch. + ID_NOT_FOUND (4): + Business registration ID not found. + POOR_DOCUMENT_IMAGE_QUALITY (5): + Uploaded document not clear, blurry, etc. + DOCUMENT_EXPIRED (6): + Uploaded document has expired. + DOCUMENT_INVALID (7): + Document revoked or annuled. + DOCUMENT_TYPE_MISMATCH (8): + Document type mismatch. + DOCUMENT_UNVERIFIABLE (9): + Uploaded document could not be verified as + legitimate. + OTHER (10): + The business registration process could not + be completed due to an issue. Contact + https://support.google.com/localservices to + learn more. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BUSINESS_NAME_MISMATCH = 2 + BUSINESS_DETAILS_MISMATCH = 3 + ID_NOT_FOUND = 4 + POOR_DOCUMENT_IMAGE_QUALITY = 5 + DOCUMENT_EXPIRED = 6 + DOCUMENT_INVALID = 7 + DOCUMENT_TYPE_MISMATCH = 8 + DOCUMENT_UNVERIFIABLE = 9 + OTHER = 10 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_business_registration_type.py b/google/ads/googleads/v24/enums/types/local_services_business_registration_type.py new file mode 100644 index 000000000..961de7a6e --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_business_registration_type.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesBusinessRegistrationTypeEnum", + }, +) + + +class LocalServicesBusinessRegistrationTypeEnum(proto.Message): + r"""Container for enum describing the type of business + registration check verification artifact. + + """ + + class LocalServicesBusinessRegistrationType(proto.Enum): + r"""Enums describing possible registration types of a local + services business registration check verification artifact. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + NUMBER (2): + Registration number check type. + DOCUMENT (3): + Registration document check type. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NUMBER = 2 + DOCUMENT = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_conversation_type.py b/google/ads/googleads/v24/enums/types/local_services_conversation_type.py new file mode 100644 index 000000000..e9dd4a1ae --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_conversation_type.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesLeadConversationTypeEnum", + }, +) + + +class LocalServicesLeadConversationTypeEnum(proto.Message): + r"""Container for enum describing possible types of lead + conversation. + + """ + + class ConversationType(proto.Enum): + r"""Possible types of lead conversation. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + EMAIL (2): + Email lead conversation. + MESSAGE (3): + Message lead conversation. + PHONE_CALL (4): + Phone call lead conversation. + SMS (5): + SMS lead conversation. + BOOKING (6): + Booking lead conversation. + WHATSAPP (7): + WhatsApp lead conversation. + ADS_API (8): + Lead conversation created through Google Ads + API. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EMAIL = 2 + MESSAGE = 3 + PHONE_CALL = 4 + SMS = 5 + BOOKING = 6 + WHATSAPP = 7 + ADS_API = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_employee_status.py b/google/ads/googleads/v24/enums/types/local_services_employee_status.py new file mode 100644 index 000000000..79d38a6d5 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_employee_status.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesEmployeeStatusEnum", + }, +) + + +class LocalServicesEmployeeStatusEnum(proto.Message): + r"""Container for enum describing the status of local services + employee. + + """ + + class LocalServicesEmployeeStatus(proto.Enum): + r"""Enums describing statuses of a local services employee. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + Employee is not removed, and employee status + is active. + REMOVED (3): + Employee is removed. Used to delete an + employee from the business. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_employee_type.py b/google/ads/googleads/v24/enums/types/local_services_employee_type.py new file mode 100644 index 000000000..1a533394b --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_employee_type.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesEmployeeTypeEnum", + }, +) + + +class LocalServicesEmployeeTypeEnum(proto.Message): + r"""Container for enum describing the types of local services + employee. + + """ + + class LocalServicesEmployeeType(proto.Enum): + r"""Enums describing types of a local services employee. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BUSINESS_OWNER (2): + Represents the owner of the business. + EMPLOYEE (3): + Represents an employee of the business. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BUSINESS_OWNER = 2 + EMPLOYEE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_insurance_rejection_reason.py b/google/ads/googleads/v24/enums/types/local_services_insurance_rejection_reason.py new file mode 100644 index 000000000..97302401b --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_insurance_rejection_reason.py @@ -0,0 +1,107 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesInsuranceRejectionReasonEnum", + }, +) + + +class LocalServicesInsuranceRejectionReasonEnum(proto.Message): + r"""Container for enum describing the rejection reason of a local + services insurance verification artifact. + + """ + + class LocalServicesInsuranceRejectionReason(proto.Enum): + r"""Enums describing possible rejection reasons of a local + services insurance verification artifact. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BUSINESS_NAME_MISMATCH (2): + Business name doesn't match business name for + the Local Services Ad. + INSURANCE_AMOUNT_INSUFFICIENT (3): + Insurance amount doesn't meet requirement + listed in the legal summaries documentation for + that geographic + category ID combination. + EXPIRED (4): + Insurance document is expired. + NO_SIGNATURE (5): + Insurance document is missing a signature. + NO_POLICY_NUMBER (6): + Insurance document is missing a policy + number. + NO_COMMERCIAL_GENERAL_LIABILITY (7): + Commercial General Liability(CGL) box is not + marked in the insurance document. + EDITABLE_FORMAT (8): + Insurance document is in an editable format. + CATEGORY_MISMATCH (9): + Insurance document does not cover insurance + for a particular category. + MISSING_EXPIRATION_DATE (10): + Insurance document is missing an expiration + date. + POOR_QUALITY (11): + Insurance document is poor quality - blurry + images, illegible, etc... + POTENTIALLY_EDITED (12): + Insurance document is suspected of being + edited. + WRONG_DOCUMENT_TYPE (13): + Insurance document not accepted. For example, + documents of insurance proposals, but missing + coverages are not accepted. + NON_FINAL (14): + Insurance document is not final. + OTHER (15): + Insurance document has another flaw not + listed explicitly. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BUSINESS_NAME_MISMATCH = 2 + INSURANCE_AMOUNT_INSUFFICIENT = 3 + EXPIRED = 4 + NO_SIGNATURE = 5 + NO_POLICY_NUMBER = 6 + NO_COMMERCIAL_GENERAL_LIABILITY = 7 + EDITABLE_FORMAT = 8 + CATEGORY_MISMATCH = 9 + MISSING_EXPIRATION_DATE = 10 + POOR_QUALITY = 11 + POTENTIALLY_EDITED = 12 + WRONG_DOCUMENT_TYPE = 13 + NON_FINAL = 14 + OTHER = 15 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_lead_credit_issuance_decision.py b/google/ads/googleads/v24/enums/types/local_services_lead_credit_issuance_decision.py new file mode 100644 index 000000000..3f8ec06d4 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_lead_credit_issuance_decision.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesLeadCreditIssuanceDecisionEnum", + }, +) + + +class LocalServicesLeadCreditIssuanceDecisionEnum(proto.Message): + r"""Container for enum describing possible credit issuance + decisions for a lead. + + """ + + class CreditIssuanceDecision(proto.Enum): + r"""Decision of bonus credit issued or rejected. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + SUCCESS_NOT_REACHED_THRESHOLD (2): + Bonus credit is issued successfully and bonus + credit cap has not reached the threshold after + issuing this bonus credit. + SUCCESS_REACHED_THRESHOLD (3): + Bonus credit is issued successfully and bonus + credit cap has reached the threshold after + issuing this bonus credit. + FAIL_OVER_THRESHOLD (4): + Bonus credit is not issued because the + provider has reached the bonus credit cap. + FAIL_NOT_ELIGIBLE (5): + Bonus credit is not issued because this lead + is not eligible for bonus credit. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SUCCESS_NOT_REACHED_THRESHOLD = 2 + SUCCESS_REACHED_THRESHOLD = 3 + FAIL_OVER_THRESHOLD = 4 + FAIL_NOT_ELIGIBLE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_lead_credit_state.py b/google/ads/googleads/v24/enums/types/local_services_lead_credit_state.py new file mode 100644 index 000000000..1c6ae8449 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_lead_credit_state.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesCreditStateEnum", + }, +) + + +class LocalServicesCreditStateEnum(proto.Message): + r"""Container for enum describing possible credit states of a + lead. + + """ + + class CreditState(proto.Enum): + r"""Possible credit states of a lead. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PENDING (2): + A credit has been filed and is being + processed by Ads backend, but has not been + applied to the account yet. + CREDITED (3): + The credit has been issued to the Ads + account. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + CREDITED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_lead_status.py b/google/ads/googleads/v24/enums/types/local_services_lead_status.py new file mode 100644 index 000000000..4ecb27049 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_lead_status.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesLeadStatusEnum", + }, +) + + +class LocalServicesLeadStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of lead.""" + + class LeadStatus(proto.Enum): + r"""Possible statuses of lead. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + NEW (2): + New lead which hasn't yet been seen by + advertiser. + ACTIVE (3): + Lead that thas been interacted by advertiser. + BOOKED (4): + Lead has been booked. + DECLINED (5): + Lead was declined by advertiser. + EXPIRED (6): + Lead has expired due to inactivity. + DISABLED (7): + Disabled due to spam or dispute. + CONSUMER_DECLINED (8): + Consumer declined the lead. + WIPED_OUT (9): + Personally Identifiable Information of the + lead is wiped out. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NEW = 2 + ACTIVE = 3 + BOOKED = 4 + DECLINED = 5 + EXPIRED = 6 + DISABLED = 7 + CONSUMER_DECLINED = 8 + WIPED_OUT = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_lead_survey_answer.py b/google/ads/googleads/v24/enums/types/local_services_lead_survey_answer.py new file mode 100644 index 000000000..5da15c7ed --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_lead_survey_answer.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesLeadSurveyAnswerEnum", + }, +) + + +class LocalServicesLeadSurveyAnswerEnum(proto.Message): + r"""Container for enum describing possible survey answers for a + lead. + + """ + + class SurveyAnswer(proto.Enum): + r"""Survey answer for Local Services Ads Lead. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + VERY_SATISFIED (2): + Very satisfied with the lead. + SATISFIED (3): + Satisfied with the lead. + NEUTRAL (4): + Neutral with the lead. + DISSATISFIED (5): + Dissatisfied with the lead. + VERY_DISSATISFIED (6): + Very dissatisfied with the lead. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + VERY_SATISFIED = 2 + SATISFIED = 3 + NEUTRAL = 4 + DISSATISFIED = 5 + VERY_DISSATISFIED = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_lead_survey_dissatisfied_reason.py b/google/ads/googleads/v24/enums/types/local_services_lead_survey_dissatisfied_reason.py new file mode 100644 index 000000000..ec11e44d7 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_lead_survey_dissatisfied_reason.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesLeadSurveyDissatisfiedReasonEnum", + }, +) + + +class LocalServicesLeadSurveyDissatisfiedReasonEnum(proto.Message): + r"""Container for enum describing possible survey dissatisfied + reasons for a lead. + + """ + + class SurveyDissatisfiedReason(proto.Enum): + r"""Provider's reason for not being satisfied with the lead. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + OTHER_DISSATISFIED_REASON (2): + Other reasons. + GEO_MISMATCH (3): + Lead was for a service that does not match + the business' service area. + JOB_TYPE_MISMATCH (4): + Lead was for a service that is not offered by + the business. + NOT_READY_TO_BOOK (5): + Lead was by a customer that was not ready to + book. + SPAM (6): + Lead was a spam. Example: lead was from a + bot, silent called, scam, etc. + DUPLICATE (7): + Lead was a duplicate of another lead that is, + customer contacted the business more than once. + SOLICITATION (8): + Lead due to solicitation. Example: a person + trying to get a job or selling a product, etc. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + OTHER_DISSATISFIED_REASON = 2 + GEO_MISMATCH = 3 + JOB_TYPE_MISMATCH = 4 + NOT_READY_TO_BOOK = 5 + SPAM = 6 + DUPLICATE = 7 + SOLICITATION = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_lead_survey_satisfied_reason.py b/google/ads/googleads/v24/enums/types/local_services_lead_survey_satisfied_reason.py new file mode 100644 index 000000000..3fd2057f6 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_lead_survey_satisfied_reason.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesLeadSurveySatisfiedReasonEnum", + }, +) + + +class LocalServicesLeadSurveySatisfiedReasonEnum(proto.Message): + r"""Container for enum describing possible survey satisfied + reasons for a lead. + + """ + + class SurveySatisfiedReason(proto.Enum): + r"""Provider's reason for being satisfied with the lead. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + OTHER_SATISFIED_REASON (2): + Other reasons. + BOOKED_CUSTOMER (3): + Lead converted into a booked customer or + client. + LIKELY_BOOKED_CUSTOMER (4): + Lead could convert into a booked customer or + client soon. + SERVICE_RELATED (5): + Lead was related to the services the business + offers. + HIGH_VALUE_SERVICE (6): + Lead was for a service that generates high + value for the business. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + OTHER_SATISFIED_REASON = 2 + BOOKED_CUSTOMER = 3 + LIKELY_BOOKED_CUSTOMER = 4 + SERVICE_RELATED = 5 + HIGH_VALUE_SERVICE = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_lead_type.py b/google/ads/googleads/v24/enums/types/local_services_lead_type.py new file mode 100644 index 000000000..06872d505 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_lead_type.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesLeadTypeEnum", + }, +) + + +class LocalServicesLeadTypeEnum(proto.Message): + r"""Container for enum describing possible types of lead.""" + + class LeadType(proto.Enum): + r"""Possible types of lead. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + MESSAGE (2): + Message lead. + PHONE_CALL (3): + Lead created by phone call. + BOOKING (4): + Booking lead. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MESSAGE = 2 + PHONE_CALL = 3 + BOOKING = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_license_rejection_reason.py b/google/ads/googleads/v24/enums/types/local_services_license_rejection_reason.py new file mode 100644 index 000000000..91e648409 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_license_rejection_reason.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesLicenseRejectionReasonEnum", + }, +) + + +class LocalServicesLicenseRejectionReasonEnum(proto.Message): + r"""Container for enum describing the rejection reason of a local + services license verification artifact. + + """ + + class LocalServicesLicenseRejectionReason(proto.Enum): + r"""Enums describing possible rejection reasons of a local + services license verification artifact. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BUSINESS_NAME_MISMATCH (2): + Business name doesn't match business name for + the Local Services Ad. + UNAUTHORIZED (3): + License is unauthorized or been revoked. + EXPIRED (4): + License is expired. + POOR_QUALITY (5): + License is poor quality - blurry images, + illegible, etc... + UNVERIFIABLE (6): + License cannot be verified due to a not + legitimate image. + WRONG_DOCUMENT_OR_ID (7): + License is not the requested document type or + contains an invalid ID. + OTHER (8): + License has another flaw not listed + explicitly. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BUSINESS_NAME_MISMATCH = 2 + UNAUTHORIZED = 3 + EXPIRED = 4 + POOR_QUALITY = 5 + UNVERIFIABLE = 6 + WRONG_DOCUMENT_OR_ID = 7 + OTHER = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_participant_type.py b/google/ads/googleads/v24/enums/types/local_services_participant_type.py new file mode 100644 index 000000000..66b920ddb --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_participant_type.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesParticipantTypeEnum", + }, +) + + +class LocalServicesParticipantTypeEnum(proto.Message): + r"""Container for enum describing possible types of lead + conversation participants. + + """ + + class ParticipantType(proto.Enum): + r"""Possible types of lead conversation participant. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ADVERTISER (2): + Local Services Ads Provider participant. + CONSUMER (3): + Local Services Ads Consumer participant. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ADVERTISER = 2 + CONSUMER = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_verification_artifact_status.py b/google/ads/googleads/v24/enums/types/local_services_verification_artifact_status.py new file mode 100644 index 000000000..033a935c5 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_verification_artifact_status.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesVerificationArtifactStatusEnum", + }, +) + + +class LocalServicesVerificationArtifactStatusEnum(proto.Message): + r"""Container for enum describing the status of local services + verification artifact. + + """ + + class LocalServicesVerificationArtifactStatus(proto.Enum): + r"""Enums describing statuses of a local services verification + artifact. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PASSED (2): + Artifact has passed verification. + FAILED (3): + Artifact has failed verification. + PENDING (4): + Artifact is in the process of verification. + NO_SUBMISSION (5): + Artifact needs user to upload information + before it is verified. + CANCELLED (6): + Artifact has been cancelled by the user. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PASSED = 2 + FAILED = 3 + PENDING = 4 + NO_SUBMISSION = 5 + CANCELLED = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_verification_artifact_type.py b/google/ads/googleads/v24/enums/types/local_services_verification_artifact_type.py new file mode 100644 index 000000000..ab3c4c01c --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_verification_artifact_type.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesVerificationArtifactTypeEnum", + }, +) + + +class LocalServicesVerificationArtifactTypeEnum(proto.Message): + r"""Container for enum describing the type of local services + verification artifact. + + """ + + class LocalServicesVerificationArtifactType(proto.Enum): + r"""Enums describing possible types of local services + verification artifact. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BACKGROUND_CHECK (2): + Background check verification artifact. + INSURANCE (3): + Insurance verification artifact. + LICENSE (4): + License verification artifact. + BUSINESS_REGISTRATION_CHECK (5): + Business registration check verification + artifact. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BACKGROUND_CHECK = 2 + INSURANCE = 3 + LICENSE = 4 + BUSINESS_REGISTRATION_CHECK = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/local_services_verification_status.py b/google/ads/googleads/v24/enums/types/local_services_verification_status.py new file mode 100644 index 000000000..79e87cd68 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/local_services_verification_status.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesVerificationStatusEnum", + }, +) + + +class LocalServicesVerificationStatusEnum(proto.Message): + r"""Container for enum describing status of a particular Local + Services Ads verification category. + + """ + + class LocalServicesVerificationStatus(proto.Enum): + r"""Enum describing status of a particular Local Services Ads + verification category. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Unknown verification status. + NEEDS_REVIEW (2): + Verification has started, but has not + finished. + FAILED (3): + Verification has failed. + PASSED (4): + Verification has passed. + NOT_APPLICABLE (5): + Verification is not applicable. + NO_SUBMISSION (6): + Verification is required but pending + submission. + PARTIAL_SUBMISSION (7): + Not all required verification has been + submitted. + PENDING_ESCALATION (8): + Verification needs review by Local Services + Ads Ops Specialist. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NEEDS_REVIEW = 2 + FAILED = 3 + PASSED = 4 + NOT_APPLICABLE = 5 + NO_SUBMISSION = 6 + PARTIAL_SUBMISSION = 7 + PENDING_ESCALATION = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/location_group_radius_units.py b/google/ads/googleads/v24/enums/types/location_group_radius_units.py new file mode 100644 index 000000000..1e1d4a9ee --- /dev/null +++ b/google/ads/googleads/v24/enums/types/location_group_radius_units.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocationGroupRadiusUnitsEnum", + }, +) + + +class LocationGroupRadiusUnitsEnum(proto.Message): + r"""Container for enum describing unit of radius in location + group. + + """ + + class LocationGroupRadiusUnits(proto.Enum): + r"""The unit of radius distance in location group (for example, + MILES) + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + METERS (2): + Meters + MILES (3): + Miles + MILLI_MILES (4): + Milli Miles + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + METERS = 2 + MILES = 3 + MILLI_MILES = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/location_ownership_type.py b/google/ads/googleads/v24/enums/types/location_ownership_type.py new file mode 100644 index 000000000..c77276236 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/location_ownership_type.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocationOwnershipTypeEnum", + }, +) + + +class LocationOwnershipTypeEnum(proto.Message): + r"""Container for enum describing possible types of a location + ownership. + + """ + + class LocationOwnershipType(proto.Enum): + r"""Possible types of a location ownership. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BUSINESS_OWNER (2): + Business Owner of location(legacy location + extension - LE). + AFFILIATE (3): + Affiliate location(Third party location + extension - ALE). + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BUSINESS_OWNER = 2 + AFFILIATE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/location_source_type.py b/google/ads/googleads/v24/enums/types/location_source_type.py new file mode 100644 index 000000000..ceb65a6a1 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/location_source_type.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocationSourceTypeEnum", + }, +) + + +class LocationSourceTypeEnum(proto.Message): + r"""Used to distinguish the location source type.""" + + class LocationSourceType(proto.Enum): + r"""The possible types of a location source. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + GOOGLE_MY_BUSINESS (2): + Locations associated with the customer's + linked Business Profile. + AFFILIATE (3): + Affiliate (chain) store locations. For + example, Best Buy store locations. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + GOOGLE_MY_BUSINESS = 2 + AFFILIATE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/location_string_filter_type.py b/google/ads/googleads/v24/enums/types/location_string_filter_type.py new file mode 100644 index 000000000..2ad059c8c --- /dev/null +++ b/google/ads/googleads/v24/enums/types/location_string_filter_type.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LocationStringFilterTypeEnum", + }, +) + + +class LocationStringFilterTypeEnum(proto.Message): + r"""Container for enum describing possible types of a location + string filter. + + """ + + class LocationStringFilterType(proto.Enum): + r"""Possible types of a location string filter. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + EXACT (2): + The filter will use exact string matching. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EXACT = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/lookalike_expansion_level.py b/google/ads/googleads/v24/enums/types/lookalike_expansion_level.py new file mode 100644 index 000000000..20b702de9 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/lookalike_expansion_level.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "LookalikeExpansionLevelEnum", + }, +) + + +class LookalikeExpansionLevelEnum(proto.Message): + r"""Lookalike Expansion level proto""" + + class LookalikeExpansionLevel(proto.Enum): + r"""Expansion level, reflecting the size of the lookalike + audience + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Invalid expansion level. + NARROW (2): + Expansion to a small set of users that are + similar to the seed lists + BALANCED (3): + Expansion to a medium set of users that are similar to the + seed lists. Includes all users of EXPANSION_LEVEL_NARROW, + and more. + BROAD (4): + Expansion to a large set of users that are similar to the + seed lists. Includes all users of EXPANSION_LEVEL_BALANCED, + and more. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NARROW = 2 + BALANCED = 3 + BROAD = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/manager_link_status.py b/google/ads/googleads/v24/enums/types/manager_link_status.py new file mode 100644 index 000000000..f29ee9604 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/manager_link_status.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ManagerLinkStatusEnum", + }, +) + + +class ManagerLinkStatusEnum(proto.Message): + r"""Container for enum describing possible status of a manager + and client link. + + """ + + class ManagerLinkStatus(proto.Enum): + r"""Possible statuses of a link. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ACTIVE (2): + Indicates current in-effect relationship + INACTIVE (3): + Indicates terminated relationship + PENDING (4): + Indicates relationship has been requested by + manager, but the client hasn't accepted yet. + REFUSED (5): + Relationship was requested by the manager, + but the client has refused. + CANCELED (6): + Indicates relationship has been requested by + manager, but manager canceled it. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ACTIVE = 2 + INACTIVE = 3 + PENDING = 4 + REFUSED = 5 + CANCELED = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/match_type.py b/google/ads/googleads/v24/enums/types/match_type.py new file mode 100644 index 000000000..29ab1e8fe --- /dev/null +++ b/google/ads/googleads/v24/enums/types/match_type.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "MatchTypeEnum", + }, +) + + +class MatchTypeEnum(proto.Message): + r"""Container for enum describing match types for a keyword + triggering an ad. + + """ + + class MatchType(proto.Enum): + r"""Possible match types for a keyword triggering an ad. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BROAD (2): + Broad match. + EXACT (3): + Exact match. + PHRASE (4): + Phrase match. + AI_MAX (5): + Match type for AI Max Search. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BROAD = 2 + EXACT = 3 + PHRASE = 4 + AI_MAX = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/media_type.py b/google/ads/googleads/v24/enums/types/media_type.py new file mode 100644 index 000000000..9d8e218c7 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/media_type.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "MediaTypeEnum", + }, +) + + +class MediaTypeEnum(proto.Message): + r"""Container for enum describing the types of media.""" + + class MediaType(proto.Enum): + r"""The type of media. + + Values: + UNSPECIFIED (0): + The media type has not been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + IMAGE (2): + Static image, used for image ad. + ICON (3): + Small image, used for map ad. + MEDIA_BUNDLE (4): + ZIP file, used in fields of template ads. + AUDIO (5): + Audio file. + VIDEO (6): + Video file. + DYNAMIC_IMAGE (7): + Animated image, such as animated GIF. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + IMAGE = 2 + ICON = 3 + MEDIA_BUNDLE = 4 + AUDIO = 5 + VIDEO = 6 + DYNAMIC_IMAGE = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/messaging_restriction_type.py b/google/ads/googleads/v24/enums/types/messaging_restriction_type.py new file mode 100644 index 000000000..6ec0a9a9d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/messaging_restriction_type.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "MessagingRestrictionTypeEnum", + }, +) + + +class MessagingRestrictionTypeEnum(proto.Message): + r"""Container for enum describing the type of a text generation + restriction. + + """ + + class MessagingRestrictionType(proto.Enum): + r"""The type of a text generation restriction. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + RESTRICTION_BASED_EXCLUSION (2): + Exclude text assets that are not compliant + with this restriction. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + RESTRICTION_BASED_EXCLUSION = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/mime_type.py b/google/ads/googleads/v24/enums/types/mime_type.py new file mode 100644 index 000000000..5cdcdc32d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/mime_type.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "MimeTypeEnum", + }, +) + + +class MimeTypeEnum(proto.Message): + r"""Container for enum describing the mime types.""" + + class MimeType(proto.Enum): + r"""The mime type + + Values: + UNSPECIFIED (0): + The mime type has not been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + IMAGE_JPEG (2): + MIME type of image/jpeg. + IMAGE_GIF (3): + MIME type of image/gif. + IMAGE_PNG (4): + MIME type of image/png. + FLASH (5): + MIME type of application/x-shockwave-flash. + TEXT_HTML (6): + MIME type of text/html. + PDF (7): + MIME type of application/pdf. + MSWORD (8): + MIME type of application/msword. + MSEXCEL (9): + MIME type of application/vnd.ms-excel. + RTF (10): + MIME type of application/rtf. + AUDIO_WAV (11): + MIME type of audio/wav. + AUDIO_MP3 (12): + MIME type of audio/mp3. + HTML5_AD_ZIP (13): + MIME type of application/x-html5-ad-zip. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + IMAGE_JPEG = 2 + IMAGE_GIF = 3 + IMAGE_PNG = 4 + FLASH = 5 + TEXT_HTML = 6 + PDF = 7 + MSWORD = 8 + MSEXCEL = 9 + RTF = 10 + AUDIO_WAV = 11 + AUDIO_MP3 = 12 + HTML5_AD_ZIP = 13 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/minute_of_hour.py b/google/ads/googleads/v24/enums/types/minute_of_hour.py new file mode 100644 index 000000000..e1b06b5d8 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/minute_of_hour.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "MinuteOfHourEnum", + }, +) + + +class MinuteOfHourEnum(proto.Message): + r"""Container for enumeration of quarter-hours.""" + + class MinuteOfHour(proto.Enum): + r"""Enumerates of quarter-hours. For example, "FIFTEEN". + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + ZERO (2): + Zero minutes past the hour. + FIFTEEN (3): + Fifteen minutes past the hour. + THIRTY (4): + Thirty minutes past the hour. + FORTY_FIVE (5): + Forty-five minutes past the hour. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ZERO = 2 + FIFTEEN = 3 + THIRTY = 4 + FORTY_FIVE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/mobile_app_vendor.py b/google/ads/googleads/v24/enums/types/mobile_app_vendor.py new file mode 100644 index 000000000..bda7b0783 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/mobile_app_vendor.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "MobileAppVendorEnum", + }, +) + + +class MobileAppVendorEnum(proto.Message): + r"""Container for enum describing different types of mobile app + vendors. + + """ + + class MobileAppVendor(proto.Enum): + r"""The type of mobile app vendor + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + APPLE_APP_STORE (2): + Mobile app vendor for Apple app store. + GOOGLE_APP_STORE (3): + Mobile app vendor for Google app store. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + APPLE_APP_STORE = 2 + GOOGLE_APP_STORE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/mobile_device_type.py b/google/ads/googleads/v24/enums/types/mobile_device_type.py new file mode 100644 index 000000000..53b12aff5 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/mobile_device_type.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "MobileDeviceTypeEnum", + }, +) + + +class MobileDeviceTypeEnum(proto.Message): + r"""Container for enum describing the types of mobile device.""" + + class MobileDeviceType(proto.Enum): + r"""The type of mobile device. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + MOBILE (2): + Mobile phones. + TABLET (3): + Tablets. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MOBILE = 2 + TABLET = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/month_of_year.py b/google/ads/googleads/v24/enums/types/month_of_year.py new file mode 100644 index 000000000..8cc11ecdb --- /dev/null +++ b/google/ads/googleads/v24/enums/types/month_of_year.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "MonthOfYearEnum", + }, +) + + +class MonthOfYearEnum(proto.Message): + r"""Container for enumeration of months of the year, for example, + "January". + + """ + + class MonthOfYear(proto.Enum): + r"""Enumerates months of the year, for example, "January". + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + JANUARY (2): + January. + FEBRUARY (3): + February. + MARCH (4): + March. + APRIL (5): + April. + MAY (6): + May. + JUNE (7): + June. + JULY (8): + July. + AUGUST (9): + August. + SEPTEMBER (10): + September. + OCTOBER (11): + October. + NOVEMBER (12): + November. + DECEMBER (13): + December. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + JANUARY = 2 + FEBRUARY = 3 + MARCH = 4 + APRIL = 5 + MAY = 6 + JUNE = 7 + JULY = 8 + AUGUST = 9 + SEPTEMBER = 10 + OCTOBER = 11 + NOVEMBER = 12 + DECEMBER = 13 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/negative_geo_target_type.py b/google/ads/googleads/v24/enums/types/negative_geo_target_type.py new file mode 100644 index 000000000..e7dba920d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/negative_geo_target_type.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "NegativeGeoTargetTypeEnum", + }, +) + + +class NegativeGeoTargetTypeEnum(proto.Message): + r"""Container for enum describing possible negative geo target + types. + + """ + + class NegativeGeoTargetType(proto.Enum): + r"""The possible negative geo target types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + PRESENCE_OR_INTEREST (4): + Specifies that a user is excluded from seeing + the ad if they are in, or show interest in, + advertiser's excluded locations. + PRESENCE (5): + Specifies that a user is excluded from seeing + the ad if they are in advertiser's excluded + locations. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PRESENCE_OR_INTEREST = 4 + PRESENCE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/non_skippable_max_duration.py b/google/ads/googleads/v24/enums/types/non_skippable_max_duration.py new file mode 100644 index 000000000..85dd093a6 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/non_skippable_max_duration.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "NonSkippableMaxDurationEnum", + }, +) + + +class NonSkippableMaxDurationEnum(proto.Message): + r"""Container for enum describing the allowed maximum duration + values for videos used in non-skippable video responsive ads. + + """ + + class NonSkippableMaxDuration(proto.Enum): + r"""Enum describing the allowed maximum duration values for + videos used in non-skippable video responsive ads. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + MAX_DURATION_FIFTEEN_SECONDS (2): + Indicates that non-skippable ads must be at + most 15 seconds long. + MAX_DURATION_THIRTY_SECONDS (3): + Indicates that non-skippable ads must be at + most 30 seconds long. + MAX_DURATION_SIXTY_SECONDS (4): + Indicates that non-skippable ads must be at + most 60 seconds long. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MAX_DURATION_FIFTEEN_SECONDS = 2 + MAX_DURATION_THIRTY_SECONDS = 3 + MAX_DURATION_SIXTY_SECONDS = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/non_skippable_min_duration.py b/google/ads/googleads/v24/enums/types/non_skippable_min_duration.py new file mode 100644 index 000000000..eb7fbccb3 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/non_skippable_min_duration.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "NonSkippableMinDurationEnum", + }, +) + + +class NonSkippableMinDurationEnum(proto.Message): + r"""Container for enum describing the allowed minimum duration + values for videos used in non-skippable video responsive ads. + + """ + + class NonSkippableMinDuration(proto.Enum): + r"""Enum describing the allowed minimum duration values for + videos used in non-skippable video responsive ads. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + MIN_DURATION_FIVE_SECONDS (2): + Indicates that non-skippable ads must be at + least 5 seconds long. + MIN_DURATION_SEVEN_SECONDS (3): + Indicates that non-skippable ads must be at + least 7 seconds long. + MIN_DURATION_SIXTEEN_SECONDS (4): + Indicates that non-skippable ads must be at + least 16 seconds long. + MIN_DURATION_THIRTY_ONE_SECONDS (5): + Indicates that non-skippable ads must be at + least 31 seconds long. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MIN_DURATION_FIVE_SECONDS = 2 + MIN_DURATION_SEVEN_SECONDS = 3 + MIN_DURATION_SIXTEEN_SECONDS = 4 + MIN_DURATION_THIRTY_ONE_SECONDS = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/offline_conversion_diagnostic_status_enum.py b/google/ads/googleads/v24/enums/types/offline_conversion_diagnostic_status_enum.py new file mode 100644 index 000000000..0e32ef90e --- /dev/null +++ b/google/ads/googleads/v24/enums/types/offline_conversion_diagnostic_status_enum.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "OfflineConversionDiagnosticStatusEnum", + }, +) + + +class OfflineConversionDiagnosticStatusEnum(proto.Message): + r"""All possible statuses for oci diagnostics.""" + + class OfflineConversionDiagnosticStatus(proto.Enum): + r"""Possible statuses of the offline ingestion setup. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + EXCELLENT (2): + Your offline data ingestion setup is active + and optimal for downstream processing. + GOOD (3): + Your offline ingestion setup is active, but + there are further improvements you could make. + See alerts. + NEEDS_ATTENTION (4): + Your offline ingestion setup is active, but + there are errors that require your attention. + See alerts. + NO_RECENT_UPLOAD (6): + Your offline ingestion setup has not received + data in the last 28 days, there may be something + wrong. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EXCELLENT = 2 + GOOD = 3 + NEEDS_ATTENTION = 4 + NO_RECENT_UPLOAD = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/offline_event_upload_client_enum.py b/google/ads/googleads/v24/enums/types/offline_event_upload_client_enum.py new file mode 100644 index 000000000..58e229e52 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/offline_event_upload_client_enum.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "OfflineEventUploadClientEnum", + }, +) + + +class OfflineEventUploadClientEnum(proto.Message): + r"""All possible clients for an offline upload event.""" + + class OfflineEventUploadClient(proto.Enum): + r"""Type of client. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + GOOGLE_ADS_API (2): + Google Ads API. + GOOGLE_ADS_WEB_CLIENT (3): + Google Ads web client, which could include + multiple sources like Ads UI, SFTP, etc. + ADS_DATA_CONNECTOR (4): + Connection platform. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + GOOGLE_ADS_API = 2 + GOOGLE_ADS_WEB_CLIENT = 3 + ADS_DATA_CONNECTOR = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/offline_user_data_job_failure_reason.py b/google/ads/googleads/v24/enums/types/offline_user_data_job_failure_reason.py new file mode 100644 index 000000000..599ae9bfa --- /dev/null +++ b/google/ads/googleads/v24/enums/types/offline_user_data_job_failure_reason.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "OfflineUserDataJobFailureReasonEnum", + }, +) + + +class OfflineUserDataJobFailureReasonEnum(proto.Message): + r"""Container for enum describing reasons why an offline user + data job failed to be processed. + + """ + + class OfflineUserDataJobFailureReason(proto.Enum): + r"""The failure reason of an offline user data job. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + INSUFFICIENT_MATCHED_TRANSACTIONS (2): + The matched transactions are insufficient. + INSUFFICIENT_TRANSACTIONS (3): + The uploaded transactions are insufficient. + HIGH_AVERAGE_TRANSACTION_VALUE (4): + The average transaction value is unusually high for your + account. If this is intended, contact support to request an + exception. Learn more at + https://support.google.com/google-ads/answer/10018944#transaction_value + LOW_AVERAGE_TRANSACTION_VALUE (5): + The average transaction value is unusually low for your + account. If this is intended, contact support to request an + exception. Learn more at + https://support.google.com/google-ads/answer/10018944#transaction_value + NEWLY_OBSERVED_CURRENCY_CODE (6): + There's a currency code that you haven't used before in your + uploads. If this is intended, contact support to request an + exception. Learn more at + https://support.google.com/google-ads/answer/10018944#Unrecognized_currency + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INSUFFICIENT_MATCHED_TRANSACTIONS = 2 + INSUFFICIENT_TRANSACTIONS = 3 + HIGH_AVERAGE_TRANSACTION_VALUE = 4 + LOW_AVERAGE_TRANSACTION_VALUE = 5 + NEWLY_OBSERVED_CURRENCY_CODE = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/offline_user_data_job_match_rate_range.py b/google/ads/googleads/v24/enums/types/offline_user_data_job_match_rate_range.py new file mode 100644 index 000000000..5e41e5edd --- /dev/null +++ b/google/ads/googleads/v24/enums/types/offline_user_data_job_match_rate_range.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "OfflineUserDataJobMatchRateRangeEnum", + }, +) + + +class OfflineUserDataJobMatchRateRangeEnum(proto.Message): + r"""Container for enum describing reasons match rate ranges for a + customer match list upload. + + """ + + class OfflineUserDataJobMatchRateRange(proto.Enum): + r"""The match rate range of an offline user data job. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Default value for match rate range. + MATCH_RANGE_LESS_THAN_20 (2): + Match rate range for offline data upload + entity is between 0% and 19%. + MATCH_RANGE_20_TO_30 (3): + Match rate range for offline data upload + entity is between 20% and 30%. + MATCH_RANGE_31_TO_40 (4): + Match rate range for offline data upload + entity is between 31% and 40%. + MATCH_RANGE_41_TO_50 (5): + Match rate range for offline data upload + entity is between 41% and 50%. + MATCH_RANGE_51_TO_60 (6): + Match rate range for offline data upload + entity is between 51% and 60%. + MATCH_RANGE_61_TO_70 (7): + Match rate range for offline data upload + entity is between 61% and 70%. + MATCH_RANGE_71_TO_80 (8): + Match rate range for offline data upload + entity is between 71% and 80%. + MATCH_RANGE_81_TO_90 (9): + Match rate range for offline data upload + entity is between 81% and 90%. + MATCH_RANGE_91_TO_100 (10): + Match rate range for offline data upload + entity is more than or equal to 91%. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MATCH_RANGE_LESS_THAN_20 = 2 + MATCH_RANGE_20_TO_30 = 3 + MATCH_RANGE_31_TO_40 = 4 + MATCH_RANGE_41_TO_50 = 5 + MATCH_RANGE_51_TO_60 = 6 + MATCH_RANGE_61_TO_70 = 7 + MATCH_RANGE_71_TO_80 = 8 + MATCH_RANGE_81_TO_90 = 9 + MATCH_RANGE_91_TO_100 = 10 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/offline_user_data_job_status.py b/google/ads/googleads/v24/enums/types/offline_user_data_job_status.py new file mode 100644 index 000000000..5c06a987d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/offline_user_data_job_status.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "OfflineUserDataJobStatusEnum", + }, +) + + +class OfflineUserDataJobStatusEnum(proto.Message): + r"""Container for enum describing status of an offline user data + job. + + """ + + class OfflineUserDataJobStatus(proto.Enum): + r"""The status of an offline user data job. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PENDING (2): + The job has been successfully created and + pending for uploading. + RUNNING (3): + Upload(s) have been accepted and data is + being processed. + SUCCESS (4): + Uploaded data has been successfully + processed. The job might have no operations, + which can happen if the job was run without any + operations added, or if all operations failed + validation individually when attempting to add + them to the job. + FAILED (5): + Uploaded data has failed to be processed. + Some operations may have been successfully + processed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + RUNNING = 3 + SUCCESS = 4 + FAILED = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/offline_user_data_job_type.py b/google/ads/googleads/v24/enums/types/offline_user_data_job_type.py new file mode 100644 index 000000000..d3609c211 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/offline_user_data_job_type.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "OfflineUserDataJobTypeEnum", + }, +) + + +class OfflineUserDataJobTypeEnum(proto.Message): + r"""Container for enum describing types of an offline user data + job. + + """ + + class OfflineUserDataJobType(proto.Enum): + r"""The type of an offline user data job. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + STORE_SALES_UPLOAD_FIRST_PARTY (2): + Store Sales Direct data for self service. + STORE_SALES_UPLOAD_THIRD_PARTY (3): + Store Sales Direct data for third party. + CUSTOMER_MATCH_USER_LIST (4): + Customer Match user list data. + CUSTOMER_MATCH_WITH_ATTRIBUTES (5): + Customer Match with attribute data. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + STORE_SALES_UPLOAD_FIRST_PARTY = 2 + STORE_SALES_UPLOAD_THIRD_PARTY = 3 + CUSTOMER_MATCH_USER_LIST = 4 + CUSTOMER_MATCH_WITH_ATTRIBUTES = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/operating_system_version_operator_type.py b/google/ads/googleads/v24/enums/types/operating_system_version_operator_type.py new file mode 100644 index 000000000..339e83e3d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/operating_system_version_operator_type.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "OperatingSystemVersionOperatorTypeEnum", + }, +) + + +class OperatingSystemVersionOperatorTypeEnum(proto.Message): + r"""Container for enum describing the type of OS operators.""" + + class OperatingSystemVersionOperatorType(proto.Enum): + r"""The type of operating system version. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + EQUALS_TO (2): + Equals to the specified version. + GREATER_THAN_EQUALS_TO (4): + Greater than or equals to the specified + version. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EQUALS_TO = 2 + GREATER_THAN_EQUALS_TO = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/optimization_goal_type.py b/google/ads/googleads/v24/enums/types/optimization_goal_type.py new file mode 100644 index 000000000..c52437862 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/optimization_goal_type.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "OptimizationGoalTypeEnum", + }, +) + + +class OptimizationGoalTypeEnum(proto.Message): + r"""Container for enum describing the type of optimization goal.""" + + class OptimizationGoalType(proto.Enum): + r"""The type of optimization goal + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used as a return value only. Represents value + unknown in this version. + CALL_CLICKS (2): + Optimize for call clicks. Call click + conversions are times people selected 'Call' to + contact a store after viewing an ad. + DRIVING_DIRECTIONS (3): + Optimize for driving directions. Driving + directions conversions are times people selected + 'Get directions' to navigate to a store after + viewing an ad. + APP_PRE_REGISTRATION (4): + Optimize for pre-registration. + Pre-registration conversions are the number of + pre-registration signups to receive a + notification when the app is released. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CALL_CLICKS = 2 + DRIVING_DIRECTIONS = 3 + APP_PRE_REGISTRATION = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/parental_status_type.py b/google/ads/googleads/v24/enums/types/parental_status_type.py new file mode 100644 index 000000000..d2de1ca8f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/parental_status_type.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ParentalStatusTypeEnum", + }, +) + + +class ParentalStatusTypeEnum(proto.Message): + r"""Container for enum describing the type of demographic + parental statuses. + + """ + + class ParentalStatusType(proto.Enum): + r"""The type of parental statuses (for example, not a parent). + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PARENT (300): + Parent. + NOT_A_PARENT (301): + Not a parent. + UNDETERMINED (302): + Undetermined parental status. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PARENT = 300 + NOT_A_PARENT = 301 + UNDETERMINED = 302 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/partnership_opportunity.py b/google/ads/googleads/v24/enums/types/partnership_opportunity.py new file mode 100644 index 000000000..1e403b27f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/partnership_opportunity.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PartnershipOpportunityEnum", + }, +) + + +class PartnershipOpportunityEnum(proto.Message): + r"""Container for enum describing partnership opportunity.""" + + class PartnershipOpportunity(proto.Enum): + r"""Partnership opportunity between media buyers and creators for + paid media on YouTube. + + Values: + UNSPECIFIED (0): + Default value. This value is equivalent to + null. + UNKNOWN (1): + Output-only. Represents a format not yet + defined in this enum. + CREATOR_PARTNERSHIPS (2): + A partnership opportunity that allows + advertisers to partner with YouTube creators on + sponsored content that mentions a brand or + product. See + https://support.google.com/google-ads/answer/15471603 + to learn more. + CREATOR_TAKEOVER (3): + A partnership opportunity that gives brands + exclusive access to all ad slots on channels of + top creators. + PARTNERSHIP_ADS (4): + A partnership opportunity that enables brands + to use YouTube creator videos in their ad + campaigns. See + https://support.google.com/google-ads/answer/15223349 + to learn more. + YOUTUBE_SELECT_LINEUPS (5): + A partnership opportunity that allows + advertisers to buy specific ad placements on a + reservation basis to target among the top 1% of + popular channels on YouTube. See + https://support.google.com/google-ads/answer/6030919 + to learn more. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CREATOR_PARTNERSHIPS = 2 + CREATOR_TAKEOVER = 3 + PARTNERSHIP_ADS = 4 + YOUTUBE_SELECT_LINEUPS = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/payment_mode.py b/google/ads/googleads/v24/enums/types/payment_mode.py new file mode 100644 index 000000000..d94e43dbc --- /dev/null +++ b/google/ads/googleads/v24/enums/types/payment_mode.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PaymentModeEnum", + }, +) + + +class PaymentModeEnum(proto.Message): + r"""Container for enum describing possible payment modes.""" + + class PaymentMode(proto.Enum): + r"""Enum describing possible payment modes. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CLICKS (4): + Pay per interaction. + CONVERSION_VALUE (5): + Pay per conversion value. This mode is only + supported by campaigns with + AdvertisingChannelType.HOTEL, + BiddingStrategyType.COMMISSION, and + BudgetType.STANDARD. + CONVERSIONS (6): + Pay per conversion. This mode is only supported by campaigns + with AdvertisingChannelType.DISPLAY (excluding + AdvertisingChannelSubType.DISPLAY_GMAIL), + BiddingStrategyType.TARGET_CPA, and BudgetType.FIXED_CPA. + The customer must also be eligible for this mode. See + Customer.eligibility_failure_reasons for details. + GUEST_STAY (7): + Pay per guest stay value. This mode is only + supported by campaigns with + AdvertisingChannelType.HOTEL, + BiddingStrategyType.COMMISSION, and + BudgetType.STANDARD. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CLICKS = 4 + CONVERSION_VALUE = 5 + CONVERSIONS = 6 + GUEST_STAY = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/performance_max_upgrade_status.py b/google/ads/googleads/v24/enums/types/performance_max_upgrade_status.py new file mode 100644 index 000000000..85961d8f2 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/performance_max_upgrade_status.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PerformanceMaxUpgradeStatusEnum", + }, +) + + +class PerformanceMaxUpgradeStatusEnum(proto.Message): + r"""Performance Max Upgrade status for campaign.""" + + class PerformanceMaxUpgradeStatus(proto.Enum): + r"""Performance Max Upgrade status enum for campaign. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + UPGRADE_IN_PROGRESS (3): + The upgrade to a Performance Max campaign is + in progress. + UPGRADE_COMPLETE (4): + The upgrade to a Performance Max campaign is + complete. + UPGRADE_FAILED (5): + The upgrade to a Performance Max campaign + failed. The campaign will still serve as it was + before upgrade was attempted. + UPGRADE_ELIGIBLE (6): + The campaign is eligible for upgrade to a + Performance Max campaign. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UPGRADE_IN_PROGRESS = 3 + UPGRADE_COMPLETE = 4 + UPGRADE_FAILED = 5 + UPGRADE_ELIGIBLE = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/placement_type.py b/google/ads/googleads/v24/enums/types/placement_type.py new file mode 100644 index 000000000..4555322fe --- /dev/null +++ b/google/ads/googleads/v24/enums/types/placement_type.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PlacementTypeEnum", + }, +) + + +class PlacementTypeEnum(proto.Message): + r"""Container for enum describing possible placement types.""" + + class PlacementType(proto.Enum): + r"""Possible placement types for a feed mapping. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + WEBSITE (2): + Websites(for example, + 'www.flowers4sale.com'). + MOBILE_APP_CATEGORY (3): + Mobile application categories(for example, + 'Games'). + MOBILE_APPLICATION (4): + mobile applications(for example, + 'mobileapp::2-com.whatsthewordanswers'). + YOUTUBE_VIDEO (5): + YouTube videos(for example, + 'youtube.com/video/wtLJPvx7-ys'). + YOUTUBE_CHANNEL (6): + YouTube channels(for example, + 'youtube.com::L8ZULXASCc1I_oaOT0NaOQ'). + GOOGLE_PRODUCTS (7): + Surfaces owned and operated by Google(for + example, 'tv.google.com'). + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + WEBSITE = 2 + MOBILE_APP_CATEGORY = 3 + MOBILE_APPLICATION = 4 + YOUTUBE_VIDEO = 5 + YOUTUBE_CHANNEL = 6 + GOOGLE_PRODUCTS = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/policy_approval_status.py b/google/ads/googleads/v24/enums/types/policy_approval_status.py new file mode 100644 index 000000000..c9407b10c --- /dev/null +++ b/google/ads/googleads/v24/enums/types/policy_approval_status.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PolicyApprovalStatusEnum", + }, +) + + +class PolicyApprovalStatusEnum(proto.Message): + r"""Container for enum describing possible policy approval + statuses. + + """ + + class PolicyApprovalStatus(proto.Enum): + r"""The possible policy approval statuses. When there are several + approval statuses available the most severe one will be used. The + order of severity is DISAPPROVED, AREA_OF_INTEREST_ONLY, + APPROVED_LIMITED and APPROVED. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + DISAPPROVED (2): + Will not serve. + APPROVED_LIMITED (3): + Serves with restrictions. + APPROVED (4): + Serves without restrictions. + AREA_OF_INTEREST_ONLY (5): + Will not serve in targeted countries, but may + serve for users who are searching for + information about the targeted countries. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DISAPPROVED = 2 + APPROVED_LIMITED = 3 + APPROVED = 4 + AREA_OF_INTEREST_ONLY = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/policy_review_status.py b/google/ads/googleads/v24/enums/types/policy_review_status.py new file mode 100644 index 000000000..3c7fc872a --- /dev/null +++ b/google/ads/googleads/v24/enums/types/policy_review_status.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PolicyReviewStatusEnum", + }, +) + + +class PolicyReviewStatusEnum(proto.Message): + r"""Container for enum describing possible policy review + statuses. + + """ + + class PolicyReviewStatus(proto.Enum): + r"""The possible policy review statuses. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + REVIEW_IN_PROGRESS (2): + Currently under review. + REVIEWED (3): + Primary review complete. Other reviews may be + continuing. + UNDER_APPEAL (4): + The resource has been resubmitted for + approval or its policy decision has been + appealed. + ELIGIBLE_MAY_SERVE (5): + The resource is eligible and may be serving + but could still undergo further review. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + REVIEW_IN_PROGRESS = 2 + REVIEWED = 3 + UNDER_APPEAL = 4 + ELIGIBLE_MAY_SERVE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/policy_topic_entry_type.py b/google/ads/googleads/v24/enums/types/policy_topic_entry_type.py new file mode 100644 index 000000000..3c388e183 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/policy_topic_entry_type.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PolicyTopicEntryTypeEnum", + }, +) + + +class PolicyTopicEntryTypeEnum(proto.Message): + r"""Container for enum describing possible policy topic entry + types. + + """ + + class PolicyTopicEntryType(proto.Enum): + r"""The possible policy topic entry types. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + PROHIBITED (2): + The resource will not be served. + LIMITED (4): + The resource will not be served under some + circumstances. + FULLY_LIMITED (8): + The resource cannot serve at all because of + the current targeting criteria. + DESCRIPTIVE (5): + May be of interest, but does not limit how + the resource is served. + BROADENING (6): + Could increase coverage beyond normal. + AREA_OF_INTEREST_ONLY (7): + Constrained for all targeted countries, but + may serve in other countries through area of + interest. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PROHIBITED = 2 + LIMITED = 4 + FULLY_LIMITED = 8 + DESCRIPTIVE = 5 + BROADENING = 6 + AREA_OF_INTEREST_ONLY = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/policy_topic_evidence_destination_mismatch_url_type.py b/google/ads/googleads/v24/enums/types/policy_topic_evidence_destination_mismatch_url_type.py new file mode 100644 index 000000000..f10726555 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/policy_topic_evidence_destination_mismatch_url_type.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PolicyTopicEvidenceDestinationMismatchUrlTypeEnum", + }, +) + + +class PolicyTopicEvidenceDestinationMismatchUrlTypeEnum(proto.Message): + r"""Container for enum describing possible policy topic evidence + destination mismatch url types. + + """ + + class PolicyTopicEvidenceDestinationMismatchUrlType(proto.Enum): + r"""The possible policy topic evidence destination mismatch url + types. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + DISPLAY_URL (2): + The display url. + FINAL_URL (3): + The final url. + FINAL_MOBILE_URL (4): + The final mobile url. + TRACKING_URL (5): + The tracking url template, with substituted + desktop url. + MOBILE_TRACKING_URL (6): + The tracking url template, with substituted + mobile url. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DISPLAY_URL = 2 + FINAL_URL = 3 + FINAL_MOBILE_URL = 4 + TRACKING_URL = 5 + MOBILE_TRACKING_URL = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/policy_topic_evidence_destination_not_working_device.py b/google/ads/googleads/v24/enums/types/policy_topic_evidence_destination_not_working_device.py new file mode 100644 index 000000000..8d0fe9ed1 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/policy_topic_evidence_destination_not_working_device.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PolicyTopicEvidenceDestinationNotWorkingDeviceEnum", + }, +) + + +class PolicyTopicEvidenceDestinationNotWorkingDeviceEnum(proto.Message): + r"""Container for enum describing possible policy topic evidence + destination not working devices. + + """ + + class PolicyTopicEvidenceDestinationNotWorkingDevice(proto.Enum): + r"""The possible policy topic evidence destination not working + devices. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + DESKTOP (2): + Landing page doesn't work on desktop device. + ANDROID (3): + Landing page doesn't work on Android device. + IOS (4): + Landing page doesn't work on iOS device. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DESKTOP = 2 + ANDROID = 3 + IOS = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/policy_topic_evidence_destination_not_working_dns_error_type.py b/google/ads/googleads/v24/enums/types/policy_topic_evidence_destination_not_working_dns_error_type.py new file mode 100644 index 000000000..9affc3a0c --- /dev/null +++ b/google/ads/googleads/v24/enums/types/policy_topic_evidence_destination_not_working_dns_error_type.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PolicyTopicEvidenceDestinationNotWorkingDnsErrorTypeEnum", + }, +) + + +class PolicyTopicEvidenceDestinationNotWorkingDnsErrorTypeEnum(proto.Message): + r"""Container for enum describing possible policy topic evidence + destination not working DNS error types. + + """ + + class PolicyTopicEvidenceDestinationNotWorkingDnsErrorType(proto.Enum): + r"""The possible policy topic evidence destination not working + DNS error types. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + HOSTNAME_NOT_FOUND (2): + Host name not found in DNS when fetching + landing page. + GOOGLE_CRAWLER_DNS_ISSUE (3): + Google internal crawler issue when + communicating with DNS. This error doesn't mean + the landing page doesn't work. Google will + recrawl the landing page. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + HOSTNAME_NOT_FOUND = 2 + GOOGLE_CRAWLER_DNS_ISSUE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/positive_geo_target_type.py b/google/ads/googleads/v24/enums/types/positive_geo_target_type.py new file mode 100644 index 000000000..7d789dd1f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/positive_geo_target_type.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PositiveGeoTargetTypeEnum", + }, +) + + +class PositiveGeoTargetTypeEnum(proto.Message): + r"""Container for enum describing possible positive geo target + types. + + """ + + class PositiveGeoTargetType(proto.Enum): + r"""The possible positive geo target types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + PRESENCE_OR_INTEREST (5): + Specifies that an ad is triggered if the user + is in, or shows interest in, advertiser's + targeted locations. + SEARCH_INTEREST (6): + Specifies that an ad is triggered if the user + searches for advertiser's targeted locations. + This can only be used with Search and standard + Shopping campaigns. + PRESENCE (7): + Specifies that an ad is triggered if the user + is in or regularly in advertiser's targeted + locations. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PRESENCE_OR_INTEREST = 5 + SEARCH_INTEREST = 6 + PRESENCE = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/preview_type.py b/google/ads/googleads/v24/enums/types/preview_type.py new file mode 100644 index 000000000..f2bcd445f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/preview_type.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PreviewTypeEnum", + }, +) + + +class PreviewTypeEnum(proto.Message): + r"""Preview type.""" + + class PreviewType(proto.Enum): + r"""Enum describing the preview type. + Next Id: 4 + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + UI_PREVIEW (2): + Request a URL to a preview in the Google Ads + UI. The generated URLs are shareable. + YOUTUBE_LIVE_PREVIEW (3): + Request a URL to a preview of the ad in + YouTube. The generated URLs are shareable. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UI_PREVIEW = 2 + YOUTUBE_LIVE_PREVIEW = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/price_extension_price_qualifier.py b/google/ads/googleads/v24/enums/types/price_extension_price_qualifier.py new file mode 100644 index 000000000..96d0c842c --- /dev/null +++ b/google/ads/googleads/v24/enums/types/price_extension_price_qualifier.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PriceExtensionPriceQualifierEnum", + }, +) + + +class PriceExtensionPriceQualifierEnum(proto.Message): + r"""Container for enum describing a price extension price + qualifier. + + """ + + class PriceExtensionPriceQualifier(proto.Enum): + r"""Enums of price extension price qualifier. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + FROM (2): + 'From' qualifier for the price. + UP_TO (3): + 'Up to' qualifier for the price. + AVERAGE (4): + 'Average' qualifier for the price. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + FROM = 2 + UP_TO = 3 + AVERAGE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/price_extension_price_unit.py b/google/ads/googleads/v24/enums/types/price_extension_price_unit.py new file mode 100644 index 000000000..1fe386b5b --- /dev/null +++ b/google/ads/googleads/v24/enums/types/price_extension_price_unit.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PriceExtensionPriceUnitEnum", + }, +) + + +class PriceExtensionPriceUnitEnum(proto.Message): + r"""Container for enum describing price extension price unit.""" + + class PriceExtensionPriceUnit(proto.Enum): + r"""Price extension price unit. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PER_HOUR (2): + Per hour. + PER_DAY (3): + Per day. + PER_WEEK (4): + Per week. + PER_MONTH (5): + Per month. + PER_YEAR (6): + Per year. + PER_NIGHT (7): + Per night. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PER_HOUR = 2 + PER_DAY = 3 + PER_WEEK = 4 + PER_MONTH = 5 + PER_YEAR = 6 + PER_NIGHT = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/price_extension_type.py b/google/ads/googleads/v24/enums/types/price_extension_type.py new file mode 100644 index 000000000..50fb4b115 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/price_extension_type.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PriceExtensionTypeEnum", + }, +) + + +class PriceExtensionTypeEnum(proto.Message): + r"""Container for enum describing types for a price extension.""" + + class PriceExtensionType(proto.Enum): + r"""Price extension type. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BRANDS (2): + The type for showing a list of brands. + EVENTS (3): + The type for showing a list of events. + LOCATIONS (4): + The type for showing locations relevant to + your business. + NEIGHBORHOODS (5): + The type for showing sub-regions or districts + within a city or region. + PRODUCT_CATEGORIES (6): + The type for showing a collection of product + categories. + PRODUCT_TIERS (7): + The type for showing a collection of related + product tiers. + SERVICES (8): + The type for showing a collection of services + offered by your business. + SERVICE_CATEGORIES (9): + The type for showing a collection of service + categories. + SERVICE_TIERS (10): + The type for showing a collection of related + service tiers. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BRANDS = 2 + EVENTS = 3 + LOCATIONS = 4 + NEIGHBORHOODS = 5 + PRODUCT_CATEGORIES = 6 + PRODUCT_TIERS = 7 + SERVICES = 8 + SERVICE_CATEGORIES = 9 + SERVICE_TIERS = 10 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/product_availability.py b/google/ads/googleads/v24/enums/types/product_availability.py new file mode 100644 index 000000000..57c14b376 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/product_availability.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ProductAvailabilityEnum", + }, +) + + +class ProductAvailabilityEnum(proto.Message): + r"""The availability of a product.""" + + class ProductAvailability(proto.Enum): + r"""Product availability. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + Used for return value only. Represents values + unknown in this version. + IN_STOCK (2): + The product is in stock. + OUT_OF_STOCK (3): + The product is out of stock. + PREORDER (4): + The product can be preordered. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + IN_STOCK = 2 + OUT_OF_STOCK = 3 + PREORDER = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/product_category_level.py b/google/ads/googleads/v24/enums/types/product_category_level.py new file mode 100644 index 000000000..1c2224bc4 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/product_category_level.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ProductCategoryLevelEnum", + }, +) + + +class ProductCategoryLevelEnum(proto.Message): + r"""Level of a product category.""" + + class ProductCategoryLevel(proto.Enum): + r"""Enum describing the level of the product category. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + LEVEL1 (2): + Level 1. + LEVEL2 (3): + Level 2. + LEVEL3 (4): + Level 3. + LEVEL4 (5): + Level 4. + LEVEL5 (6): + Level 5. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LEVEL1 = 2 + LEVEL2 = 3 + LEVEL3 = 4 + LEVEL4 = 5 + LEVEL5 = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/product_category_state.py b/google/ads/googleads/v24/enums/types/product_category_state.py new file mode 100644 index 000000000..93e01444f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/product_category_state.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ProductCategoryStateEnum", + }, +) + + +class ProductCategoryStateEnum(proto.Message): + r"""State of the product category.""" + + class ProductCategoryState(proto.Enum): + r"""Enum describing the state of the product category. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + The category is enabled. + OBSOLETE (3): + The category is obsolete. Used only for + reporting purposes. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + OBSOLETE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/product_channel.py b/google/ads/googleads/v24/enums/types/product_channel.py new file mode 100644 index 000000000..4c8a85b84 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/product_channel.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ProductChannelEnum", + }, +) + + +class ProductChannelEnum(proto.Message): + r"""Locality of a product offer.""" + + class ProductChannel(proto.Enum): + r"""Enum describing the locality of a product offer. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ONLINE (2): + The item is sold online. + LOCAL (3): + The item is sold in local stores. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ONLINE = 2 + LOCAL = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/product_channel_exclusivity.py b/google/ads/googleads/v24/enums/types/product_channel_exclusivity.py new file mode 100644 index 000000000..5f5757c94 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/product_channel_exclusivity.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ProductChannelExclusivityEnum", + }, +) + + +class ProductChannelExclusivityEnum(proto.Message): + r"""Availability of a product offer.""" + + class ProductChannelExclusivity(proto.Enum): + r"""Enum describing the availability of a product offer. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + SINGLE_CHANNEL (2): + The item is sold through one channel only, + either local stores or online as indicated by + its ProductChannel. + MULTI_CHANNEL (3): + The item is matched to its online or local + stores counterpart, indicating it is available + for purchase in both ShoppingProductChannels. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SINGLE_CHANNEL = 2 + MULTI_CHANNEL = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/product_condition.py b/google/ads/googleads/v24/enums/types/product_condition.py new file mode 100644 index 000000000..dcca3632c --- /dev/null +++ b/google/ads/googleads/v24/enums/types/product_condition.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ProductConditionEnum", + }, +) + + +class ProductConditionEnum(proto.Message): + r"""Condition of a product offer.""" + + class ProductCondition(proto.Enum): + r"""Enum describing the condition of a product offer. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + NEW (3): + The product condition is new. + REFURBISHED (4): + The product condition is refurbished. + USED (5): + The product condition is used. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NEW = 3 + REFURBISHED = 4 + USED = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/product_custom_attribute_index.py b/google/ads/googleads/v24/enums/types/product_custom_attribute_index.py new file mode 100644 index 000000000..2d7598ecf --- /dev/null +++ b/google/ads/googleads/v24/enums/types/product_custom_attribute_index.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ProductCustomAttributeIndexEnum", + }, +) + + +class ProductCustomAttributeIndexEnum(proto.Message): + r"""Container for enum describing the index of the product custom + attribute. + + """ + + class ProductCustomAttributeIndex(proto.Enum): + r"""The index of the product custom attribute. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + INDEX0 (7): + First product custom attribute. + INDEX1 (8): + Second product custom attribute. + INDEX2 (9): + Third product custom attribute. + INDEX3 (10): + Fourth product custom attribute. + INDEX4 (11): + Fifth product custom attribute. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INDEX0 = 7 + INDEX1 = 8 + INDEX2 = 9 + INDEX3 = 10 + INDEX4 = 11 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/product_issue_severity.py b/google/ads/googleads/v24/enums/types/product_issue_severity.py new file mode 100644 index 000000000..aa3662180 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/product_issue_severity.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ProductIssueSeverityEnum", + }, +) + + +class ProductIssueSeverityEnum(proto.Message): + r"""The severity of a product issue.""" + + class ProductIssueSeverity(proto.Enum): + r"""Product issue severity. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + WARNING (2): + The issue limits the performance of the + product in ads. + ERROR (3): + The issue prevents the product from showing + in ads. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + WARNING = 2 + ERROR = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/product_link_invitation_status.py b/google/ads/googleads/v24/enums/types/product_link_invitation_status.py new file mode 100644 index 000000000..8dc329b75 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/product_link_invitation_status.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ProductLinkInvitationStatusEnum", + }, +) + + +class ProductLinkInvitationStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a product + link invitation. + + """ + + class ProductLinkInvitationStatus(proto.Enum): + r"""Describes the possible statuses for an invitation between a + Google Ads customer and another account. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ACCEPTED (2): + The invitation is accepted. + REQUESTED (3): + An invitation has been sent to the other + account. A user on the other account may now + accept the invitation by setting the status to + ACCEPTED. + PENDING_APPROVAL (4): + This invitation has been sent by a user on + the other account. It may be accepted by a user + on this account by setting the status to + ACCEPTED. + REVOKED (5): + The invitation is revoked by the user who + sent the invitation. + REJECTED (6): + The invitation has been rejected by the + invitee. + EXPIRED (7): + The invitation has timed out before being + accepted by the invitee. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ACCEPTED = 2 + REQUESTED = 3 + PENDING_APPROVAL = 4 + REVOKED = 5 + REJECTED = 6 + EXPIRED = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/product_status.py b/google/ads/googleads/v24/enums/types/product_status.py new file mode 100644 index 000000000..4499f1039 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/product_status.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ProductStatusEnum", + }, +) + + +class ProductStatusEnum(proto.Message): + r"""The status of a product indicating whether it can show in + ads. + + """ + + class ProductStatus(proto.Enum): + r"""Enum describing the status of a product. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents values + unknown in this version. + NOT_ELIGIBLE (2): + The product cannot show in ads. + ELIGIBLE_LIMITED (3): + The product can show in ads but may be + limited in where and when it can show due to + identified issues. + ELIGIBLE (4): + The product can show in ads. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NOT_ELIGIBLE = 2 + ELIGIBLE_LIMITED = 3 + ELIGIBLE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/product_type_level.py b/google/ads/googleads/v24/enums/types/product_type_level.py new file mode 100644 index 000000000..98989f4b6 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/product_type_level.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ProductTypeLevelEnum", + }, +) + + +class ProductTypeLevelEnum(proto.Message): + r"""Level of the type of a product offer.""" + + class ProductTypeLevel(proto.Enum): + r"""Enum describing the level of the type of a product offer. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + LEVEL1 (7): + Level 1. + LEVEL2 (8): + Level 2. + LEVEL3 (9): + Level 3. + LEVEL4 (10): + Level 4. + LEVEL5 (11): + Level 5. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LEVEL1 = 7 + LEVEL2 = 8 + LEVEL3 = 9 + LEVEL4 = 10 + LEVEL5 = 11 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/promotion_barcode_type.py b/google/ads/googleads/v24/enums/types/promotion_barcode_type.py new file mode 100644 index 000000000..6ee4246e2 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/promotion_barcode_type.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PromotionBarcodeTypeEnum", + }, +) + + +class PromotionBarcodeTypeEnum(proto.Message): + r"""Container for enum describing a promotion barcode type.""" + + class PromotionBarcodeType(proto.Enum): + r"""A promotion barcode type. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + AZTEC (2): + Aztec 2D barcode format. + Max 350 characters and no links + CODABAR (3): + CODABAR 1D format. + Max 12 characters and no links. Supported + characters include 0123456789-$:/.+ and optional + start and end guards from ABCD. + CODE39 (4): + Code 39 1D format. Max 8 characters and no links. Supported + characters include 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. + \*$/+%. + CODE128 (5): + Code 128 1D format. + Max 18 ASCII characters only and no links + DATA_MATRIX (6): + Data Matrix 2D barcode format. + Max 525 ISO-8859-1 characters only and no links + EAN8 (7): + EAN-8 1D format. + The barcode value should be 7 digits (the check + digit will be computed automatically) or 8 + digits (if you are providing your own check + digit). + EAN13 (8): + EAN-13 1D format. + The barcode value should be 12 digits (the check + digit will be computed automatically) or 13 + digits (if you are providing your own check + digit). + ITF (9): + ITF (Interleaved Two of Five) 1D format. + Must be 14 digits long + PDF417 (10): + PDF417 format. + Max 140 characters and no links + UPC_A (11): + UPC-A 1D format. + The barcode value should be 11 digits (the check + digit will be computed automatically) or 12 + digits (if you are providing your own check + digit). + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AZTEC = 2 + CODABAR = 3 + CODE39 = 4 + CODE128 = 5 + DATA_MATRIX = 6 + EAN8 = 7 + EAN13 = 8 + ITF = 9 + PDF417 = 10 + UPC_A = 11 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/promotion_extension_discount_modifier.py b/google/ads/googleads/v24/enums/types/promotion_extension_discount_modifier.py new file mode 100644 index 000000000..f6812033f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/promotion_extension_discount_modifier.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PromotionExtensionDiscountModifierEnum", + }, +) + + +class PromotionExtensionDiscountModifierEnum(proto.Message): + r"""Container for enum describing possible a promotion extension + discount modifier. + + """ + + class PromotionExtensionDiscountModifier(proto.Enum): + r"""A promotion extension discount modifier. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + UP_TO (2): + 'Up to'. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UP_TO = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/promotion_extension_occasion.py b/google/ads/googleads/v24/enums/types/promotion_extension_occasion.py new file mode 100644 index 000000000..047851f86 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/promotion_extension_occasion.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "PromotionExtensionOccasionEnum", + }, +) + + +class PromotionExtensionOccasionEnum(proto.Message): + r"""Container for enum describing a promotion extension occasion. + For more information about the occasions check: + + https://support.google.com/google-ads/answer/7367521 + + """ + + class PromotionExtensionOccasion(proto.Enum): + r"""A promotion extension occasion. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + NEW_YEARS (2): + New Year's. + CHINESE_NEW_YEAR (3): + Chinese New Year. + VALENTINES_DAY (4): + Valentine's Day. + EASTER (5): + Easter. + MOTHERS_DAY (6): + Mother's Day. + FATHERS_DAY (7): + Father's Day. + LABOR_DAY (8): + Labor Day. + BACK_TO_SCHOOL (9): + Back To School. + HALLOWEEN (10): + Halloween. + BLACK_FRIDAY (11): + Black Friday. + CYBER_MONDAY (12): + Cyber Monday. + CHRISTMAS (13): + Christmas. + BOXING_DAY (14): + Boxing Day. + INDEPENDENCE_DAY (15): + Independence Day in any country. + NATIONAL_DAY (16): + National Day in any country. + END_OF_SEASON (17): + End of any season. + WINTER_SALE (18): + Winter Sale. + SUMMER_SALE (19): + Summer sale. + FALL_SALE (20): + Fall Sale. + SPRING_SALE (21): + Spring Sale. + RAMADAN (22): + Ramadan. + EID_AL_FITR (23): + Eid al-Fitr. + EID_AL_ADHA (24): + Eid al-Adha. + SINGLES_DAY (25): + Singles Day. + WOMENS_DAY (26): + Women's Day. + HOLI (27): + Holi. + PARENTS_DAY (28): + Parent's Day. + ST_NICHOLAS_DAY (29): + St. Nicholas Day. + CARNIVAL (30): + Carnival. + EPIPHANY (31): + Epiphany, also known as Three Kings' Day. + ROSH_HASHANAH (32): + Rosh Hashanah. + PASSOVER (33): + Passover. + HANUKKAH (34): + Hanukkah. + DIWALI (35): + Diwali. + NAVRATRI (36): + Navratri. + SONGKRAN (37): + Available in Thai: Songkran. + YEAR_END_GIFT (38): + Available in Japanese: Year-end Gift. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NEW_YEARS = 2 + CHINESE_NEW_YEAR = 3 + VALENTINES_DAY = 4 + EASTER = 5 + MOTHERS_DAY = 6 + FATHERS_DAY = 7 + LABOR_DAY = 8 + BACK_TO_SCHOOL = 9 + HALLOWEEN = 10 + BLACK_FRIDAY = 11 + CYBER_MONDAY = 12 + CHRISTMAS = 13 + BOXING_DAY = 14 + INDEPENDENCE_DAY = 15 + NATIONAL_DAY = 16 + END_OF_SEASON = 17 + WINTER_SALE = 18 + SUMMER_SALE = 19 + FALL_SALE = 20 + SPRING_SALE = 21 + RAMADAN = 22 + EID_AL_FITR = 23 + EID_AL_ADHA = 24 + SINGLES_DAY = 25 + WOMENS_DAY = 26 + HOLI = 27 + PARENTS_DAY = 28 + ST_NICHOLAS_DAY = 29 + CARNIVAL = 30 + EPIPHANY = 31 + ROSH_HASHANAH = 32 + PASSOVER = 33 + HANUKKAH = 34 + DIWALI = 35 + NAVRATRI = 36 + SONGKRAN = 37 + YEAR_END_GIFT = 38 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/proximity_radius_units.py b/google/ads/googleads/v24/enums/types/proximity_radius_units.py new file mode 100644 index 000000000..365b8b0a7 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/proximity_radius_units.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ProximityRadiusUnitsEnum", + }, +) + + +class ProximityRadiusUnitsEnum(proto.Message): + r"""Container for enum describing unit of radius in proximity.""" + + class ProximityRadiusUnits(proto.Enum): + r"""The unit of radius distance in proximity (for example, MILES) + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + MILES (2): + Miles + KILOMETERS (3): + Kilometers + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MILES = 2 + KILOMETERS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/quality_score_bucket.py b/google/ads/googleads/v24/enums/types/quality_score_bucket.py new file mode 100644 index 000000000..10bd00ad4 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/quality_score_bucket.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "QualityScoreBucketEnum", + }, +) + + +class QualityScoreBucketEnum(proto.Message): + r"""The relative performance compared to other advertisers.""" + + class QualityScoreBucket(proto.Enum): + r"""Enum listing the possible quality score buckets. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BELOW_AVERAGE (2): + Quality of the creative is below average. + AVERAGE (3): + Quality of the creative is average. + ABOVE_AVERAGE (4): + Quality of the creative is above average. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BELOW_AVERAGE = 2 + AVERAGE = 3 + ABOVE_AVERAGE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/reach_plan_age_range.py b/google/ads/googleads/v24/enums/types/reach_plan_age_range.py new file mode 100644 index 000000000..8feda55be --- /dev/null +++ b/google/ads/googleads/v24/enums/types/reach_plan_age_range.py @@ -0,0 +1,141 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ReachPlanAgeRangeEnum", + }, +) + + +class ReachPlanAgeRangeEnum(proto.Message): + r"""Message describing plannable age ranges.""" + + class ReachPlanAgeRange(proto.Enum): + r"""Possible plannable age range values. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + AGE_RANGE_18_24 (503001): + Between 18 and 24 years old. + AGE_RANGE_18_34 (2): + Between 18 and 34 years old. + AGE_RANGE_18_44 (3): + Between 18 and 44 years old. + AGE_RANGE_18_49 (4): + Between 18 and 49 years old. + AGE_RANGE_18_54 (5): + Between 18 and 54 years old. + AGE_RANGE_18_64 (6): + Between 18 and 64 years old. + AGE_RANGE_18_65_UP (7): + Between 18 and 65+ years old. + AGE_RANGE_21_34 (8): + Between 21 and 34 years old. + AGE_RANGE_21_44 (22): + Between 21 and 44 years old. + AGE_RANGE_21_49 (23): + Between 21 and 49 years old. + AGE_RANGE_21_54 (24): + Between 21 and 54 years old. + AGE_RANGE_21_64 (25): + Between 21 and 64 years old. + AGE_RANGE_21_65_UP (26): + Between 21 and 65+ years old. + AGE_RANGE_25_34 (503002): + Between 25 and 34 years old. + AGE_RANGE_25_44 (9): + Between 25 and 44 years old. + AGE_RANGE_25_49 (10): + Between 25 and 49 years old. + AGE_RANGE_25_54 (11): + Between 25 and 54 years old. + AGE_RANGE_25_64 (12): + Between 25 and 64 years old. + AGE_RANGE_25_65_UP (13): + Between 25 and 65+ years old. + AGE_RANGE_35_44 (503003): + Between 35 and 44 years old. + AGE_RANGE_35_49 (14): + Between 35 and 49 years old. + AGE_RANGE_35_54 (15): + Between 35 and 54 years old. + AGE_RANGE_35_64 (16): + Between 35 and 64 years old. + AGE_RANGE_35_65_UP (17): + Between 35 and 65+ years old. + AGE_RANGE_45_54 (503004): + Between 45 and 54 years old. + AGE_RANGE_45_64 (18): + Between 45 and 64 years old. + AGE_RANGE_45_65_UP (19): + Between 45 and 65+ years old. + AGE_RANGE_50_65_UP (20): + Between 50 and 65+ years old. + AGE_RANGE_55_64 (503005): + Between 55 and 64 years old. + AGE_RANGE_55_65_UP (21): + Between 55 and 65+ years old. + AGE_RANGE_65_UP (503006): + 65 years old and beyond. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AGE_RANGE_18_24 = 503001 + AGE_RANGE_18_34 = 2 + AGE_RANGE_18_44 = 3 + AGE_RANGE_18_49 = 4 + AGE_RANGE_18_54 = 5 + AGE_RANGE_18_64 = 6 + AGE_RANGE_18_65_UP = 7 + AGE_RANGE_21_34 = 8 + AGE_RANGE_21_44 = 22 + AGE_RANGE_21_49 = 23 + AGE_RANGE_21_54 = 24 + AGE_RANGE_21_64 = 25 + AGE_RANGE_21_65_UP = 26 + AGE_RANGE_25_34 = 503002 + AGE_RANGE_25_44 = 9 + AGE_RANGE_25_49 = 10 + AGE_RANGE_25_54 = 11 + AGE_RANGE_25_64 = 12 + AGE_RANGE_25_65_UP = 13 + AGE_RANGE_35_44 = 503003 + AGE_RANGE_35_49 = 14 + AGE_RANGE_35_54 = 15 + AGE_RANGE_35_64 = 16 + AGE_RANGE_35_65_UP = 17 + AGE_RANGE_45_54 = 503004 + AGE_RANGE_45_64 = 18 + AGE_RANGE_45_65_UP = 19 + AGE_RANGE_50_65_UP = 20 + AGE_RANGE_55_64 = 503005 + AGE_RANGE_55_65_UP = 21 + AGE_RANGE_65_UP = 503006 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/reach_plan_buying_method.py b/google/ads/googleads/v24/enums/types/reach_plan_buying_method.py new file mode 100644 index 000000000..d29656488 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/reach_plan_buying_method.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ReachPlanBuyingMethodEnum", + }, +) + + +class ReachPlanBuyingMethodEnum(proto.Message): + r"""Container for enum describing reach planning buying methods.""" + + class ReachPlanBuyingMethod(proto.Enum): + r"""The reach plan buying method for an ad product. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + AUCTION (2): + Bidding on ads with a target CPM. + RESERVATION (3): + Buying method that encompasses deal-based and + instant reserve pricing. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AUCTION = 2 + RESERVATION = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/reach_plan_conversion_rate_model.py b/google/ads/googleads/v24/enums/types/reach_plan_conversion_rate_model.py new file mode 100644 index 000000000..beb99c100 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/reach_plan_conversion_rate_model.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ReachPlanConversionRateModelEnum", + }, +) + + +class ReachPlanConversionRateModelEnum(proto.Message): + r"""Container for enum describing the type of model used to + create a conversion rate suggestion for a supported ad product. + + """ + + class ReachPlanConversionRateModel(proto.Enum): + r"""Types of models used to create conversion rate suggestions. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + CUSTOMER_HISTORY (2): + Suggested conversion rate for the + authenticated customer based on the previous 70 + days. + INVENTORY_AGGRESSIVE (3): + Suggested conversion rate based on an + aggressive rate for the entire inventory. + INVENTORY_CONSERVATIVE (4): + Suggested conversion rate based on a + conservative rate for the entire inventory. + INVENTORY_MEDIAN (5): + Suggested conversion rate based on the median + rate for the entire inventory. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER_HISTORY = 2 + INVENTORY_AGGRESSIVE = 3 + INVENTORY_CONSERVATIVE = 4 + INVENTORY_MEDIAN = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/reach_plan_cost_model.py b/google/ads/googleads/v24/enums/types/reach_plan_cost_model.py new file mode 100644 index 000000000..5419a6177 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/reach_plan_cost_model.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ReachPlanCostModelEnum", + }, +) + + +class ReachPlanCostModelEnum(proto.Message): + r"""Container for enum describing cost models available for reach + planning. + + """ + + class ReachPlanCostModel(proto.Enum): + r"""The reach plan cost model for an ad format. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + CPM (2): + Cost per mille (thousand impressions). + CPV (3): + Cost per view. + CPC (4): + Cost per click. + CPA (5): + Cost per action (conversion). + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CPM = 2 + CPV = 3 + CPC = 4 + CPA = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/reach_plan_marketing_objective.py b/google/ads/googleads/v24/enums/types/reach_plan_marketing_objective.py new file mode 100644 index 000000000..7adfab287 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/reach_plan_marketing_objective.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ReachPlanMarketingObjectiveEnum", + }, +) + + +class ReachPlanMarketingObjectiveEnum(proto.Message): + r"""Container for enum describing marketing objectives available + for reach planning. + + """ + + class ReachPlanMarketingObjective(proto.Enum): + r"""Marketing objectives available for reach planning. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + AWARENESS (2): + The objective is to maximize brand visibility + and reach as many relevant people as possible, + making potential customers aware of the brand or + product. + CONSIDERATION (3): + The objective is to encourage potential + customers to learn more about the brand or + products and consider them for a future + purchase. + ACTION (4): + The objective is to persuade potential + customers to take a specific, valuable action, + such as making a purchase, signing up for a + newsletter, or generating a lead. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AWARENESS = 2 + CONSIDERATION = 3 + ACTION = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/reach_plan_network.py b/google/ads/googleads/v24/enums/types/reach_plan_network.py new file mode 100644 index 000000000..add8249d9 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/reach_plan_network.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ReachPlanNetworkEnum", + }, +) + + +class ReachPlanNetworkEnum(proto.Message): + r"""Container for enum describing plannable networks.""" + + class ReachPlanNetwork(proto.Enum): + r"""Possible plannable network values. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used as a return value only. Represents value + unknown in this version. + YOUTUBE (2): + YouTube network. + GOOGLE_VIDEO_PARTNERS (3): + Google Video Partners (GVP) network. + YOUTUBE_AND_GOOGLE_VIDEO_PARTNERS (4): + A combination of the YouTube network and the + Google Video Partners network. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + YOUTUBE = 2 + GOOGLE_VIDEO_PARTNERS = 3 + YOUTUBE_AND_GOOGLE_VIDEO_PARTNERS = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/reach_plan_plannable_user_list_status.py b/google/ads/googleads/v24/enums/types/reach_plan_plannable_user_list_status.py new file mode 100644 index 000000000..cdcc70e41 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/reach_plan_plannable_user_list_status.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ReachPlanPlannableUserListStatusEnum", + }, +) + + +class ReachPlanPlannableUserListStatusEnum(proto.Message): + r"""Container for enum describing the plannable status of a user + list. + + """ + + class ReachPlanPlannableUserListStatus(proto.Enum): + r"""The plannable user list status. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PLANNABLE (2): + The user list is plannable. + UNPLANNABLE (3): + The user list is not plannable. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PLANNABLE = 2 + UNPLANNABLE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/reach_plan_surface.py b/google/ads/googleads/v24/enums/types/reach_plan_surface.py new file mode 100644 index 000000000..b16e107fc --- /dev/null +++ b/google/ads/googleads/v24/enums/types/reach_plan_surface.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ReachPlanSurfaceEnum", + }, +) + + +class ReachPlanSurfaceEnum(proto.Message): + r"""Container for enum describing surfaces available for + targeting in forecasts. Surfaces refer to the available types of + ad inventories such as In-Feed, In-Stream, and Shorts. + + """ + + class ReachPlanSurface(proto.Enum): + r"""Surfaces available to target in reach forecasts. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + DISCOVER_FEED (7): + Discover feed ad surface. + GMAIL (8): + Gmail ad surface. + IN_FEED (2): + In-Feed ad surface. + IN_STREAM_BUMPER (3): + In-Stream bumper ad surface. + IN_STREAM_NON_SKIPPABLE (4): + In-Stream non-skippable ad surface. + IN_STREAM_SKIPPABLE (5): + In-Stream skippable ad surface. + SHORTS (6): + Shorts ad surface. + GOOGLE_DISPLAY_NETWORK (9): + Google Display Network ad surface. + IN_STREAM_NON_SKIPPABLE_THIRTY_SECONDS (10): + In-Stream non-skippable (30 seconds) ad + surface. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DISCOVER_FEED = 7 + GMAIL = 8 + IN_FEED = 2 + IN_STREAM_BUMPER = 3 + IN_STREAM_NON_SKIPPABLE = 4 + IN_STREAM_SKIPPABLE = 5 + SHORTS = 6 + GOOGLE_DISPLAY_NETWORK = 9 + IN_STREAM_NON_SKIPPABLE_THIRTY_SECONDS = 10 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/recommendation_subscription_status.py b/google/ads/googleads/v24/enums/types/recommendation_subscription_status.py new file mode 100644 index 000000000..76539640f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/recommendation_subscription_status.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "RecommendationSubscriptionStatusEnum", + }, +) + + +class RecommendationSubscriptionStatusEnum(proto.Message): + r"""Container for enum describing recommendation subscription + statuses. + + """ + + class RecommendationSubscriptionStatus(proto.Enum): + r"""Enum describing recommendation subscription statuses. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Output-only. Represents a format not yet + defined in this enum. + ENABLED (2): + A subscription in the enabled state will + automatically apply any recommendations of that + type. + PAUSED (3): + Recommendations of the relevant type will not + be automatically applied. Subscriptions cannot + be deleted. Once created, they can only move + between enabled and paused states. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + PAUSED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/recommendation_type.py b/google/ads/googleads/v24/enums/types/recommendation_type.py new file mode 100644 index 000000000..a86eb6ea2 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/recommendation_type.py @@ -0,0 +1,287 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "RecommendationTypeEnum", + }, +) + + +class RecommendationTypeEnum(proto.Message): + r"""Container for enum describing types of recommendations.""" + + class RecommendationType(proto.Enum): + r"""Types of recommendations. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CAMPAIGN_BUDGET (2): + Provides optimized budget recommendations for + campaigns. + KEYWORD (3): + Keyword recommendation. + TEXT_AD (4): + Recommendation to add a new text ad. + TARGET_CPA_OPT_IN (5): + Recommendation to update a campaign to use a + Target CPA bidding strategy. + MAXIMIZE_CONVERSIONS_OPT_IN (6): + Recommendation to update a campaign to use + the Maximize Conversions bidding strategy. + ENHANCED_CPC_OPT_IN (7): + Recommendation to enable Enhanced Cost Per + Click for a campaign. + SEARCH_PARTNERS_OPT_IN (8): + Recommendation to start showing your + campaign's ads on Google Search Partners + Websites. + MAXIMIZE_CLICKS_OPT_IN (9): + Recommendation to update a campaign to use a + Maximize Clicks bidding strategy. + OPTIMIZE_AD_ROTATION (10): + Recommendation to start using the "Optimize" + ad rotation setting for the given ad group. + KEYWORD_MATCH_TYPE (14): + Recommendation to change an existing keyword + from one match type to a broader match type. + MOVE_UNUSED_BUDGET (15): + Recommendation to move unused budget from one + budget to a constrained budget. + FORECASTING_CAMPAIGN_BUDGET (16): + Budget recommendation for campaigns that are expected to + become budget-constrained in the future (as opposed to the + CAMPAIGN_BUDGET recommendation, which applies to campaigns + that are currently budget-constrained). + TARGET_ROAS_OPT_IN (17): + Recommendation to update a campaign to use a + Target ROAS bidding strategy. + RESPONSIVE_SEARCH_AD (18): + Recommendation to add a new responsive search + ad. + MARGINAL_ROI_CAMPAIGN_BUDGET (19): + Budget recommendation for campaigns whose ROI + is predicted to increase with a budget + adjustment. + USE_BROAD_MATCH_KEYWORD (20): + Recommendation to add broad match versions of + keywords for fully automated conversion-based + bidding campaigns. + RESPONSIVE_SEARCH_AD_ASSET (21): + Recommendation to add new responsive search + ad assets. + UPGRADE_SMART_SHOPPING_CAMPAIGN_TO_PERFORMANCE_MAX (22): + Recommendation to upgrade a Smart Shopping + campaign to a Performance Max campaign. + RESPONSIVE_SEARCH_AD_IMPROVE_AD_STRENGTH (23): + Recommendation to improve strength of + responsive search ad. + DISPLAY_EXPANSION_OPT_IN (24): + Recommendation to update a campaign to use + Display Expansion. + UPGRADE_LOCAL_CAMPAIGN_TO_PERFORMANCE_MAX (25): + Recommendation to upgrade a Local campaign to + a Performance Max campaign. + RAISE_TARGET_CPA_BID_TOO_LOW (26): + Recommendation to raise target CPA when it is + too low and there are very few or no + conversions. It is applied asynchronously and + can take minutes depending on the number of ad + groups there are in the related campaign. + FORECASTING_SET_TARGET_ROAS (27): + Recommendation to raise the budget in advance + of a seasonal event that is forecasted to + increase traffic, and change bidding strategy + from maximize conversion value to target ROAS. + CALLOUT_ASSET (28): + Recommendation to add callout assets to + campaign or customer level. + SITELINK_ASSET (29): + Recommendation to add sitelink assets to + campaign or customer level. + CALL_ASSET (30): + Recommendation to add call assets to campaign + or customer level. + SHOPPING_ADD_AGE_GROUP (31): + Recommendation to add the age group attribute + to offers that are demoted because of a missing + age group. + SHOPPING_ADD_COLOR (32): + Recommendation to add a color to offers that + are demoted because of a missing color. + SHOPPING_ADD_GENDER (33): + Recommendation to add a gender to offers that + are demoted because of a missing gender. + SHOPPING_ADD_GTIN (34): + Recommendation to add a GTIN (Global Trade + Item Number) to offers that are demoted because + of a missing GTIN. + SHOPPING_ADD_MORE_IDENTIFIERS (35): + Recommendation to add more identifiers to + offers that are demoted because of missing + identifiers. + SHOPPING_ADD_SIZE (36): + Recommendation to add the size to offers that + are demoted because of a missing size. + SHOPPING_ADD_PRODUCTS_TO_CAMPAIGN (37): + Recommendation informing a customer about a + campaign that cannot serve because no products + are being targeted. + SHOPPING_FIX_DISAPPROVED_PRODUCTS (38): + The shopping recommendation informing a + customer about campaign with a high percentage + of disapproved products. + SHOPPING_TARGET_ALL_OFFERS (39): + Recommendation to create a catch-all campaign + that targets all offers. + SHOPPING_FIX_SUSPENDED_MERCHANT_CENTER_ACCOUNT (40): + Recommendation to fix Merchant Center account + suspension issues. + SHOPPING_FIX_MERCHANT_CENTER_ACCOUNT_SUSPENSION_WARNING (41): + Recommendation to fix Merchant Center account + suspension warning issues. + SHOPPING_MIGRATE_REGULAR_SHOPPING_CAMPAIGN_OFFERS_TO_PERFORMANCE_MAX (42): + Recommendation to migrate offers targeted by + Regular Shopping Campaigns to existing + Performance Max campaigns. + DYNAMIC_IMAGE_EXTENSION_OPT_IN (43): + Recommendation to enable dynamic image + extensions on the account, allowing Google to + find the best images from ad landing pages and + complement text ads. + RAISE_TARGET_CPA (44): + Recommendation to raise Target CPA based on + Google predictions modeled from past + conversions. It is applied asynchronously and + can take minutes depending on the number of ad + groups there are in the related campaign. + LOWER_TARGET_ROAS (45): + Recommendation to lower Target ROAS. + PERFORMANCE_MAX_OPT_IN (46): + Recommendation to opt into Performance Max + campaigns. + IMPROVE_PERFORMANCE_MAX_AD_STRENGTH (47): + Recommendation to improve the asset group + strength of a Performance Max campaign to an + "Excellent" rating. + MIGRATE_DYNAMIC_SEARCH_ADS_CAMPAIGN_TO_PERFORMANCE_MAX (48): + Recommendation to migrate Dynamic Search Ads + to Performance Max campaigns. + FORECASTING_SET_TARGET_CPA (49): + Recommendation to set a target CPA for + campaigns that do not have one specified, in + advance of a seasonal event that is forecasted + to increase traffic. + SET_TARGET_CPA (50): + Recommendation to set a target CPA for + campaigns that do not have one specified. + SET_TARGET_ROAS (51): + Recommendation to set a target ROAS for + campaigns that do not have one specified. + MAXIMIZE_CONVERSION_VALUE_OPT_IN (52): + Recommendation to update a campaign to use + the Maximize Conversion Value bidding strategy. + IMPROVE_GOOGLE_TAG_COVERAGE (53): + Recommendation to deploy Google Tag on more + pages. + PERFORMANCE_MAX_FINAL_URL_OPT_IN (54): + Recommendation to turn on Final URL expansion + for your Performance Max campaigns. + REFRESH_CUSTOMER_MATCH_LIST (55): + Recommendation to update a customer list that + hasn't been updated in the last 90 days. + CUSTOM_AUDIENCE_OPT_IN (56): + Recommendation to create a custom audience. + LEAD_FORM_ASSET (57): + Recommendation to add lead form assets to + campaign or customer level. + IMPROVE_DEMAND_GEN_AD_STRENGTH (58): + Recommendation to improve the strength of ads + in Demand Gen campaigns. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CAMPAIGN_BUDGET = 2 + KEYWORD = 3 + TEXT_AD = 4 + TARGET_CPA_OPT_IN = 5 + MAXIMIZE_CONVERSIONS_OPT_IN = 6 + ENHANCED_CPC_OPT_IN = 7 + SEARCH_PARTNERS_OPT_IN = 8 + MAXIMIZE_CLICKS_OPT_IN = 9 + OPTIMIZE_AD_ROTATION = 10 + KEYWORD_MATCH_TYPE = 14 + MOVE_UNUSED_BUDGET = 15 + FORECASTING_CAMPAIGN_BUDGET = 16 + TARGET_ROAS_OPT_IN = 17 + RESPONSIVE_SEARCH_AD = 18 + MARGINAL_ROI_CAMPAIGN_BUDGET = 19 + USE_BROAD_MATCH_KEYWORD = 20 + RESPONSIVE_SEARCH_AD_ASSET = 21 + UPGRADE_SMART_SHOPPING_CAMPAIGN_TO_PERFORMANCE_MAX = 22 + RESPONSIVE_SEARCH_AD_IMPROVE_AD_STRENGTH = 23 + DISPLAY_EXPANSION_OPT_IN = 24 + UPGRADE_LOCAL_CAMPAIGN_TO_PERFORMANCE_MAX = 25 + RAISE_TARGET_CPA_BID_TOO_LOW = 26 + FORECASTING_SET_TARGET_ROAS = 27 + CALLOUT_ASSET = 28 + SITELINK_ASSET = 29 + CALL_ASSET = 30 + SHOPPING_ADD_AGE_GROUP = 31 + SHOPPING_ADD_COLOR = 32 + SHOPPING_ADD_GENDER = 33 + SHOPPING_ADD_GTIN = 34 + SHOPPING_ADD_MORE_IDENTIFIERS = 35 + SHOPPING_ADD_SIZE = 36 + SHOPPING_ADD_PRODUCTS_TO_CAMPAIGN = 37 + SHOPPING_FIX_DISAPPROVED_PRODUCTS = 38 + SHOPPING_TARGET_ALL_OFFERS = 39 + SHOPPING_FIX_SUSPENDED_MERCHANT_CENTER_ACCOUNT = 40 + SHOPPING_FIX_MERCHANT_CENTER_ACCOUNT_SUSPENSION_WARNING = 41 + SHOPPING_MIGRATE_REGULAR_SHOPPING_CAMPAIGN_OFFERS_TO_PERFORMANCE_MAX = ( + 42 + ) + DYNAMIC_IMAGE_EXTENSION_OPT_IN = 43 + RAISE_TARGET_CPA = 44 + LOWER_TARGET_ROAS = 45 + PERFORMANCE_MAX_OPT_IN = 46 + IMPROVE_PERFORMANCE_MAX_AD_STRENGTH = 47 + MIGRATE_DYNAMIC_SEARCH_ADS_CAMPAIGN_TO_PERFORMANCE_MAX = 48 + FORECASTING_SET_TARGET_CPA = 49 + SET_TARGET_CPA = 50 + SET_TARGET_ROAS = 51 + MAXIMIZE_CONVERSION_VALUE_OPT_IN = 52 + IMPROVE_GOOGLE_TAG_COVERAGE = 53 + PERFORMANCE_MAX_FINAL_URL_OPT_IN = 54 + REFRESH_CUSTOMER_MATCH_LIST = 55 + CUSTOM_AUDIENCE_OPT_IN = 56 + LEAD_FORM_ASSET = 57 + IMPROVE_DEMAND_GEN_AD_STRENGTH = 58 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/regulatory_fee_type.py b/google/ads/googleads/v24/enums/types/regulatory_fee_type.py new file mode 100644 index 000000000..1ab6a4e05 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/regulatory_fee_type.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "RegulatoryFeeTypeEnum", + }, +) + + +class RegulatoryFeeTypeEnum(proto.Message): + r"""Container for enum describing the type of regulatory fees.""" + + class RegulatoryFeeType(proto.Enum): + r"""The possible type of regulatory fees. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + AUSTRIA_DST_FEE (2): + Represents Austria DST fee. + TURKIYE_REGULATORY_OPERATING_COST (3): + Represents Türkiye regulatory operating cost. + UK_DST_FEE (4): + Represents UK DST fee. + SPAIN_REGULATORY_OPERATING_COST (5): + Represents Spain regulatory operating cost. + FRANCE_REGULATORY_OPERATING_COST (6): + Represents France regulatory operating cost. + ITALY_REGULATORY_OPERATING_COST (7): + Represents Italy regulatory operating cost. + INDIA_REGULATORY_OPERATING_COST (8): + Represents India regulatory operating cost. + POLAND_REGULATORY_OPERATING_COST (9): + Represents Poland regulatory operating cost. + OPERATING_CHARGES (10): + Represents operating charges. + CANADA_DST_FEE (11): + Represents Canada DST fee. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AUSTRIA_DST_FEE = 2 + TURKIYE_REGULATORY_OPERATING_COST = 3 + UK_DST_FEE = 4 + SPAIN_REGULATORY_OPERATING_COST = 5 + FRANCE_REGULATORY_OPERATING_COST = 6 + ITALY_REGULATORY_OPERATING_COST = 7 + INDIA_REGULATORY_OPERATING_COST = 8 + POLAND_REGULATORY_OPERATING_COST = 9 + OPERATING_CHARGES = 10 + CANADA_DST_FEE = 11 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/reservation_request_type.py b/google/ads/googleads/v24/enums/types/reservation_request_type.py new file mode 100644 index 000000000..58f99972e --- /dev/null +++ b/google/ads/googleads/v24/enums/types/reservation_request_type.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ReservationRequestTypeEnum", + }, +) + + +class ReservationRequestTypeEnum(proto.Message): + r"""Container for enum describing the request type of a + reservation booking. + + """ + + class ReservationRequestType(proto.Enum): + r"""Enum describing the request type of a reservation booking. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BOOK (2): + Book the campaign. The campaign must have + ENABLED status. If the campaign has a hold, it + will remove the hold and confirm the contract. + HOLD (3): + Hold the inventory for the campaign. The + campaign must have PAUSED status to request a + hold. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BOOK = 2 + HOLD = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/resource_change_operation.py b/google/ads/googleads/v24/enums/types/resource_change_operation.py new file mode 100644 index 000000000..aef6603c2 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/resource_change_operation.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ResourceChangeOperationEnum", + }, +) + + +class ResourceChangeOperationEnum(proto.Message): + r"""Container for enum describing resource change operations + in the ChangeEvent resource. + + """ + + class ResourceChangeOperation(proto.Enum): + r"""The operation on the changed resource in change_event resource. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + Used for return value only. Represents an + unclassified operation unknown in this version. + CREATE (2): + The resource was created. + UPDATE (3): + The resource was modified. + REMOVE (4): + The resource was removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CREATE = 2 + UPDATE = 3 + REMOVE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/resource_limit_type.py b/google/ads/googleads/v24/enums/types/resource_limit_type.py new file mode 100644 index 000000000..4e3534e88 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/resource_limit_type.py @@ -0,0 +1,632 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ResourceLimitTypeEnum", + }, +) + + +class ResourceLimitTypeEnum(proto.Message): + r"""Container for enum describing possible resource limit types.""" + + class ResourceLimitType(proto.Enum): + r"""Resource limit type. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + Used for return value only. Represents an + unclassified operation unknown in this version. + CAMPAIGNS_PER_CUSTOMER (2): + Number of ENABLED and PAUSED campaigns per + customer. + BASE_CAMPAIGNS_PER_CUSTOMER (3): + Number of ENABLED and PAUSED base campaigns + per customer. + EXPERIMENT_CAMPAIGNS_PER_CUSTOMER (105): + Number of ENABLED and PAUSED experiment + campaigns per customer. + HOTEL_CAMPAIGNS_PER_CUSTOMER (4): + Number of ENABLED and PAUSED Hotel campaigns + per customer. + SMART_SHOPPING_CAMPAIGNS_PER_CUSTOMER (5): + Number of ENABLED and PAUSED Smart Shopping + campaigns per customer. + AD_GROUPS_PER_CAMPAIGN (6): + Number of ENABLED ad groups per campaign. + AD_GROUPS_PER_SHOPPING_CAMPAIGN (8): + Number of ENABLED ad groups per Shopping + campaign. + AD_GROUPS_PER_HOTEL_CAMPAIGN (9): + Number of ENABLED ad groups per Hotel + campaign. + REPORTING_AD_GROUPS_PER_LOCAL_CAMPAIGN (10): + Number of ENABLED reporting ad groups per + local campaign. + REPORTING_AD_GROUPS_PER_APP_CAMPAIGN (11): + Number of ENABLED reporting ad groups per App + campaign. It includes app campaign and app + campaign for engagement. + MANAGED_AD_GROUPS_PER_SMART_CAMPAIGN (52): + Number of ENABLED managed ad groups per smart + campaign. + AD_GROUP_CRITERIA_PER_CUSTOMER (12): + Number of ENABLED ad group criteria per + customer. An ad group criterion is considered as + ENABLED if: + + 1. it's not REMOVED + 2. its ad group is not REMOVED + 3. its campaign is not REMOVED. + BASE_AD_GROUP_CRITERIA_PER_CUSTOMER (13): + Number of ad group criteria across all base + campaigns for a customer. + EXPERIMENT_AD_GROUP_CRITERIA_PER_CUSTOMER (107): + Number of ad group criteria across all + experiment campaigns for a customer. + AD_GROUP_CRITERIA_PER_CAMPAIGN (14): + Number of ENABLED ad group criteria per + campaign. An ad group criterion is considered as + ENABLED if: + + 1. it's not REMOVED + 2. its ad group is not REMOVED. + CAMPAIGN_CRITERIA_PER_CUSTOMER (15): + Number of ENABLED campaign criteria per + customer. + BASE_CAMPAIGN_CRITERIA_PER_CUSTOMER (16): + Number of ENABLED campaign criteria across + all base campaigns for a customer. + EXPERIMENT_CAMPAIGN_CRITERIA_PER_CUSTOMER (108): + Number of ENABLED campaign criteria across + all experiment campaigns for a customer. + WEBPAGE_CRITERIA_PER_CUSTOMER (17): + Number of ENABLED webpage criteria per + customer, including campaign level and ad group + level. + BASE_WEBPAGE_CRITERIA_PER_CUSTOMER (18): + Number of ENABLED webpage criteria across all + base campaigns for a customer. + EXPERIMENT_WEBPAGE_CRITERIA_PER_CUSTOMER (19): + Meximum number of ENABLED webpage criteria + across all experiment campaigns for a customer. + COMBINED_AUDIENCE_CRITERIA_PER_AD_GROUP (20): + Number of combined audience criteria per ad + group. + CUSTOMER_NEGATIVE_PLACEMENT_CRITERIA_PER_CUSTOMER (21): + Limit for placement criterion type group in + customer negative criterion. + CUSTOMER_NEGATIVE_YOUTUBE_CHANNEL_CRITERIA_PER_CUSTOMER (22): + Limit for YouTube TV channels in customer + negative criterion. + CRITERIA_PER_AD_GROUP (23): + Number of ENABLED criteria per ad group. + LISTING_GROUPS_PER_AD_GROUP (24): + Number of listing group criteria per ad + group. + EXPLICITLY_SHARED_BUDGETS_PER_CUSTOMER (25): + Number of ENABLED explicitly shared budgets + per customer. + IMPLICITLY_SHARED_BUDGETS_PER_CUSTOMER (26): + Number of ENABLED implicitly shared budgets + per customer. + COMBINED_AUDIENCE_CRITERIA_PER_CAMPAIGN (27): + Number of combined audience criteria per + campaign. + NEGATIVE_KEYWORDS_PER_CAMPAIGN (28): + Number of negative keywords per campaign. + NEGATIVE_PLACEMENTS_PER_CAMPAIGN (29): + Number of excluded campaign criteria in + placement dimension, for example, placement, + mobile application, YouTube channel, etc. The + API criterion type is NOT limited to placement + only, and this does not include exclusions at + the ad group or other levels. + GEO_TARGETS_PER_CAMPAIGN (30): + Number of geo targets per campaign. + NEGATIVE_IP_BLOCKS_PER_CAMPAIGN (32): + Number of negative IP blocks per campaign. + PROXIMITIES_PER_CAMPAIGN (33): + Number of proximity targets per campaign. + LISTING_SCOPES_PER_SHOPPING_CAMPAIGN (34): + Number of listing scopes per Shopping + campaign. + LISTING_SCOPES_PER_NON_SHOPPING_CAMPAIGN (35): + Number of listing scopes per non-Shopping + campaign. + NEGATIVE_KEYWORDS_PER_SHARED_SET (36): + Number of criteria per negative keyword + shared set. + NEGATIVE_PLACEMENTS_PER_SHARED_SET (37): + Number of criteria per negative placement + shared set. + SHARED_SETS_PER_CUSTOMER_FOR_TYPE_DEFAULT (40): + Default number of shared sets allowed per + type per customer. + SHARED_SETS_PER_CUSTOMER_FOR_NEGATIVE_PLACEMENT_LIST_LOWER (41): + Number of shared sets of negative placement + list type for a manager customer. + HOTEL_ADVANCE_BOOKING_WINDOW_BID_MODIFIERS_PER_AD_GROUP (44): + Number of hotel_advance_booking_window bid modifiers per ad + group. + BIDDING_STRATEGIES_PER_CUSTOMER (45): + Number of ENABLED shared bidding strategies + per customer. + BASIC_USER_LISTS_PER_CUSTOMER (47): + Number of open basic user lists per customer. + LOGICAL_USER_LISTS_PER_CUSTOMER (48): + Number of open logical user lists per + customer. + RULE_BASED_USER_LISTS_PER_CUSTOMER (153): + Number of open rule based user lists per + customer. + BASE_AD_GROUP_ADS_PER_CUSTOMER (53): + Number of ENABLED and PAUSED ad group ads + across all base campaigns for a customer. + EXPERIMENT_AD_GROUP_ADS_PER_CUSTOMER (54): + Number of ENABLED and PAUSED ad group ads + across all experiment campaigns for a customer. + AD_GROUP_ADS_PER_CAMPAIGN (55): + Number of ENABLED and PAUSED ad group ads per + campaign. + TEXT_AND_OTHER_ADS_PER_AD_GROUP (56): + Number of ENABLED ads per ad group that do + not fall in to other buckets. Includes text and + many other types. + IMAGE_ADS_PER_AD_GROUP (57): + Number of ENABLED image ads per ad group. + SHOPPING_SMART_ADS_PER_AD_GROUP (58): + Number of ENABLED shopping smart ads per ad + group. + RESPONSIVE_SEARCH_ADS_PER_AD_GROUP (59): + Number of ENABLED responsive search ads per + ad group. + APP_ADS_PER_AD_GROUP (60): + Number of ENABLED app ads per ad group. + APP_ENGAGEMENT_ADS_PER_AD_GROUP (61): + Number of ENABLED app engagement ads per ad + group. + LOCAL_ADS_PER_AD_GROUP (62): + Number of ENABLED local ads per ad group. + VIDEO_ADS_PER_AD_GROUP (63): + Number of ENABLED video ads per ad group. + LEAD_FORM_CAMPAIGN_ASSETS_PER_CAMPAIGN (143): + Number of ENABLED lead form CampaignAssets + per campaign. + PROMOTION_CUSTOMER_ASSETS_PER_CUSTOMER (79): + Number of ENABLED promotion CustomerAssets + per customer. + PROMOTION_CAMPAIGN_ASSETS_PER_CAMPAIGN (80): + Number of ENABLED promotion CampaignAssets + per campaign. + PROMOTION_AD_GROUP_ASSETS_PER_AD_GROUP (81): + Number of ENABLED promotion AdGroupAssets per + ad group. + CALLOUT_CUSTOMER_ASSETS_PER_CUSTOMER (134): + Number of ENABLED callout CustomerAssets per + customer. + CALLOUT_CAMPAIGN_ASSETS_PER_CAMPAIGN (135): + Number of ENABLED callout CampaignAssets per + campaign. + CALLOUT_AD_GROUP_ASSETS_PER_AD_GROUP (136): + Number of ENABLED callout AdGroupAssets per + ad group. + SITELINK_CUSTOMER_ASSETS_PER_CUSTOMER (137): + Number of ENABLED sitelink CustomerAssets per + customer. + SITELINK_CAMPAIGN_ASSETS_PER_CAMPAIGN (138): + Number of ENABLED sitelink CampaignAssets per + campaign. + SITELINK_AD_GROUP_ASSETS_PER_AD_GROUP (139): + Number of ENABLED sitelink AdGroupAssets per + ad group. + STRUCTURED_SNIPPET_CUSTOMER_ASSETS_PER_CUSTOMER (140): + Number of ENABLED structured snippet + CustomerAssets per customer. + STRUCTURED_SNIPPET_CAMPAIGN_ASSETS_PER_CAMPAIGN (141): + Number of ENABLED structured snippet + CampaignAssets per campaign. + STRUCTURED_SNIPPET_AD_GROUP_ASSETS_PER_AD_GROUP (142): + Number of ENABLED structured snippet + AdGroupAssets per ad group. + MOBILE_APP_CUSTOMER_ASSETS_PER_CUSTOMER (144): + Number of ENABLED mobile app CustomerAssets + per customer. + MOBILE_APP_CAMPAIGN_ASSETS_PER_CAMPAIGN (145): + Number of ENABLED mobile app CampaignAssets + per campaign. + MOBILE_APP_AD_GROUP_ASSETS_PER_AD_GROUP (146): + Number of ENABLED mobile app AdGroupAssets + per ad group. + HOTEL_CALLOUT_CUSTOMER_ASSETS_PER_CUSTOMER (147): + Number of ENABLED hotel callout + CustomerAssets per customer. + HOTEL_CALLOUT_CAMPAIGN_ASSETS_PER_CAMPAIGN (148): + Number of ENABLED hotel callout + CampaignAssets per campaign. + HOTEL_CALLOUT_AD_GROUP_ASSETS_PER_AD_GROUP (149): + Number of ENABLED hotel callout AdGroupAssets + per ad group. + CALL_CUSTOMER_ASSETS_PER_CUSTOMER (150): + Number of ENABLED call CustomerAssets per + customer. + CALL_CAMPAIGN_ASSETS_PER_CAMPAIGN (151): + Number of ENABLED call CampaignAssets per + campaign. + CALL_AD_GROUP_ASSETS_PER_AD_GROUP (152): + Number of ENABLED call AdGroupAssets per ad + group. + PRICE_CUSTOMER_ASSETS_PER_CUSTOMER (154): + Number of ENABLED price CustomerAssets per + customer. + PRICE_CAMPAIGN_ASSETS_PER_CAMPAIGN (155): + Number of ENABLED price CampaignAssets per + campaign. + PRICE_AD_GROUP_ASSETS_PER_AD_GROUP (156): + Number of ENABLED price AdGroupAssets per ad + group. + AD_IMAGE_CAMPAIGN_ASSETS_PER_CAMPAIGN (175): + Number of ENABLED ad image CampaignAssets per + campaign. + AD_IMAGE_AD_GROUP_ASSETS_PER_AD_GROUP (176): + Number of ENABLED ad image AdGroupAssets per + ad group. + PAGE_FEED_ASSET_SETS_PER_CUSTOMER (157): + Number of ENABLED page feed asset sets per + customer. + DYNAMIC_EDUCATION_FEED_ASSET_SETS_PER_CUSTOMER (158): + Number of ENABLED dynamic education feed + asset sets per customer. + ASSETS_PER_PAGE_FEED_ASSET_SET (159): + Number of ENABLED assets per page feed asset + set. + ASSETS_PER_DYNAMIC_EDUCATION_FEED_ASSET_SET (160): + Number of ENABLED assets per dynamic + education asset set. + DYNAMIC_REAL_ESTATE_ASSET_SETS_PER_CUSTOMER (161): + Number of ENABLED dynamic real estate asset + sets per customer. + ASSETS_PER_DYNAMIC_REAL_ESTATE_ASSET_SET (162): + Number of ENABLED assets per dynamic real + estate asset set. + DYNAMIC_CUSTOM_ASSET_SETS_PER_CUSTOMER (163): + Number of ENABLED dynamic custom asset sets + per customer. + ASSETS_PER_DYNAMIC_CUSTOM_ASSET_SET (164): + Number of ENABLED assets per dynamic custom + asset set. + DYNAMIC_HOTELS_AND_RENTALS_ASSET_SETS_PER_CUSTOMER (165): + Number of ENABLED dynamic hotels and rentals + asset sets per customer. + ASSETS_PER_DYNAMIC_HOTELS_AND_RENTALS_ASSET_SET (166): + Number of ENABLED assets per dynamic hotels + and rentals asset set. + DYNAMIC_LOCAL_ASSET_SETS_PER_CUSTOMER (167): + Number of ENABLED dynamic local asset sets + per customer. + ASSETS_PER_DYNAMIC_LOCAL_ASSET_SET (168): + Number of ENABLED assets per dynamic local + asset set. + DYNAMIC_FLIGHTS_ASSET_SETS_PER_CUSTOMER (169): + Number of ENABLED dynamic flights asset sets + per customer. + ASSETS_PER_DYNAMIC_FLIGHTS_ASSET_SET (170): + Number of ENABLED assets per dynamic flights + asset set. + DYNAMIC_TRAVEL_ASSET_SETS_PER_CUSTOMER (171): + Number of ENABLED dynamic travel asset sets + per customer. + ASSETS_PER_DYNAMIC_TRAVEL_ASSET_SET (172): + Number of ENABLED assets per dynamic travel + asset set. + DYNAMIC_JOBS_ASSET_SETS_PER_CUSTOMER (173): + Number of ENABLED dynamic jobs asset sets per + customer. + ASSETS_PER_DYNAMIC_JOBS_ASSET_SET (174): + Number of ENABLED assets per dynamic jobs + asset set. + BUSINESS_NAME_CAMPAIGN_ASSETS_PER_CAMPAIGN (179): + Number of ENABLED business name + CampaignAssets per campaign. + BUSINESS_LOGO_CAMPAIGN_ASSETS_PER_CAMPAIGN (180): + Number of ENABLED business logo + CampaignAssets per campaign. + VERSIONS_PER_AD (82): + Number of versions per ad. + USER_FEEDS_PER_CUSTOMER (90): + Number of ENABLED user feeds per customer. + SYSTEM_FEEDS_PER_CUSTOMER (91): + Number of ENABLED system feeds per customer. + FEED_ATTRIBUTES_PER_FEED (92): + Number of feed attributes per feed. + FEED_ITEMS_PER_CUSTOMER (94): + Number of ENABLED feed items per customer. + CAMPAIGN_FEEDS_PER_CUSTOMER (95): + Number of ENABLED campaign feeds per + customer. + BASE_CAMPAIGN_FEEDS_PER_CUSTOMER (96): + Number of ENABLED campaign feeds across all + base campaigns for a customer. + EXPERIMENT_CAMPAIGN_FEEDS_PER_CUSTOMER (109): + Number of ENABLED campaign feeds across all + experiment campaigns for a customer. + AD_GROUP_FEEDS_PER_CUSTOMER (97): + Number of ENABLED ad group feeds per + customer. + BASE_AD_GROUP_FEEDS_PER_CUSTOMER (98): + Number of ENABLED ad group feeds across all + base campaigns for a customer. + EXPERIMENT_AD_GROUP_FEEDS_PER_CUSTOMER (110): + Number of ENABLED ad group feeds across all + experiment campaigns for a customer. + AD_GROUP_FEEDS_PER_CAMPAIGN (99): + Number of ENABLED ad group feeds per + campaign. + FEED_ITEM_SETS_PER_CUSTOMER (100): + Number of ENABLED feed items per customer. + FEED_ITEMS_PER_FEED_ITEM_SET (101): + Number of feed items per feed item set. + CAMPAIGN_EXPERIMENTS_PER_CUSTOMER (112): + Number of ENABLED campaign experiments per + customer. + EXPERIMENT_ARMS_PER_VIDEO_EXPERIMENT (113): + Number of video experiment arms per + experiment. + OWNED_LABELS_PER_CUSTOMER (115): + Number of owned labels per customer. + LABELS_PER_CAMPAIGN (117): + Number of applied labels per campaign. + LABELS_PER_AD_GROUP (118): + Number of applied labels per ad group. + LABELS_PER_AD_GROUP_AD (119): + Number of applied labels per ad group ad. + LABELS_PER_AD_GROUP_CRITERION (120): + Number of applied labels per ad group + criterion. + TARGET_CUSTOMERS_PER_LABEL (121): + Number of customers with a single label + applied. + KEYWORD_PLANS_PER_USER_PER_CUSTOMER (122): + Number of ENABLED keyword plans per user per + customer. The limit is applied per pair because by default a plan is + private to a user of a customer. Each user of a + customer has their own independent limit. + KEYWORD_PLAN_AD_GROUP_KEYWORDS_PER_KEYWORD_PLAN (123): + Number of keyword plan ad group keywords per + keyword plan. + KEYWORD_PLAN_AD_GROUPS_PER_KEYWORD_PLAN (124): + Number of keyword plan ad groups per keyword + plan. + KEYWORD_PLAN_NEGATIVE_KEYWORDS_PER_KEYWORD_PLAN (125): + Number of keyword plan negative keywords + (both campaign and ad group) per keyword plan. + KEYWORD_PLAN_CAMPAIGNS_PER_KEYWORD_PLAN (126): + Number of keyword plan campaigns per keyword + plan. + CONVERSION_ACTIONS_PER_CUSTOMER (128): + Number of ENABLED conversion actions per + customer. + BATCH_JOB_OPERATIONS_PER_JOB (130): + Number of operations in a single batch job. + BATCH_JOBS_PER_CUSTOMER (131): + Number of PENDING or ENABLED batch jobs per + customer. + HOTEL_CHECK_IN_DATE_RANGE_BID_MODIFIERS_PER_AD_GROUP (132): + Number of hotel check-in date range bid + modifiers per ad agroup. + SHARED_SETS_PER_ACCOUNT_FOR_ACCOUNT_LEVEL_NEGATIVE_KEYWORDS (177): + Number of shared sets of type + ACCOUNT_LEVEL_NEGATIVE_KEYWORDS per account. + ACCOUNT_LEVEL_NEGATIVE_KEYWORDS_PER_SHARED_SET (178): + Number of keywords per ACCOUNT_LEVEL_NEGATIVE_KEYWORDS + shared set. + ENABLED_ASSET_PER_HOTEL_PROPERTY_ASSET_SET (181): + Maximum number of asset per hotel property + asset set. + ENABLED_HOTEL_PROPERTY_ASSET_LINKS_PER_ASSET_GROUP (182): + Maximum number of enabled hotel property + assets per asset group. + BRANDS_PER_SHARED_SET (183): + Number of criteria per brand shared set. + ENABLED_BRAND_LIST_CRITERIA_PER_CAMPAIGN (184): + Number of active brand list criteria per + campaign. + SHARED_SETS_PER_ACCOUNT_FOR_BRAND (185): + Maximum number of shared sets of brand type + for an account. + LOOKALIKE_USER_LISTS_PER_CUSTOMER (186): + Maximum number of lookalike lists per + customer. + LOGO_CAMPAIGN_ASSETS_PER_CAMPAIGN (187): + Total number of enabled IMAGE CampaignAssets with LOGO and + LANDSCAPE_LOGO field types per campaign. + BUSINESS_MESSAGE_ASSET_LINKS_PER_CUSTOMER (188): + Maximum number of active business message + asset links at customer level. + WHATSAPP_BUSINESS_MESSAGE_ASSET_LINKS_PER_CAMPAIGN (189): + Maximum number of active WhatsApp business + message asset links at campaign level. + WHATSAPP_BUSINESS_MESSAGE_ASSET_LINKS_PER_AD_GROUP (190): + Maximum number of active WhatsApp business + message asset links at ad group level. + BRAND_LIST_CRITERIA_PER_AD_GROUP (193): + Number of ENABLED brand list criteria per ad + group. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CAMPAIGNS_PER_CUSTOMER = 2 + BASE_CAMPAIGNS_PER_CUSTOMER = 3 + EXPERIMENT_CAMPAIGNS_PER_CUSTOMER = 105 + HOTEL_CAMPAIGNS_PER_CUSTOMER = 4 + SMART_SHOPPING_CAMPAIGNS_PER_CUSTOMER = 5 + AD_GROUPS_PER_CAMPAIGN = 6 + AD_GROUPS_PER_SHOPPING_CAMPAIGN = 8 + AD_GROUPS_PER_HOTEL_CAMPAIGN = 9 + REPORTING_AD_GROUPS_PER_LOCAL_CAMPAIGN = 10 + REPORTING_AD_GROUPS_PER_APP_CAMPAIGN = 11 + MANAGED_AD_GROUPS_PER_SMART_CAMPAIGN = 52 + AD_GROUP_CRITERIA_PER_CUSTOMER = 12 + BASE_AD_GROUP_CRITERIA_PER_CUSTOMER = 13 + EXPERIMENT_AD_GROUP_CRITERIA_PER_CUSTOMER = 107 + AD_GROUP_CRITERIA_PER_CAMPAIGN = 14 + CAMPAIGN_CRITERIA_PER_CUSTOMER = 15 + BASE_CAMPAIGN_CRITERIA_PER_CUSTOMER = 16 + EXPERIMENT_CAMPAIGN_CRITERIA_PER_CUSTOMER = 108 + WEBPAGE_CRITERIA_PER_CUSTOMER = 17 + BASE_WEBPAGE_CRITERIA_PER_CUSTOMER = 18 + EXPERIMENT_WEBPAGE_CRITERIA_PER_CUSTOMER = 19 + COMBINED_AUDIENCE_CRITERIA_PER_AD_GROUP = 20 + CUSTOMER_NEGATIVE_PLACEMENT_CRITERIA_PER_CUSTOMER = 21 + CUSTOMER_NEGATIVE_YOUTUBE_CHANNEL_CRITERIA_PER_CUSTOMER = 22 + CRITERIA_PER_AD_GROUP = 23 + LISTING_GROUPS_PER_AD_GROUP = 24 + EXPLICITLY_SHARED_BUDGETS_PER_CUSTOMER = 25 + IMPLICITLY_SHARED_BUDGETS_PER_CUSTOMER = 26 + COMBINED_AUDIENCE_CRITERIA_PER_CAMPAIGN = 27 + NEGATIVE_KEYWORDS_PER_CAMPAIGN = 28 + NEGATIVE_PLACEMENTS_PER_CAMPAIGN = 29 + GEO_TARGETS_PER_CAMPAIGN = 30 + NEGATIVE_IP_BLOCKS_PER_CAMPAIGN = 32 + PROXIMITIES_PER_CAMPAIGN = 33 + LISTING_SCOPES_PER_SHOPPING_CAMPAIGN = 34 + LISTING_SCOPES_PER_NON_SHOPPING_CAMPAIGN = 35 + NEGATIVE_KEYWORDS_PER_SHARED_SET = 36 + NEGATIVE_PLACEMENTS_PER_SHARED_SET = 37 + SHARED_SETS_PER_CUSTOMER_FOR_TYPE_DEFAULT = 40 + SHARED_SETS_PER_CUSTOMER_FOR_NEGATIVE_PLACEMENT_LIST_LOWER = 41 + HOTEL_ADVANCE_BOOKING_WINDOW_BID_MODIFIERS_PER_AD_GROUP = 44 + BIDDING_STRATEGIES_PER_CUSTOMER = 45 + BASIC_USER_LISTS_PER_CUSTOMER = 47 + LOGICAL_USER_LISTS_PER_CUSTOMER = 48 + RULE_BASED_USER_LISTS_PER_CUSTOMER = 153 + BASE_AD_GROUP_ADS_PER_CUSTOMER = 53 + EXPERIMENT_AD_GROUP_ADS_PER_CUSTOMER = 54 + AD_GROUP_ADS_PER_CAMPAIGN = 55 + TEXT_AND_OTHER_ADS_PER_AD_GROUP = 56 + IMAGE_ADS_PER_AD_GROUP = 57 + SHOPPING_SMART_ADS_PER_AD_GROUP = 58 + RESPONSIVE_SEARCH_ADS_PER_AD_GROUP = 59 + APP_ADS_PER_AD_GROUP = 60 + APP_ENGAGEMENT_ADS_PER_AD_GROUP = 61 + LOCAL_ADS_PER_AD_GROUP = 62 + VIDEO_ADS_PER_AD_GROUP = 63 + LEAD_FORM_CAMPAIGN_ASSETS_PER_CAMPAIGN = 143 + PROMOTION_CUSTOMER_ASSETS_PER_CUSTOMER = 79 + PROMOTION_CAMPAIGN_ASSETS_PER_CAMPAIGN = 80 + PROMOTION_AD_GROUP_ASSETS_PER_AD_GROUP = 81 + CALLOUT_CUSTOMER_ASSETS_PER_CUSTOMER = 134 + CALLOUT_CAMPAIGN_ASSETS_PER_CAMPAIGN = 135 + CALLOUT_AD_GROUP_ASSETS_PER_AD_GROUP = 136 + SITELINK_CUSTOMER_ASSETS_PER_CUSTOMER = 137 + SITELINK_CAMPAIGN_ASSETS_PER_CAMPAIGN = 138 + SITELINK_AD_GROUP_ASSETS_PER_AD_GROUP = 139 + STRUCTURED_SNIPPET_CUSTOMER_ASSETS_PER_CUSTOMER = 140 + STRUCTURED_SNIPPET_CAMPAIGN_ASSETS_PER_CAMPAIGN = 141 + STRUCTURED_SNIPPET_AD_GROUP_ASSETS_PER_AD_GROUP = 142 + MOBILE_APP_CUSTOMER_ASSETS_PER_CUSTOMER = 144 + MOBILE_APP_CAMPAIGN_ASSETS_PER_CAMPAIGN = 145 + MOBILE_APP_AD_GROUP_ASSETS_PER_AD_GROUP = 146 + HOTEL_CALLOUT_CUSTOMER_ASSETS_PER_CUSTOMER = 147 + HOTEL_CALLOUT_CAMPAIGN_ASSETS_PER_CAMPAIGN = 148 + HOTEL_CALLOUT_AD_GROUP_ASSETS_PER_AD_GROUP = 149 + CALL_CUSTOMER_ASSETS_PER_CUSTOMER = 150 + CALL_CAMPAIGN_ASSETS_PER_CAMPAIGN = 151 + CALL_AD_GROUP_ASSETS_PER_AD_GROUP = 152 + PRICE_CUSTOMER_ASSETS_PER_CUSTOMER = 154 + PRICE_CAMPAIGN_ASSETS_PER_CAMPAIGN = 155 + PRICE_AD_GROUP_ASSETS_PER_AD_GROUP = 156 + AD_IMAGE_CAMPAIGN_ASSETS_PER_CAMPAIGN = 175 + AD_IMAGE_AD_GROUP_ASSETS_PER_AD_GROUP = 176 + PAGE_FEED_ASSET_SETS_PER_CUSTOMER = 157 + DYNAMIC_EDUCATION_FEED_ASSET_SETS_PER_CUSTOMER = 158 + ASSETS_PER_PAGE_FEED_ASSET_SET = 159 + ASSETS_PER_DYNAMIC_EDUCATION_FEED_ASSET_SET = 160 + DYNAMIC_REAL_ESTATE_ASSET_SETS_PER_CUSTOMER = 161 + ASSETS_PER_DYNAMIC_REAL_ESTATE_ASSET_SET = 162 + DYNAMIC_CUSTOM_ASSET_SETS_PER_CUSTOMER = 163 + ASSETS_PER_DYNAMIC_CUSTOM_ASSET_SET = 164 + DYNAMIC_HOTELS_AND_RENTALS_ASSET_SETS_PER_CUSTOMER = 165 + ASSETS_PER_DYNAMIC_HOTELS_AND_RENTALS_ASSET_SET = 166 + DYNAMIC_LOCAL_ASSET_SETS_PER_CUSTOMER = 167 + ASSETS_PER_DYNAMIC_LOCAL_ASSET_SET = 168 + DYNAMIC_FLIGHTS_ASSET_SETS_PER_CUSTOMER = 169 + ASSETS_PER_DYNAMIC_FLIGHTS_ASSET_SET = 170 + DYNAMIC_TRAVEL_ASSET_SETS_PER_CUSTOMER = 171 + ASSETS_PER_DYNAMIC_TRAVEL_ASSET_SET = 172 + DYNAMIC_JOBS_ASSET_SETS_PER_CUSTOMER = 173 + ASSETS_PER_DYNAMIC_JOBS_ASSET_SET = 174 + BUSINESS_NAME_CAMPAIGN_ASSETS_PER_CAMPAIGN = 179 + BUSINESS_LOGO_CAMPAIGN_ASSETS_PER_CAMPAIGN = 180 + VERSIONS_PER_AD = 82 + USER_FEEDS_PER_CUSTOMER = 90 + SYSTEM_FEEDS_PER_CUSTOMER = 91 + FEED_ATTRIBUTES_PER_FEED = 92 + FEED_ITEMS_PER_CUSTOMER = 94 + CAMPAIGN_FEEDS_PER_CUSTOMER = 95 + BASE_CAMPAIGN_FEEDS_PER_CUSTOMER = 96 + EXPERIMENT_CAMPAIGN_FEEDS_PER_CUSTOMER = 109 + AD_GROUP_FEEDS_PER_CUSTOMER = 97 + BASE_AD_GROUP_FEEDS_PER_CUSTOMER = 98 + EXPERIMENT_AD_GROUP_FEEDS_PER_CUSTOMER = 110 + AD_GROUP_FEEDS_PER_CAMPAIGN = 99 + FEED_ITEM_SETS_PER_CUSTOMER = 100 + FEED_ITEMS_PER_FEED_ITEM_SET = 101 + CAMPAIGN_EXPERIMENTS_PER_CUSTOMER = 112 + EXPERIMENT_ARMS_PER_VIDEO_EXPERIMENT = 113 + OWNED_LABELS_PER_CUSTOMER = 115 + LABELS_PER_CAMPAIGN = 117 + LABELS_PER_AD_GROUP = 118 + LABELS_PER_AD_GROUP_AD = 119 + LABELS_PER_AD_GROUP_CRITERION = 120 + TARGET_CUSTOMERS_PER_LABEL = 121 + KEYWORD_PLANS_PER_USER_PER_CUSTOMER = 122 + KEYWORD_PLAN_AD_GROUP_KEYWORDS_PER_KEYWORD_PLAN = 123 + KEYWORD_PLAN_AD_GROUPS_PER_KEYWORD_PLAN = 124 + KEYWORD_PLAN_NEGATIVE_KEYWORDS_PER_KEYWORD_PLAN = 125 + KEYWORD_PLAN_CAMPAIGNS_PER_KEYWORD_PLAN = 126 + CONVERSION_ACTIONS_PER_CUSTOMER = 128 + BATCH_JOB_OPERATIONS_PER_JOB = 130 + BATCH_JOBS_PER_CUSTOMER = 131 + HOTEL_CHECK_IN_DATE_RANGE_BID_MODIFIERS_PER_AD_GROUP = 132 + SHARED_SETS_PER_ACCOUNT_FOR_ACCOUNT_LEVEL_NEGATIVE_KEYWORDS = 177 + ACCOUNT_LEVEL_NEGATIVE_KEYWORDS_PER_SHARED_SET = 178 + ENABLED_ASSET_PER_HOTEL_PROPERTY_ASSET_SET = 181 + ENABLED_HOTEL_PROPERTY_ASSET_LINKS_PER_ASSET_GROUP = 182 + BRANDS_PER_SHARED_SET = 183 + ENABLED_BRAND_LIST_CRITERIA_PER_CAMPAIGN = 184 + SHARED_SETS_PER_ACCOUNT_FOR_BRAND = 185 + LOOKALIKE_USER_LISTS_PER_CUSTOMER = 186 + LOGO_CAMPAIGN_ASSETS_PER_CAMPAIGN = 187 + BUSINESS_MESSAGE_ASSET_LINKS_PER_CUSTOMER = 188 + WHATSAPP_BUSINESS_MESSAGE_ASSET_LINKS_PER_CAMPAIGN = 189 + WHATSAPP_BUSINESS_MESSAGE_ASSET_LINKS_PER_AD_GROUP = 190 + BRAND_LIST_CRITERIA_PER_AD_GROUP = 193 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/response_content_type.py b/google/ads/googleads/v24/enums/types/response_content_type.py new file mode 100644 index 000000000..2bbeadd15 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/response_content_type.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ResponseContentTypeEnum", + }, +) + + +class ResponseContentTypeEnum(proto.Message): + r"""Container for possible response content types.""" + + class ResponseContentType(proto.Enum): + r"""Possible response content types. + + Values: + UNSPECIFIED (0): + Not specified. Will return the resource name + only in the response. + RESOURCE_NAME_ONLY (1): + The mutate response will be the resource + name. + MUTABLE_RESOURCE (2): + The mutate response will contain the resource + name and the resource with mutable fields if + possible. Otherwise, only the resource name will + be returned. + """ + + UNSPECIFIED = 0 + RESOURCE_NAME_ONLY = 1 + MUTABLE_RESOURCE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/search_engine_results_page_type.py b/google/ads/googleads/v24/enums/types/search_engine_results_page_type.py new file mode 100644 index 000000000..64e2080df --- /dev/null +++ b/google/ads/googleads/v24/enums/types/search_engine_results_page_type.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SearchEngineResultsPageTypeEnum", + }, +) + + +class SearchEngineResultsPageTypeEnum(proto.Message): + r"""The type of the search engine results page.""" + + class SearchEngineResultsPageType(proto.Enum): + r"""The type of the search engine results page. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ADS_ONLY (2): + Only ads were contained in the search engine + results page. + ORGANIC_ONLY (3): + Only organic results were contained in the + search engine results page. + ADS_AND_ORGANIC (4): + Both ads and organic results were contained + in the search engine results page. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ADS_ONLY = 2 + ORGANIC_ONLY = 3 + ADS_AND_ORGANIC = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/search_term_match_source.py b/google/ads/googleads/v24/enums/types/search_term_match_source.py new file mode 100644 index 000000000..d95adeada --- /dev/null +++ b/google/ads/googleads/v24/enums/types/search_term_match_source.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SearchTermMatchSourceEnum", + }, +) + + +class SearchTermMatchSourceEnum(proto.Message): + r"""Container for enum describing the source for search term + matches in the search term report. + + """ + + class SearchTermMatchSource(proto.Enum): + r"""The search term match sources. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ADVERTISER_PROVIDED_KEYWORD (2): + The match is from a user-provided keyword. + AI_MAX_KEYWORDLESS (3): + The match is from the keywordless expansion + portion of AI Max. + AI_MAX_BROAD_MATCH (4): + The match is from the broad match expansion + portion of AI Max. + DYNAMIC_SEARCH_ADS (5): + The match is from a Dynamic Search Ad. + PERFORMANCE_MAX (6): + The match is from the search term matching + functionality in PMax. + VERTICAL_ADS_DATA_FEED (7): + The match is from a vertical ads data feed + (e.g. Travel Ads entity targeting). + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ADVERTISER_PROVIDED_KEYWORD = 2 + AI_MAX_KEYWORDLESS = 3 + AI_MAX_BROAD_MATCH = 4 + DYNAMIC_SEARCH_ADS = 5 + PERFORMANCE_MAX = 6 + VERTICAL_ADS_DATA_FEED = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/search_term_match_type.py b/google/ads/googleads/v24/enums/types/search_term_match_type.py new file mode 100644 index 000000000..79a01904a --- /dev/null +++ b/google/ads/googleads/v24/enums/types/search_term_match_type.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SearchTermMatchTypeEnum", + }, +) + + +class SearchTermMatchTypeEnum(proto.Message): + r"""Container for enum describing match types for a keyword + triggering an ad. + + """ + + class SearchTermMatchType(proto.Enum): + r"""Possible match types for a keyword triggering an ad, + including variants. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BROAD (2): + Broad match. + EXACT (3): + Exact match. + PHRASE (4): + Phrase match. + NEAR_EXACT (5): + Exact match (close variant). + NEAR_PHRASE (6): + Phrase match (close variant). + AI_MAX (7): + Match type for AI Max Search. + PERFORMANCE_MAX (8): + Match type for Performance Max campaigns. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BROAD = 2 + EXACT = 3 + PHRASE = 4 + NEAR_EXACT = 5 + NEAR_PHRASE = 6 + AI_MAX = 7 + PERFORMANCE_MAX = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/search_term_targeting_status.py b/google/ads/googleads/v24/enums/types/search_term_targeting_status.py new file mode 100644 index 000000000..25fd0c481 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/search_term_targeting_status.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SearchTermTargetingStatusEnum", + }, +) + + +class SearchTermTargetingStatusEnum(proto.Message): + r"""Container for enum indicating whether a search term is one of + your targeted or excluded keywords. + + """ + + class SearchTermTargetingStatus(proto.Enum): + r"""Indicates whether the search term is one of your targeted or + excluded keywords. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ADDED (2): + Search term is added to targeted keywords. + EXCLUDED (3): + Search term matches a negative keyword. + ADDED_EXCLUDED (4): + Search term has been both added and excluded. + NONE (5): + Search term is neither targeted nor excluded. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ADDED = 2 + EXCLUDED = 3 + ADDED_EXCLUDED = 4 + NONE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/seasonality_event_scope.py b/google/ads/googleads/v24/enums/types/seasonality_event_scope.py new file mode 100644 index 000000000..a52626eae --- /dev/null +++ b/google/ads/googleads/v24/enums/types/seasonality_event_scope.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SeasonalityEventScopeEnum", + }, +) + + +class SeasonalityEventScopeEnum(proto.Message): + r"""Message describing seasonality event scopes. The two types of + seasonality events are BiddingSeasonalityAdjustments and + BiddingDataExclusions. + + """ + + class SeasonalityEventScope(proto.Enum): + r"""The possible scopes of a Seasonality Event. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + CUSTOMER (2): + The seasonality event is applied to all the + customer's traffic for supported advertising + channel types and device types. The CUSTOMER + scope cannot be used in mutates. + CAMPAIGN (4): + The seasonality event is applied to all + specified campaigns. + CHANNEL (5): + The seasonality event is applied to all + campaigns that belong to specified channel + types. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER = 2 + CAMPAIGN = 4 + CHANNEL = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/seasonality_event_status.py b/google/ads/googleads/v24/enums/types/seasonality_event_status.py new file mode 100644 index 000000000..3945d39a3 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/seasonality_event_status.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SeasonalityEventStatusEnum", + }, +) + + +class SeasonalityEventStatusEnum(proto.Message): + r"""Message describing seasonality event statuses. The two types + of seasonality events are BiddingSeasonalityAdjustments and + BiddingDataExclusions. + + """ + + class SeasonalityEventStatus(proto.Enum): + r"""The possible statuses of a Seasonality Event. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + ENABLED (2): + The seasonality event is enabled. + REMOVED (4): + The seasonality event is removed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/served_asset_field_type.py b/google/ads/googleads/v24/enums/types/served_asset_field_type.py new file mode 100644 index 000000000..ef84edeb7 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/served_asset_field_type.py @@ -0,0 +1,170 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ServedAssetFieldTypeEnum", + }, +) + + +class ServedAssetFieldTypeEnum(proto.Message): + r"""Container for enum describing possible asset field types.""" + + class ServedAssetFieldType(proto.Enum): + r"""The possible asset field types. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + HEADLINE_1 (2): + The asset is used in headline 1. + HEADLINE_2 (3): + The asset is used in headline 2. + HEADLINE_3 (4): + The asset is used in headline 3. + DESCRIPTION_1 (5): + The asset is used in description 1. + DESCRIPTION_2 (6): + The asset is used in description 2. + HEADLINE (7): + The asset was used in a headline. Use this only if there is + only one headline in the ad. Otherwise, use the HEADLINE_1, + HEADLINE_2 or HEADLINE_3 enums + HEADLINE_IN_PORTRAIT (8): + The asset was used as a headline in portrait + image. + LONG_HEADLINE (9): + The asset was used in a long headline (used + in MultiAssetResponsiveAd). + DESCRIPTION (10): + The asset was used in a description. Use this only if there + is only one description in the ad. Otherwise, use the + DESCRIPTION_1 or DESCRIPTION\_@ enums + DESCRIPTION_IN_PORTRAIT (11): + The asset was used as description in portrait + image. + BUSINESS_NAME_IN_PORTRAIT (12): + The asset was used as business name in + portrait image. + BUSINESS_NAME (13): + The asset was used as business name. + MARKETING_IMAGE (14): + The asset was used as a marketing image. + MARKETING_IMAGE_IN_PORTRAIT (15): + The asset was used as a marketing image in + portrait image. + SQUARE_MARKETING_IMAGE (16): + The asset was used as a square marketing + image. + PORTRAIT_MARKETING_IMAGE (17): + The asset was used as a portrait marketing + image. + LOGO (18): + The asset was used as a logo. + LANDSCAPE_LOGO (19): + The asset was used as a landscape logo. + CALL_TO_ACTION (20): + The asset was used as a call-to-action. + YOU_TUBE_VIDEO (21): + The asset was used as a YouTube video. + SITELINK (22): + This asset is used as a sitelink. + CALL (23): + This asset is used as a call. + MOBILE_APP (24): + This asset is used as a mobile app. + CALLOUT (25): + This asset is used as a callout. + STRUCTURED_SNIPPET (26): + This asset is used as a structured snippet. + PRICE (27): + This asset is used as a price. + PROMOTION (28): + This asset is used as a promotion. + AD_IMAGE (29): + This asset is used as an image. + LEAD_FORM (30): + The asset is used as a lead form. + BUSINESS_LOGO (31): + The asset is used as a business logo. + DESCRIPTION_PREFIX (32): + The asset is used as a description prefix. + HEADLINE_AS_SITELINK_POSITION_ONE (39): + A headline asset used as a sitelink in + position 1. + HEADLINE_AS_SITELINK_POSITION_TWO (40): + A headline asset used as a sitelink in + position 2. + DESCRIPTION_LINE_HEADLINE_AS_SITELINK_POSITION_ONE (41): + A description line asset used as a sitelink + in position 1. + DESCRIPTION_LINE_HEADLINE_AS_SITELINK_POSITION_TWO (42): + A description line asset used as a sitelink + in position 2. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + HEADLINE_1 = 2 + HEADLINE_2 = 3 + HEADLINE_3 = 4 + DESCRIPTION_1 = 5 + DESCRIPTION_2 = 6 + HEADLINE = 7 + HEADLINE_IN_PORTRAIT = 8 + LONG_HEADLINE = 9 + DESCRIPTION = 10 + DESCRIPTION_IN_PORTRAIT = 11 + BUSINESS_NAME_IN_PORTRAIT = 12 + BUSINESS_NAME = 13 + MARKETING_IMAGE = 14 + MARKETING_IMAGE_IN_PORTRAIT = 15 + SQUARE_MARKETING_IMAGE = 16 + PORTRAIT_MARKETING_IMAGE = 17 + LOGO = 18 + LANDSCAPE_LOGO = 19 + CALL_TO_ACTION = 20 + YOU_TUBE_VIDEO = 21 + SITELINK = 22 + CALL = 23 + MOBILE_APP = 24 + CALLOUT = 25 + STRUCTURED_SNIPPET = 26 + PRICE = 27 + PROMOTION = 28 + AD_IMAGE = 29 + LEAD_FORM = 30 + BUSINESS_LOGO = 31 + DESCRIPTION_PREFIX = 32 + HEADLINE_AS_SITELINK_POSITION_ONE = 39 + HEADLINE_AS_SITELINK_POSITION_TWO = 40 + DESCRIPTION_LINE_HEADLINE_AS_SITELINK_POSITION_ONE = 41 + DESCRIPTION_LINE_HEADLINE_AS_SITELINK_POSITION_TWO = 42 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/shared_set_status.py b/google/ads/googleads/v24/enums/types/shared_set_status.py new file mode 100644 index 000000000..4d378b987 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/shared_set_status.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SharedSetStatusEnum", + }, +) + + +class SharedSetStatusEnum(proto.Message): + r"""Container for enum describing types of shared set statuses.""" + + class SharedSetStatus(proto.Enum): + r"""Enum listing the possible shared set statuses. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + The shared set is enabled. + REMOVED (3): + The shared set is removed and can no longer + be used. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/shared_set_type.py b/google/ads/googleads/v24/enums/types/shared_set_type.py new file mode 100644 index 000000000..d8f76e4cc --- /dev/null +++ b/google/ads/googleads/v24/enums/types/shared_set_type.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SharedSetTypeEnum", + }, +) + + +class SharedSetTypeEnum(proto.Message): + r"""Container for enum describing types of shared sets.""" + + class SharedSetType(proto.Enum): + r"""Enum listing the possible shared set types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + NEGATIVE_KEYWORDS (2): + A set of keywords that can be excluded from + targeting. + NEGATIVE_PLACEMENTS (3): + A set of placements that can be excluded from + targeting. + ACCOUNT_LEVEL_NEGATIVE_KEYWORDS (4): + An account-level set of keywords that can be + excluded from targeting. + BRANDS (5): + A set of brands can be included or excluded + from targeting. + WEBPAGES (6): + A set of webpages that can be excluded from + targeting. This shared set type is not publicly + available. + VERTICAL_ADS_ITEM_GROUP_RULE_LIST (7): + A set of vertical ads item group rules that + can be included or excluded from targeting in + Vertical Ads (e.g., for hotel ads). + RETAIL_FILTER (32): + A set representing Retail Filter, which is + used for filtering offers served in a campaign. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NEGATIVE_KEYWORDS = 2 + NEGATIVE_PLACEMENTS = 3 + ACCOUNT_LEVEL_NEGATIVE_KEYWORDS = 4 + BRANDS = 5 + WEBPAGES = 6 + VERTICAL_ADS_ITEM_GROUP_RULE_LIST = 7 + RETAIL_FILTER = 32 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/shopping_add_products_to_campaign_recommendation_enum.py b/google/ads/googleads/v24/enums/types/shopping_add_products_to_campaign_recommendation_enum.py new file mode 100644 index 000000000..39c985a97 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/shopping_add_products_to_campaign_recommendation_enum.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ShoppingAddProductsToCampaignRecommendationEnum", + }, +) + + +class ShoppingAddProductsToCampaignRecommendationEnum(proto.Message): + r"""Indicates the key issue that results in a shopping campaign + targeting zero products. + + """ + + class Reason(proto.Enum): + r"""Issues that results in a shopping campaign targeting zero + products. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + MERCHANT_CENTER_ACCOUNT_HAS_NO_SUBMITTED_PRODUCTS (2): + The Merchant Center account does not have any + submitted products. + MERCHANT_CENTER_ACCOUNT_HAS_NO_SUBMITTED_PRODUCTS_IN_FEED (3): + The Merchant Center account does not have any + submitted products in the feed. + ADS_ACCOUNT_EXCLUDES_OFFERS_FROM_CAMPAIGN (4): + The Google Ads account has active campaign + filters that prevents inclusion of offers in the + campaign. + ALL_PRODUCTS_ARE_EXCLUDED_FROM_CAMPAIGN (5): + All products available have been explicitly + excluded from being targeted by the campaign. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MERCHANT_CENTER_ACCOUNT_HAS_NO_SUBMITTED_PRODUCTS = 2 + MERCHANT_CENTER_ACCOUNT_HAS_NO_SUBMITTED_PRODUCTS_IN_FEED = 3 + ADS_ACCOUNT_EXCLUDES_OFFERS_FROM_CAMPAIGN = 4 + ALL_PRODUCTS_ARE_EXCLUDED_FROM_CAMPAIGN = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/simulation_modification_method.py b/google/ads/googleads/v24/enums/types/simulation_modification_method.py new file mode 100644 index 000000000..35cd11bf3 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/simulation_modification_method.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SimulationModificationMethodEnum", + }, +) + + +class SimulationModificationMethodEnum(proto.Message): + r"""Container for enum describing the method by which a + simulation modifies a field. + + """ + + class SimulationModificationMethod(proto.Enum): + r"""Enum describing the method by which a simulation modifies a + field. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + UNIFORM (2): + The values in a simulation were applied to + all children of a given resource uniformly. + Overrides on child resources were not respected. + DEFAULT (3): + The values in a simulation were applied to + the given resource. Overrides on child resources + were respected, and traffic estimates do not + include these resources. + SCALING (4): + The values in a simulation were all scaled by + the same factor. For example, in a simulated + TargetCpa campaign, the campaign target and all + ad group targets were scaled by a factor of X. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UNIFORM = 2 + DEFAULT = 3 + SCALING = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/simulation_type.py b/google/ads/googleads/v24/enums/types/simulation_type.py new file mode 100644 index 000000000..5230856d0 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/simulation_type.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SimulationTypeEnum", + }, +) + + +class SimulationTypeEnum(proto.Message): + r"""Container for enum describing the field a simulation + modifies. + + """ + + class SimulationType(proto.Enum): + r"""Enum describing the field a simulation modifies. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CPC_BID (2): + The simulation is for a CPC bid. + CPV_BID (3): + The simulation is for a CPV bid. + TARGET_CPA (4): + The simulation is for a CPA target. + BID_MODIFIER (5): + The simulation is for a bid modifier. + TARGET_ROAS (6): + The simulation is for a ROAS target. + PERCENT_CPC_BID (7): + The simulation is for a percent CPC bid. + TARGET_IMPRESSION_SHARE (8): + The simulation is for an impression share + target. + BUDGET (9): + The simulation is for a budget. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CPC_BID = 2 + CPV_BID = 3 + TARGET_CPA = 4 + BID_MODIFIER = 5 + TARGET_ROAS = 6 + PERCENT_CPC_BID = 7 + TARGET_IMPRESSION_SHARE = 8 + BUDGET = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/sk_ad_network_ad_event_type.py b/google/ads/googleads/v24/enums/types/sk_ad_network_ad_event_type.py new file mode 100644 index 000000000..0c52f00f3 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/sk_ad_network_ad_event_type.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SkAdNetworkAdEventTypeEnum", + }, +) + + +class SkAdNetworkAdEventTypeEnum(proto.Message): + r"""Container for enumeration of SkAdNetwork ad event types.""" + + class SkAdNetworkAdEventType(proto.Enum): + r"""Enumerates SkAdNetwork ad event types + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + UNAVAILABLE (2): + The value was not present in the postback or + we do not have this data for other reasons. + INTERACTION (3): + The user interacted with the ad. + VIEW (4): + The user viewed the ad. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UNAVAILABLE = 2 + INTERACTION = 3 + VIEW = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/sk_ad_network_attribution_credit.py b/google/ads/googleads/v24/enums/types/sk_ad_network_attribution_credit.py new file mode 100644 index 000000000..4fe58f3e4 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/sk_ad_network_attribution_credit.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SkAdNetworkAttributionCreditEnum", + }, +) + + +class SkAdNetworkAttributionCreditEnum(proto.Message): + r"""Container for enumeration of SkAdNetwork attribution credits.""" + + class SkAdNetworkAttributionCredit(proto.Enum): + r"""Enumerates SkAdNetwork attribution credits. + + Values: + UNSPECIFIED (0): + Default value. This value is equivalent to + null. + UNKNOWN (1): + The value is unknown in this API version. The + true enum value cannot be returned in this API + version or is not supported yet. + UNAVAILABLE (2): + The value was not present in the postback or + we do not have this data for other reasons. + WON (3): + Google was the ad network that won ad + attribution. + CONTRIBUTED (4): + Google qualified for attribution, but didn't + win. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UNAVAILABLE = 2 + WON = 3 + CONTRIBUTED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/sk_ad_network_coarse_conversion_value.py b/google/ads/googleads/v24/enums/types/sk_ad_network_coarse_conversion_value.py new file mode 100644 index 000000000..35cf50eae --- /dev/null +++ b/google/ads/googleads/v24/enums/types/sk_ad_network_coarse_conversion_value.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SkAdNetworkCoarseConversionValueEnum", + }, +) + + +class SkAdNetworkCoarseConversionValueEnum(proto.Message): + r"""Container for enumeration of SkAdNetwork coarse conversion + values. + + """ + + class SkAdNetworkCoarseConversionValue(proto.Enum): + r"""Enumerates SkAdNetwork coarse conversion values + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + UNAVAILABLE (2): + The value was not present in the postback or + we do not have this data for other reasons. + LOW (3): + A low coarse conversion value. + MEDIUM (4): + A medium coarse conversion value. + HIGH (5): + A high coarse conversion value. + NONE (6): + A coarse conversion value was not configured. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UNAVAILABLE = 2 + LOW = 3 + MEDIUM = 4 + HIGH = 5 + NONE = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/sk_ad_network_source_type.py b/google/ads/googleads/v24/enums/types/sk_ad_network_source_type.py new file mode 100644 index 000000000..c22e79cd0 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/sk_ad_network_source_type.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SkAdNetworkSourceTypeEnum", + }, +) + + +class SkAdNetworkSourceTypeEnum(proto.Message): + r"""Container for enumeration of SkAdNetwork source types.""" + + class SkAdNetworkSourceType(proto.Enum): + r"""Enumerates SkAdNetwork source types + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + UNAVAILABLE (2): + The source app ID or source domain was not + present in the postback or we do not have this + data for other reasons. + WEBSITE (3): + The ad was shown on a webpage. + MOBILE_APPLICATION (4): + The ad was shown on an app. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UNAVAILABLE = 2 + WEBSITE = 3 + MOBILE_APPLICATION = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/sk_ad_network_user_type.py b/google/ads/googleads/v24/enums/types/sk_ad_network_user_type.py new file mode 100644 index 000000000..744d800be --- /dev/null +++ b/google/ads/googleads/v24/enums/types/sk_ad_network_user_type.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SkAdNetworkUserTypeEnum", + }, +) + + +class SkAdNetworkUserTypeEnum(proto.Message): + r"""Container for enumeration of SkAdNetwork user types.""" + + class SkAdNetworkUserType(proto.Enum): + r"""Enumerates SkAdNetwork user types + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + UNAVAILABLE (2): + The value was not present in the postback or + we do not have this data for other reasons. + NEW_INSTALLER (3): + The user installed the app for the first + time. + REINSTALLER (4): + The user has previously installed the app. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UNAVAILABLE = 2 + NEW_INSTALLER = 3 + REINSTALLER = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/slot.py b/google/ads/googleads/v24/enums/types/slot.py new file mode 100644 index 000000000..6992ce1b4 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/slot.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SlotEnum", + }, +) + + +class SlotEnum(proto.Message): + r"""Container for enumeration of possible positions of the Ad.""" + + class Slot(proto.Enum): + r"""Enumerates possible positions of the Ad. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + SEARCH_SIDE (2): + Google search: Side. + SEARCH_TOP (3): + Google search: Top. + SEARCH_OTHER (4): + Google search: Other. + CONTENT (5): + Google Display Network. + SEARCH_PARTNER_TOP (6): + Search partners: Top. + SEARCH_PARTNER_OTHER (7): + Search partners: Other. + MIXED (8): + Cross-network. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SEARCH_SIDE = 2 + SEARCH_TOP = 3 + SEARCH_OTHER = 4 + CONTENT = 5 + SEARCH_PARTNER_TOP = 6 + SEARCH_PARTNER_OTHER = 7 + MIXED = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/smart_campaign_not_eligible_reason.py b/google/ads/googleads/v24/enums/types/smart_campaign_not_eligible_reason.py new file mode 100644 index 000000000..2d6fc99ab --- /dev/null +++ b/google/ads/googleads/v24/enums/types/smart_campaign_not_eligible_reason.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SmartCampaignNotEligibleReasonEnum", + }, +) + + +class SmartCampaignNotEligibleReasonEnum(proto.Message): + r"""A container for an enum that describes reasons for why a + Smart campaign is not eligible to serve. + + """ + + class SmartCampaignNotEligibleReason(proto.Enum): + r"""Reasons for why a Smart campaign is not eligible to serve. + + Values: + UNSPECIFIED (0): + The status has not been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + ACCOUNT_ISSUE (2): + The campaign is not eligible to serve because + of an issue with the account. + BILLING_ISSUE (3): + The campaign is not eligible to serve because + of a payment issue. + BUSINESS_PROFILE_LOCATION_REMOVED (4): + The business profile location associated with + the campaign has been removed. + ALL_ADS_DISAPPROVED (5): + All system-generated ads have been disapproved. Consult the + policy_summary field in the AdGroupAd resource for more + details. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ACCOUNT_ISSUE = 2 + BILLING_ISSUE = 3 + BUSINESS_PROFILE_LOCATION_REMOVED = 4 + ALL_ADS_DISAPPROVED = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/smart_campaign_status.py b/google/ads/googleads/v24/enums/types/smart_campaign_status.py new file mode 100644 index 000000000..acfbe6a9f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/smart_campaign_status.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SmartCampaignStatusEnum", + }, +) + + +class SmartCampaignStatusEnum(proto.Message): + r"""A container for an enum that describes Smart campaign + statuses. + + """ + + class SmartCampaignStatus(proto.Enum): + r"""Smart campaign statuses. + + Values: + UNSPECIFIED (0): + The status has not been specified. + UNKNOWN (1): + The received value is not known in this + version. + This is a response-only value. + PAUSED (2): + The campaign was paused. + NOT_ELIGIBLE (3): + The campaign is not eligible to serve and has + issues that may require intervention. + PENDING (4): + The campaign is pending the approval of at + least one ad. + ELIGIBLE (5): + The campaign is eligible to serve. + REMOVED (6): + The campaign has been removed. + ENDED (7): + The campaign has ended. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PAUSED = 2 + NOT_ELIGIBLE = 3 + PENDING = 4 + ELIGIBLE = 5 + REMOVED = 6 + ENDED = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/spending_limit_type.py b/google/ads/googleads/v24/enums/types/spending_limit_type.py new file mode 100644 index 000000000..09f84563d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/spending_limit_type.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SpendingLimitTypeEnum", + }, +) + + +class SpendingLimitTypeEnum(proto.Message): + r"""Message describing spending limit types.""" + + class SpendingLimitType(proto.Enum): + r"""The possible spending limit types used by certain resources + as an alternative to absolute money values in micros. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + INFINITE (2): + Infinite, indicates unlimited spending power. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INFINITE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/summary_row_setting.py b/google/ads/googleads/v24/enums/types/summary_row_setting.py new file mode 100644 index 000000000..9d0b615e0 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/summary_row_setting.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SummaryRowSettingEnum", + }, +) + + +class SummaryRowSettingEnum(proto.Message): + r"""Indicates summary row setting in request parameter.""" + + class SummaryRowSetting(proto.Enum): + r"""Enum describing return summary row settings. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Represent unknown values of return summary + row. + NO_SUMMARY_ROW (2): + Do not return summary row. + SUMMARY_ROW_WITH_RESULTS (3): + Return summary row along with results. The + summary row will be returned in the last batch + alone (last batch will contain no results). + SUMMARY_ROW_ONLY (4): + Return summary row only and return no + results. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NO_SUMMARY_ROW = 2 + SUMMARY_ROW_WITH_RESULTS = 3 + SUMMARY_ROW_ONLY = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/system_managed_entity_source.py b/google/ads/googleads/v24/enums/types/system_managed_entity_source.py new file mode 100644 index 000000000..25c943cd7 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/system_managed_entity_source.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "SystemManagedResourceSourceEnum", + }, +) + + +class SystemManagedResourceSourceEnum(proto.Message): + r"""Container for enum describing possible system managed entity + sources. + + """ + + class SystemManagedResourceSource(proto.Enum): + r"""Enum listing the possible system managed entity sources. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + AD_VARIATIONS (2): + Generated ad variations experiment ad. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AD_VARIATIONS = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/target_cpa_opt_in_recommendation_goal.py b/google/ads/googleads/v24/enums/types/target_cpa_opt_in_recommendation_goal.py new file mode 100644 index 000000000..59fb2326b --- /dev/null +++ b/google/ads/googleads/v24/enums/types/target_cpa_opt_in_recommendation_goal.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "TargetCpaOptInRecommendationGoalEnum", + }, +) + + +class TargetCpaOptInRecommendationGoalEnum(proto.Message): + r"""Container for enum describing goals for TargetCpaOptIn + recommendation. + + """ + + class TargetCpaOptInRecommendationGoal(proto.Enum): + r"""Goal of TargetCpaOptIn recommendation. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + SAME_COST (2): + Recommendation to set Target CPA to maintain + the same cost. + SAME_CONVERSIONS (3): + Recommendation to set Target CPA to maintain + the same conversions. + SAME_CPA (4): + Recommendation to set Target CPA to maintain + the same CPA. + CLOSEST_CPA (5): + Recommendation to set Target CPA to a value + that is as close as possible to, yet lower than, + the actual CPA (computed for past 28 days). + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SAME_COST = 2 + SAME_CONVERSIONS = 3 + SAME_CPA = 4 + CLOSEST_CPA = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/target_frequency_time_unit.py b/google/ads/googleads/v24/enums/types/target_frequency_time_unit.py new file mode 100644 index 000000000..63e27760c --- /dev/null +++ b/google/ads/googleads/v24/enums/types/target_frequency_time_unit.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "TargetFrequencyTimeUnitEnum", + }, +) + + +class TargetFrequencyTimeUnitEnum(proto.Message): + r"""Container for enum describing bidding goal Target Frequency + time units. + + """ + + class TargetFrequencyTimeUnit(proto.Enum): + r"""Enum describing time window over which we want to reach + Target Frequency. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + WEEKLY (2): + Optimize bidding to reach Target Frequency in + a week. + MONTHLY (3): + Optimize bidding to reach Target Frequency in + a month. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + WEEKLY = 2 + MONTHLY = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/target_impression_share_location.py b/google/ads/googleads/v24/enums/types/target_impression_share_location.py new file mode 100644 index 000000000..4cb99c0e1 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/target_impression_share_location.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "TargetImpressionShareLocationEnum", + }, +) + + +class TargetImpressionShareLocationEnum(proto.Message): + r"""Container for enum describing where on the first search + results page the automated bidding system should target + impressions for the TargetImpressionShare bidding strategy. + + """ + + class TargetImpressionShareLocation(proto.Enum): + r"""Enum describing possible goals. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ANYWHERE_ON_PAGE (2): + Any location on the web page. + TOP_OF_PAGE (3): + Top box of ads. + ABSOLUTE_TOP_OF_PAGE (4): + Top slot in the top box of ads. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ANYWHERE_ON_PAGE = 2 + TOP_OF_PAGE = 3 + ABSOLUTE_TOP_OF_PAGE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/targeting_dimension.py b/google/ads/googleads/v24/enums/types/targeting_dimension.py new file mode 100644 index 000000000..baef22bf6 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/targeting_dimension.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "TargetingDimensionEnum", + }, +) + + +class TargetingDimensionEnum(proto.Message): + r"""The dimensions that can be targeted.""" + + class TargetingDimension(proto.Enum): + r"""Enum describing possible targeting dimensions. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + KEYWORD (2): + Keyword criteria, for example, 'mars cruise'. + KEYWORD may be used as a custom bid dimension. + Keywords are always a targeting dimension, so + may not be set as a target "ALL" dimension with + TargetRestriction. + AUDIENCE (3): + Audience criteria, which include user list, + user interest, custom affinity, and custom in + market. + TOPIC (4): + Topic criteria for targeting categories of + content, for example, 'category::Animals>Pets' + Used for Display and Video targeting. + GENDER (5): + Criteria for targeting gender. + AGE_RANGE (6): + Criteria for targeting age ranges. + PLACEMENT (7): + Placement criteria, which include websites + like 'www.flowers4sale.com', as well as mobile + applications, mobile app categories, YouTube + videos, and YouTube channels. + PARENTAL_STATUS (8): + Criteria for parental status targeting. + INCOME_RANGE (9): + Criteria for income range targeting. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + KEYWORD = 2 + AUDIENCE = 3 + TOPIC = 4 + GENDER = 5 + AGE_RANGE = 6 + PLACEMENT = 7 + PARENTAL_STATUS = 8 + INCOME_RANGE = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/third_party_brand_lift_integration_partner.py b/google/ads/googleads/v24/enums/types/third_party_brand_lift_integration_partner.py new file mode 100644 index 000000000..2bdf7aeae --- /dev/null +++ b/google/ads/googleads/v24/enums/types/third_party_brand_lift_integration_partner.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ThirdPartyBrandLiftIntegrationPartnerEnum", + }, +) + + +class ThirdPartyBrandLiftIntegrationPartnerEnum(proto.Message): + r"""Container for enum describing available third party + integration partners for Brand Lift verification. + + """ + + class ThirdPartyBrandLiftIntegrationPartner(proto.Enum): + r"""Enum describing available third party integration partners + for Brand Lift verification. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + KANTAR_MILLWARD_BROWN (2): + Kantar + DYNATA (3): + Dynata + INTAGE (4): + Intage + MACROMILL (5): + Macromill + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + KANTAR_MILLWARD_BROWN = 2 + DYNATA = 3 + INTAGE = 4 + MACROMILL = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/third_party_brand_safety_integration_partner.py b/google/ads/googleads/v24/enums/types/third_party_brand_safety_integration_partner.py new file mode 100644 index 000000000..c91f56bf1 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/third_party_brand_safety_integration_partner.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ThirdPartyBrandSafetyIntegrationPartnerEnum", + }, +) + + +class ThirdPartyBrandSafetyIntegrationPartnerEnum(proto.Message): + r"""Container for enum describing available third party + integration partners for brand safety verification. + + """ + + class ThirdPartyBrandSafetyIntegrationPartner(proto.Enum): + r"""Enum describing available third party integration partners + for brand safety verification. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + DOUBLE_VERIFY (2): + DoubleVerify. + INTEGRAL_AD_SCIENCE (3): + Integral Ad Science. + ZEFR (4): + Zefr. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DOUBLE_VERIFY = 2 + INTEGRAL_AD_SCIENCE = 3 + ZEFR = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/third_party_reach_integration_partner.py b/google/ads/googleads/v24/enums/types/third_party_reach_integration_partner.py new file mode 100644 index 000000000..019558849 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/third_party_reach_integration_partner.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ThirdPartyReachIntegrationPartnerEnum", + }, +) + + +class ThirdPartyReachIntegrationPartnerEnum(proto.Message): + r"""Container for enum describing available third party + integration partners for reach verification. + + """ + + class ThirdPartyReachIntegrationPartner(proto.Enum): + r"""Enum describing available third party integration partners + for reach verification. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + NIELSEN (2): + Nielsen. + COMSCORE (3): + Comscore. + KANTAR_MILLWARD_BROWN (4): + Kantar. + VIDEO_RESEARCH (5): + Video Research. + GEMIUS (6): + Gemius. + MEDIA_SCOPE (7): + MediaScope. + AUDIENCE_PROJECT (8): + AudienceProject + VIDEO_AMP (9): + VideoAmp + ISPOT_TV (10): + iSpot.tv + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NIELSEN = 2 + COMSCORE = 3 + KANTAR_MILLWARD_BROWN = 4 + VIDEO_RESEARCH = 5 + GEMIUS = 6 + MEDIA_SCOPE = 7 + AUDIENCE_PROJECT = 8 + VIDEO_AMP = 9 + ISPOT_TV = 10 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/third_party_viewability_integration_partner.py b/google/ads/googleads/v24/enums/types/third_party_viewability_integration_partner.py new file mode 100644 index 000000000..ddb6025c8 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/third_party_viewability_integration_partner.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ThirdPartyViewabilityIntegrationPartnerEnum", + }, +) + + +class ThirdPartyViewabilityIntegrationPartnerEnum(proto.Message): + r"""Container for enum describing available third party + integration partners for YouTube viewability verification. + + """ + + class ThirdPartyViewabilityIntegrationPartner(proto.Enum): + r"""Enum describing available third party integration partners + for YouTube viewability verification. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + DOUBLE_VERIFY (2): + DoubleVerify. + INTEGRAL_AD_SCIENCE (3): + Integral Ad Science. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DOUBLE_VERIFY = 2 + INTEGRAL_AD_SCIENCE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/time_type.py b/google/ads/googleads/v24/enums/types/time_type.py new file mode 100644 index 000000000..3ae95d920 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/time_type.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "TimeTypeEnum", + }, +) + + +class TimeTypeEnum(proto.Message): + r"""Message describing time types.""" + + class TimeType(proto.Enum): + r"""The possible time types used by certain resources as an + alternative to absolute timestamps. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + NOW (2): + As soon as possible. + FOREVER (3): + An infinite point in the future. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NOW = 2 + FOREVER = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/tracking_code_page_format.py b/google/ads/googleads/v24/enums/types/tracking_code_page_format.py new file mode 100644 index 000000000..2c154437e --- /dev/null +++ b/google/ads/googleads/v24/enums/types/tracking_code_page_format.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "TrackingCodePageFormatEnum", + }, +) + + +class TrackingCodePageFormatEnum(proto.Message): + r"""Container for enum describing the format of the web page + where the tracking tag and snippet will be installed. + + """ + + class TrackingCodePageFormat(proto.Enum): + r"""The format of the web page where the tracking tag and snippet + will be installed. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + HTML (2): + Standard HTML page format. + AMP (3): + Google AMP page format. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + HTML = 2 + AMP = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/tracking_code_type.py b/google/ads/googleads/v24/enums/types/tracking_code_type.py new file mode 100644 index 000000000..627dec412 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/tracking_code_type.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "TrackingCodeTypeEnum", + }, +) + + +class TrackingCodeTypeEnum(proto.Message): + r"""Container for enum describing the type of the generated tag + snippets for tracking conversions. + + """ + + class TrackingCodeType(proto.Enum): + r"""The type of the generated tag snippets for tracking + conversions. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + WEBPAGE (2): + The snippet that is fired as a result of a + website page loading. + WEBPAGE_ONCLICK (3): + The snippet contains a JavaScript function + which fires the tag. This function is typically + called from an onClick handler added to a link + or button element on the page. + CLICK_TO_CALL (4): + For embedding on a mobile webpage. The + snippet contains a JavaScript function which + fires the tag. + WEBSITE_CALL (5): + The snippet that is used to replace the phone + number on your website with a Google forwarding + number for call tracking purposes. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + WEBPAGE = 2 + WEBPAGE_ONCLICK = 3 + CLICK_TO_CALL = 4 + WEBSITE_CALL = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/unit_of_measure.py b/google/ads/googleads/v24/enums/types/unit_of_measure.py new file mode 100644 index 000000000..f577b9086 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/unit_of_measure.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UnitOfMeasureEnum", + }, +) + + +class UnitOfMeasureEnum(proto.Message): + r"""Container for enum describing the type of unit of measure.""" + + class UnitOfMeasure(proto.Enum): + r"""The possible type of unit of measure. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CLICKS (2): + Clicks as unit of measure. + IMPRESSIONS (3): + Impressions as unit of measure. + ACQUISITIONS (4): + Acquisitions as unit of measure. + PHONE_CALLS (5): + Phone calls as unit of measure. + VIDEO_PLAYS (6): + Video plays as unit of measure. + DAYS (7): + Days as unit of measure. + AUDIO_PLAYS (8): + Audio plays as unit of measure. + ENGAGEMENTS (9): + Engagements as unit of measure. + SECONDS (10): + Seconds as unit of measure. + LEADS (11): + Leads as unit of measure. + GUEST_STAYS (12): + Guest stays as unit of measure. + HOURS (13): + Hours as unit of measure. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CLICKS = 2 + IMPRESSIONS = 3 + ACQUISITIONS = 4 + PHONE_CALLS = 5 + VIDEO_PLAYS = 6 + DAYS = 7 + AUDIO_PLAYS = 8 + ENGAGEMENTS = 9 + SECONDS = 10 + LEADS = 11 + GUEST_STAYS = 12 + HOURS = 13 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_identifier_source.py b/google/ads/googleads/v24/enums/types/user_identifier_source.py new file mode 100644 index 000000000..fe754bdf8 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_identifier_source.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserIdentifierSourceEnum", + }, +) + + +class UserIdentifierSourceEnum(proto.Message): + r"""Container for enum describing the source of the user + identifier for offline Store Sales, click conversion, and + conversion adjustment uploads. + + """ + + class UserIdentifierSource(proto.Enum): + r"""The type of user identifier source for offline Store Sales, + click conversion, and conversion adjustment uploads. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version + FIRST_PARTY (2): + Indicates that the user identifier was + provided by the first party (advertiser). + THIRD_PARTY (3): + Indicates that the user identifier was + provided by the third party (partner). + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + FIRST_PARTY = 2 + THIRD_PARTY = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_interest_taxonomy_type.py b/google/ads/googleads/v24/enums/types/user_interest_taxonomy_type.py new file mode 100644 index 000000000..e840b9ede --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_interest_taxonomy_type.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserInterestTaxonomyTypeEnum", + }, +) + + +class UserInterestTaxonomyTypeEnum(proto.Message): + r"""Message describing a UserInterestTaxonomyType.""" + + class UserInterestTaxonomyType(proto.Enum): + r"""Enum containing the possible UserInterestTaxonomyTypes. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + AFFINITY (2): + The affinity for this user interest. + IN_MARKET (3): + The market for this user interest. + MOBILE_APP_INSTALL_USER (4): + Users known to have installed applications in + the specified categories. + VERTICAL_GEO (5): + The geographical location of the + interest-based vertical. + NEW_SMART_PHONE_USER (6): + User interest criteria for new smart phone + users. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AFFINITY = 2 + IN_MARKET = 3 + MOBILE_APP_INSTALL_USER = 4 + VERTICAL_GEO = 5 + NEW_SMART_PHONE_USER = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_list_access_status.py b/google/ads/googleads/v24/enums/types/user_list_access_status.py new file mode 100644 index 000000000..8d9c29b81 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_list_access_status.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserListAccessStatusEnum", + }, +) + + +class UserListAccessStatusEnum(proto.Message): + r"""Indicates if this client still has access to the list.""" + + class UserListAccessStatus(proto.Enum): + r"""Enum containing possible user list access statuses. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ENABLED (2): + The access is enabled. + DISABLED (3): + The access is disabled. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + DISABLED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_list_closing_reason.py b/google/ads/googleads/v24/enums/types/user_list_closing_reason.py new file mode 100644 index 000000000..195de4273 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_list_closing_reason.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserListClosingReasonEnum", + }, +) + + +class UserListClosingReasonEnum(proto.Message): + r"""Indicates the reason why the userlist was closed. + This enum is only used when a list is auto-closed by the system. + + """ + + class UserListClosingReason(proto.Enum): + r"""Enum describing possible user list closing reasons. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + UNUSED (2): + The userlist was closed because of not being + used for over one year. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UNUSED = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_list_crm_data_source_type.py b/google/ads/googleads/v24/enums/types/user_list_crm_data_source_type.py new file mode 100644 index 000000000..0889fb928 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_list_crm_data_source_type.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserListCrmDataSourceTypeEnum", + }, +) + + +class UserListCrmDataSourceTypeEnum(proto.Message): + r"""Indicates source of Crm upload data.""" + + class UserListCrmDataSourceType(proto.Enum): + r"""Enum describing possible user list crm data source type. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + FIRST_PARTY (2): + The uploaded data is first-party data. + THIRD_PARTY_CREDIT_BUREAU (3): + The uploaded data is from a third-party + credit bureau. + THIRD_PARTY_VOTER_FILE (4): + The uploaded data is from a third-party voter + file. + THIRD_PARTY_PARTNER_DATA (5): + The uploaded data is third party partner + data. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + FIRST_PARTY = 2 + THIRD_PARTY_CREDIT_BUREAU = 3 + THIRD_PARTY_VOTER_FILE = 4 + THIRD_PARTY_PARTNER_DATA = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_list_customer_type_category.py b/google/ads/googleads/v24/enums/types/user_list_customer_type_category.py new file mode 100644 index 000000000..d033d4709 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_list_customer_type_category.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserListCustomerTypeCategoryEnum", + }, +) + + +class UserListCustomerTypeCategoryEnum(proto.Message): + r"""The user list customer type categories.""" + + class UserListCustomerTypeCategory(proto.Enum): + r"""Enum containing possible user list customer type categories. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Unknown type. + ALL_CUSTOMERS (2): + Customer type category for all customers. + PURCHASERS (3): + Customer type category for all purchasers. + HIGH_VALUE_CUSTOMERS (4): + Customer type category for high value + purchasers. + DISENGAGED_CUSTOMERS (5): + Customer type category for disengaged + purchasers. + QUALIFIED_LEADS (6): + Customer type category for qualified leads. + CONVERTED_LEADS (7): + Customer type category for converted leads. + PAID_SUBSCRIBERS (8): + Customer type category for paid subscribers. + CART_ABANDONERS (10): + Customer type category for cart abandoners. + LOYALTY_TIER_1_MEMBERS (11): + Customer type category for loyalty tier 1 + members. + LOYALTY_TIER_2_MEMBERS (12): + Customer type category for loyalty tier 2 + members. + LOYALTY_TIER_3_MEMBERS (13): + Customer type category for loyalty tier 3 + members. + LOYALTY_TIER_4_MEMBERS (14): + Customer type category for loyalty tier 4 + members. + LOYALTY_TIER_5_MEMBERS (15): + Customer type category for loyalty tier 5 + members. + LOYALTY_TIER_6_MEMBERS (16): + Customer type category for loyalty tier 6 + members. + LOYALTY_TIER_7_MEMBERS (17): + Customer type category for loyalty tier 7 + members. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ALL_CUSTOMERS = 2 + PURCHASERS = 3 + HIGH_VALUE_CUSTOMERS = 4 + DISENGAGED_CUSTOMERS = 5 + QUALIFIED_LEADS = 6 + CONVERTED_LEADS = 7 + PAID_SUBSCRIBERS = 8 + CART_ABANDONERS = 10 + LOYALTY_TIER_1_MEMBERS = 11 + LOYALTY_TIER_2_MEMBERS = 12 + LOYALTY_TIER_3_MEMBERS = 13 + LOYALTY_TIER_4_MEMBERS = 14 + LOYALTY_TIER_5_MEMBERS = 15 + LOYALTY_TIER_6_MEMBERS = 16 + LOYALTY_TIER_7_MEMBERS = 17 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_list_date_rule_item_operator.py b/google/ads/googleads/v24/enums/types/user_list_date_rule_item_operator.py new file mode 100644 index 000000000..6a9912efc --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_list_date_rule_item_operator.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserListDateRuleItemOperatorEnum", + }, +) + + +class UserListDateRuleItemOperatorEnum(proto.Message): + r"""Supported rule operator for date type.""" + + class UserListDateRuleItemOperator(proto.Enum): + r"""Enum describing possible user list date rule item operators. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + EQUALS (2): + Equals. + NOT_EQUALS (3): + Not Equals. + BEFORE (4): + Before. + AFTER (5): + After. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EQUALS = 2 + NOT_EQUALS = 3 + BEFORE = 4 + AFTER = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_list_flexible_rule_operator.py b/google/ads/googleads/v24/enums/types/user_list_flexible_rule_operator.py new file mode 100644 index 000000000..feab91009 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_list_flexible_rule_operator.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserListFlexibleRuleOperatorEnum", + }, +) + + +class UserListFlexibleRuleOperatorEnum(proto.Message): + r"""Logical operator connecting two rules.""" + + class UserListFlexibleRuleOperator(proto.Enum): + r"""Enum describing possible user list combined rule operators. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + AND (2): + A AND B. + OR (3): + A OR B. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AND = 2 + OR = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_list_logical_rule_operator.py b/google/ads/googleads/v24/enums/types/user_list_logical_rule_operator.py new file mode 100644 index 000000000..452105928 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_list_logical_rule_operator.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserListLogicalRuleOperatorEnum", + }, +) + + +class UserListLogicalRuleOperatorEnum(proto.Message): + r"""The logical operator of the rule.""" + + class UserListLogicalRuleOperator(proto.Enum): + r"""Enum describing possible user list logical rule operators. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ALL (2): + And - all of the operands. + ANY (3): + Or - at least one of the operands. + NONE (4): + Not - none of the operands. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ALL = 2 + ANY = 3 + NONE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_list_membership_status.py b/google/ads/googleads/v24/enums/types/user_list_membership_status.py new file mode 100644 index 000000000..f5ca1392d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_list_membership_status.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserListMembershipStatusEnum", + }, +) + + +class UserListMembershipStatusEnum(proto.Message): + r"""Membership status of this user list. Indicates whether a user + list is open or active. Only open user lists can accumulate more + users and can be used for targeting. + + """ + + class UserListMembershipStatus(proto.Enum): + r"""Enum containing possible user list membership statuses. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + OPEN (2): + Open status - List is accruing members and + can be targeted to. + CLOSED (3): + Closed status - No new members being added. + Cannot be used for targeting. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + OPEN = 2 + CLOSED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_list_number_rule_item_operator.py b/google/ads/googleads/v24/enums/types/user_list_number_rule_item_operator.py new file mode 100644 index 000000000..65b09f04b --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_list_number_rule_item_operator.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserListNumberRuleItemOperatorEnum", + }, +) + + +class UserListNumberRuleItemOperatorEnum(proto.Message): + r"""Supported rule operator for number type.""" + + class UserListNumberRuleItemOperator(proto.Enum): + r"""Enum describing possible user list number rule item + operators. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + GREATER_THAN (2): + Greater than. + GREATER_THAN_OR_EQUAL (3): + Greater than or equal. + EQUALS (4): + Equals. + NOT_EQUALS (5): + Not equals. + LESS_THAN (6): + Less than. + LESS_THAN_OR_EQUAL (7): + Less than or equal. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + GREATER_THAN = 2 + GREATER_THAN_OR_EQUAL = 3 + EQUALS = 4 + NOT_EQUALS = 5 + LESS_THAN = 6 + LESS_THAN_OR_EQUAL = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_list_prepopulation_status.py b/google/ads/googleads/v24/enums/types/user_list_prepopulation_status.py new file mode 100644 index 000000000..d3218cb8a --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_list_prepopulation_status.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserListPrepopulationStatusEnum", + }, +) + + +class UserListPrepopulationStatusEnum(proto.Message): + r"""Indicates status of prepopulation based on the rule.""" + + class UserListPrepopulationStatus(proto.Enum): + r"""Enum describing possible user list prepopulation status. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + REQUESTED (2): + Prepopoulation is being requested. + FINISHED (3): + Prepopulation is finished. + FAILED (4): + Prepopulation failed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + REQUESTED = 2 + FINISHED = 3 + FAILED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_list_rule_type.py b/google/ads/googleads/v24/enums/types/user_list_rule_type.py new file mode 100644 index 000000000..ce121ca4f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_list_rule_type.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserListRuleTypeEnum", + }, +) + + +class UserListRuleTypeEnum(proto.Message): + r"""Rule based user list rule type.""" + + class UserListRuleType(proto.Enum): + r"""Enum describing possible user list rule types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + AND_OF_ORS (2): + Conjunctive normal form. + OR_OF_ANDS (3): + Disjunctive normal form. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AND_OF_ORS = 2 + OR_OF_ANDS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_list_size_range.py b/google/ads/googleads/v24/enums/types/user_list_size_range.py new file mode 100644 index 000000000..435c13fa1 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_list_size_range.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserListSizeRangeEnum", + }, +) + + +class UserListSizeRangeEnum(proto.Message): + r"""Size range in terms of number of users of a UserList.""" + + class UserListSizeRange(proto.Enum): + r"""Enum containing possible user list size ranges. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + LESS_THAN_FIVE_HUNDRED (2): + User list has less than 500 users. + LESS_THAN_ONE_THOUSAND (3): + User list has number of users in range of 500 + to 1000. + ONE_THOUSAND_TO_TEN_THOUSAND (4): + User list has number of users in range of + 1000 to 10000. + TEN_THOUSAND_TO_FIFTY_THOUSAND (5): + User list has number of users in range of + 10000 to 50000. + FIFTY_THOUSAND_TO_ONE_HUNDRED_THOUSAND (6): + User list has number of users in range of + 50000 to 100000. + ONE_HUNDRED_THOUSAND_TO_THREE_HUNDRED_THOUSAND (7): + User list has number of users in range of + 100000 to 300000. + THREE_HUNDRED_THOUSAND_TO_FIVE_HUNDRED_THOUSAND (8): + User list has number of users in range of + 300000 to 500000. + FIVE_HUNDRED_THOUSAND_TO_ONE_MILLION (9): + User list has number of users in range of + 500000 to 1 million. + ONE_MILLION_TO_TWO_MILLION (10): + User list has number of users in range of 1 + to 2 millions. + TWO_MILLION_TO_THREE_MILLION (11): + User list has number of users in range of 2 + to 3 millions. + THREE_MILLION_TO_FIVE_MILLION (12): + User list has number of users in range of 3 + to 5 millions. + FIVE_MILLION_TO_TEN_MILLION (13): + User list has number of users in range of 5 + to 10 millions. + TEN_MILLION_TO_TWENTY_MILLION (14): + User list has number of users in range of 10 + to 20 millions. + TWENTY_MILLION_TO_THIRTY_MILLION (15): + User list has number of users in range of 20 + to 30 millions. + THIRTY_MILLION_TO_FIFTY_MILLION (16): + User list has number of users in range of 30 + to 50 millions. + OVER_FIFTY_MILLION (17): + User list has over 50 million users. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LESS_THAN_FIVE_HUNDRED = 2 + LESS_THAN_ONE_THOUSAND = 3 + ONE_THOUSAND_TO_TEN_THOUSAND = 4 + TEN_THOUSAND_TO_FIFTY_THOUSAND = 5 + FIFTY_THOUSAND_TO_ONE_HUNDRED_THOUSAND = 6 + ONE_HUNDRED_THOUSAND_TO_THREE_HUNDRED_THOUSAND = 7 + THREE_HUNDRED_THOUSAND_TO_FIVE_HUNDRED_THOUSAND = 8 + FIVE_HUNDRED_THOUSAND_TO_ONE_MILLION = 9 + ONE_MILLION_TO_TWO_MILLION = 10 + TWO_MILLION_TO_THREE_MILLION = 11 + THREE_MILLION_TO_FIVE_MILLION = 12 + FIVE_MILLION_TO_TEN_MILLION = 13 + TEN_MILLION_TO_TWENTY_MILLION = 14 + TWENTY_MILLION_TO_THIRTY_MILLION = 15 + THIRTY_MILLION_TO_FIFTY_MILLION = 16 + OVER_FIFTY_MILLION = 17 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_list_string_rule_item_operator.py b/google/ads/googleads/v24/enums/types/user_list_string_rule_item_operator.py new file mode 100644 index 000000000..d5ed35139 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_list_string_rule_item_operator.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserListStringRuleItemOperatorEnum", + }, +) + + +class UserListStringRuleItemOperatorEnum(proto.Message): + r"""Supported rule operator for string type.""" + + class UserListStringRuleItemOperator(proto.Enum): + r"""Enum describing possible user list string rule item + operators. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CONTAINS (2): + Contains. + EQUALS (3): + Equals. + STARTS_WITH (4): + Starts with. + ENDS_WITH (5): + Ends with. + NOT_EQUALS (6): + Not equals. + NOT_CONTAINS (7): + Not contains. + NOT_STARTS_WITH (8): + Not starts with. + NOT_ENDS_WITH (9): + Not ends with. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CONTAINS = 2 + EQUALS = 3 + STARTS_WITH = 4 + ENDS_WITH = 5 + NOT_EQUALS = 6 + NOT_CONTAINS = 7 + NOT_STARTS_WITH = 8 + NOT_ENDS_WITH = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/user_list_type.py b/google/ads/googleads/v24/enums/types/user_list_type.py new file mode 100644 index 000000000..32ae3365f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/user_list_type.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "UserListTypeEnum", + }, +) + + +class UserListTypeEnum(proto.Message): + r"""The user list types.""" + + class UserListType(proto.Enum): + r"""Enum containing possible user list types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + REMARKETING (2): + UserList represented as a collection of + conversion types. + LOGICAL (3): + UserList represented as a combination of + other user lists/interests. + EXTERNAL_REMARKETING (4): + UserList created in the Google Ad Manager + platform. + RULE_BASED (5): + UserList associated with a rule. + SIMILAR (6): + UserList with users similar to users of + another UserList. + CRM_BASED (7): + UserList of first-party CRM data provided by + advertiser in the form of emails or other + formats. + LOOKALIKE (9): + LookalikeUserlist, composed of users similar + to those of a configurable seed (set of + UserLists) + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + REMARKETING = 2 + LOGICAL = 3 + EXTERNAL_REMARKETING = 4 + RULE_BASED = 5 + SIMILAR = 6 + CRM_BASED = 7 + LOOKALIKE = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/value_rule_device_type.py b/google/ads/googleads/v24/enums/types/value_rule_device_type.py new file mode 100644 index 000000000..6869f6af6 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/value_rule_device_type.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ValueRuleDeviceTypeEnum", + }, +) + + +class ValueRuleDeviceTypeEnum(proto.Message): + r"""Container for enum describing possible device types used in a + conversion value rule. + + """ + + class ValueRuleDeviceType(proto.Enum): + r"""Possible device types used in conversion value rule. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + MOBILE (2): + Mobile device. + DESKTOP (3): + Desktop device. + TABLET (4): + Tablet device. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MOBILE = 2 + DESKTOP = 3 + TABLET = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/value_rule_geo_location_match_type.py b/google/ads/googleads/v24/enums/types/value_rule_geo_location_match_type.py new file mode 100644 index 000000000..9413cf8b0 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/value_rule_geo_location_match_type.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ValueRuleGeoLocationMatchTypeEnum", + }, +) + + +class ValueRuleGeoLocationMatchTypeEnum(proto.Message): + r"""Container for enum describing possible geographic location + matching types used in a conversion value rule. + + """ + + class ValueRuleGeoLocationMatchType(proto.Enum): + r"""Possible geographic location matching types. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ANY (2): + Either Area of Interest or Location of + Presence can be used to match. + LOCATION_OF_PRESENCE (3): + Only Location of Presence can be used to + match. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ANY = 2 + LOCATION_OF_PRESENCE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/value_rule_operation.py b/google/ads/googleads/v24/enums/types/value_rule_operation.py new file mode 100644 index 000000000..d8f6dd06f --- /dev/null +++ b/google/ads/googleads/v24/enums/types/value_rule_operation.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ValueRuleOperationEnum", + }, +) + + +class ValueRuleOperationEnum(proto.Message): + r"""Container for enum describing possible operations for value + rules which are executed when rules are triggered. + + """ + + class ValueRuleOperation(proto.Enum): + r"""Possible operations of the action of a conversion value rule. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ADD (2): + Add provided value to conversion value. + MULTIPLY (3): + Multiply conversion value by provided value. + SET (4): + Set conversion value to provided value. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ADD = 2 + MULTIPLY = 3 + SET = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/value_rule_set_attachment_type.py b/google/ads/googleads/v24/enums/types/value_rule_set_attachment_type.py new file mode 100644 index 000000000..4828cae58 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/value_rule_set_attachment_type.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ValueRuleSetAttachmentTypeEnum", + }, +) + + +class ValueRuleSetAttachmentTypeEnum(proto.Message): + r"""Container for enum describing where a value rule set is + attached. + + """ + + class ValueRuleSetAttachmentType(proto.Enum): + r"""Possible level where a value rule set is attached. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + CUSTOMER (2): + Attached to the customer. + CAMPAIGN (3): + Attached to a campaign. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER = 2 + CAMPAIGN = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/value_rule_set_dimension.py b/google/ads/googleads/v24/enums/types/value_rule_set_dimension.py new file mode 100644 index 000000000..d9429aa76 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/value_rule_set_dimension.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "ValueRuleSetDimensionEnum", + }, +) + + +class ValueRuleSetDimensionEnum(proto.Message): + r"""Container for enum describing possible dimensions of a + conversion value rule set. + + """ + + class ValueRuleSetDimension(proto.Enum): + r"""Possible dimensions of a conversion value rule set. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + GEO_LOCATION (2): + Dimension for geo location. + DEVICE (3): + Dimension for device type. + AUDIENCE (4): + Dimension for audience. + NO_CONDITION (5): + This dimension implies the rule will always + apply. + ITINERARY (6): + Dimension for itinerary. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + GEO_LOCATION = 2 + DEVICE = 3 + AUDIENCE = 4 + NO_CONDITION = 5 + ITINERARY = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/vanity_pharma_display_url_mode.py b/google/ads/googleads/v24/enums/types/vanity_pharma_display_url_mode.py new file mode 100644 index 000000000..673db939b --- /dev/null +++ b/google/ads/googleads/v24/enums/types/vanity_pharma_display_url_mode.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "VanityPharmaDisplayUrlModeEnum", + }, +) + + +class VanityPharmaDisplayUrlModeEnum(proto.Message): + r"""The display mode for vanity pharma URLs.""" + + class VanityPharmaDisplayUrlMode(proto.Enum): + r"""Enum describing possible display modes for vanity pharma + URLs. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + MANUFACTURER_WEBSITE_URL (2): + Replace vanity pharma URL with manufacturer + website url. + WEBSITE_DESCRIPTION (3): + Replace vanity pharma URL with description of + the website. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MANUFACTURER_WEBSITE_URL = 2 + WEBSITE_DESCRIPTION = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/vanity_pharma_text.py b/google/ads/googleads/v24/enums/types/vanity_pharma_text.py new file mode 100644 index 000000000..6120d383d --- /dev/null +++ b/google/ads/googleads/v24/enums/types/vanity_pharma_text.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "VanityPharmaTextEnum", + }, +) + + +class VanityPharmaTextEnum(proto.Message): + r"""The text that will be displayed in display URL of the text ad + when website description is the selected display mode for vanity + pharma URLs. + + """ + + class VanityPharmaText(proto.Enum): + r"""Enum describing possible text. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PRESCRIPTION_TREATMENT_WEBSITE_EN (2): + Prescription treatment website with website + content in English. + PRESCRIPTION_TREATMENT_WEBSITE_ES (3): + Prescription treatment website with website + content in Spanish (Sitio de tratamientos con + receta). + PRESCRIPTION_DEVICE_WEBSITE_EN (4): + Prescription device website with website + content in English. + PRESCRIPTION_DEVICE_WEBSITE_ES (5): + Prescription device website with website + content in Spanish (Sitio de dispositivos con + receta). + MEDICAL_DEVICE_WEBSITE_EN (6): + Medical device website with website content + in English. + MEDICAL_DEVICE_WEBSITE_ES (7): + Medical device website with website content + in Spanish (Sitio de dispositivos médicos). + PREVENTATIVE_TREATMENT_WEBSITE_EN (8): + Preventative treatment website with website + content in English. + PREVENTATIVE_TREATMENT_WEBSITE_ES (9): + Preventative treatment website with website + content in Spanish (Sitio de tratamientos + preventivos). + PRESCRIPTION_CONTRACEPTION_WEBSITE_EN (10): + Prescription contraception website with + website content in English. + PRESCRIPTION_CONTRACEPTION_WEBSITE_ES (11): + Prescription contraception website with + website content in Spanish (Sitio de + anticonceptivos con receta). + PRESCRIPTION_VACCINE_WEBSITE_EN (12): + Prescription vaccine website with website + content in English. + PRESCRIPTION_VACCINE_WEBSITE_ES (13): + Prescription vaccine website with website + content in Spanish (Sitio de vacunas con + receta). + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PRESCRIPTION_TREATMENT_WEBSITE_EN = 2 + PRESCRIPTION_TREATMENT_WEBSITE_ES = 3 + PRESCRIPTION_DEVICE_WEBSITE_EN = 4 + PRESCRIPTION_DEVICE_WEBSITE_ES = 5 + MEDICAL_DEVICE_WEBSITE_EN = 6 + MEDICAL_DEVICE_WEBSITE_ES = 7 + PREVENTATIVE_TREATMENT_WEBSITE_EN = 8 + PREVENTATIVE_TREATMENT_WEBSITE_ES = 9 + PRESCRIPTION_CONTRACEPTION_WEBSITE_EN = 10 + PRESCRIPTION_CONTRACEPTION_WEBSITE_ES = 11 + PRESCRIPTION_VACCINE_WEBSITE_EN = 12 + PRESCRIPTION_VACCINE_WEBSITE_ES = 13 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/vertical_ads_item_vertical_type.py b/google/ads/googleads/v24/enums/types/vertical_ads_item_vertical_type.py new file mode 100644 index 000000000..b98cd6690 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/vertical_ads_item_vertical_type.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "VerticalAdsItemVerticalTypeEnum", + }, +) + + +class VerticalAdsItemVerticalTypeEnum(proto.Message): + r"""Container for enum describing Vertical Ads Item Vertical Type for + SharedSet of type VERTICAL_ADS_ITEM_GROUP_RULE_LIST. + + """ + + class VerticalAdsItemVerticalType(proto.Enum): + r"""Enum describing Vertical Ads Item Vertical Type for SharedSet of + type VERTICAL_ADS_ITEM_GROUP_RULE_LIST. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + HOTELS (2): + Hotels travel vertical. + VACATION_RENTALS (3): + Vacation rentals travel vertical. + RENTAL_CARS (4): + Rental cars travel vertical. + EVENTS (5): + Events travel vertical. + THINGS_TO_DO (6): + Things to do travel vertical. + FLIGHTS (7): + Flights travel vertical. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + HOTELS = 2 + VACATION_RENTALS = 3 + RENTAL_CARS = 4 + EVENTS = 5 + THINGS_TO_DO = 6 + FLIGHTS = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/video_ad_format_restriction.py b/google/ads/googleads/v24/enums/types/video_ad_format_restriction.py new file mode 100644 index 000000000..09d6a73a1 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/video_ad_format_restriction.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "VideoAdFormatRestrictionEnum", + }, +) + + +class VideoAdFormatRestrictionEnum(proto.Message): + r"""Container for enum describing format restrictions for video + responsive ads in video campaigns. + + """ + + class VideoAdFormatRestriction(proto.Enum): + r"""Enum describing format restrictions for responsive ads in + video campaigns. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + NON_SKIPPABLE_IN_STREAM (2): + Non-skippable in-stream video responsive ad. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NON_SKIPPABLE_IN_STREAM = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/video_ad_sequence_interaction_type.py b/google/ads/googleads/v24/enums/types/video_ad_sequence_interaction_type.py new file mode 100644 index 000000000..643417282 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/video_ad_sequence_interaction_type.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "VideoAdSequenceInteractionTypeEnum", + }, +) + + +class VideoAdSequenceInteractionTypeEnum(proto.Message): + r"""Container for enum describing an interaction between a viewer + and a video in a video ad sequence. + + """ + + class VideoAdSequenceInteractionType(proto.Enum): + r"""Enum describing an interaction between a viewer and a video + in a video ad sequence. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + PAID_VIEW (2): + The viewer engaged with or watched at least + 30 seconds of the ad (or the entire ad, if it + was less than 30 seconds). Only available for + campaigns using Target CPM as the bidding + strategy and skippable in-stream ads as the ad + format. + SKIP (3): + The viewer skipped the ad. Only available for + campaigns using Target CPM as the bidding + strategy and skippable in-stream ads as the ad + format. + IMPRESSION (4): + The ad was shown to the viewer. + ENGAGED_IMPRESSION (5): + An ad impression that was not immediately + skipped, but didn't reach the billable event + either. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PAID_VIEW = 2 + SKIP = 3 + IMPRESSION = 4 + ENGAGED_IMPRESSION = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/video_ad_sequence_minimum_duration.py b/google/ads/googleads/v24/enums/types/video_ad_sequence_minimum_duration.py new file mode 100644 index 000000000..befbb5448 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/video_ad_sequence_minimum_duration.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "VideoAdSequenceMinimumDurationEnum", + }, +) + + +class VideoAdSequenceMinimumDurationEnum(proto.Message): + r"""Container for enum describing possible times after starting a + video ad sequence when a user is eligible to repeat the + sequence. + + """ + + class VideoAdSequenceMinimumDuration(proto.Enum): + r"""Enum describing possible times after starting a video ad + sequence when a user is eligible to repeat the sequence. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + WEEK (2): + Users are eligible to restart a sequence once + they have completed the sequence and at least 7 + days have passed since sequence start. + MONTH (3): + Users are eligible to restart a sequence once + at least 30 days have passed since sequence + start. Users are eligible to start the sequence + again even if they haven't completed the + sequence. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + WEEK = 2 + MONTH = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/video_enhancement_source.py b/google/ads/googleads/v24/enums/types/video_enhancement_source.py new file mode 100644 index 000000000..c19b83ecb --- /dev/null +++ b/google/ads/googleads/v24/enums/types/video_enhancement_source.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "VideoEnhancementSourceEnum", + }, +) + + +class VideoEnhancementSourceEnum(proto.Message): + r"""Container for enum describing possible video enhancement + source types. + + """ + + class VideoEnhancementSource(proto.Enum): + r"""Enum listing the possible video sources. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ADVERTISER (2): + The video is provided by the advertiser. + ENHANCED_BY_GOOGLE_ADS (3): + The video is an enhancement generated by + Google. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ADVERTISER = 2 + ENHANCED_BY_GOOGLE_ADS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/video_thumbnail.py b/google/ads/googleads/v24/enums/types/video_thumbnail.py new file mode 100644 index 000000000..1771c9ca5 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/video_thumbnail.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "VideoThumbnailEnum", + }, +) + + +class VideoThumbnailEnum(proto.Message): + r"""Defines the thumbnail to use for In-Display video ads. Note that + DEFAULT_THUMBNAIL may have been uploaded by the user while + thumbnails 1-3 are auto-generated from the video. + + """ + + class VideoThumbnail(proto.Enum): + r"""Enum listing the possible types of a video thumbnail. + + Values: + UNSPECIFIED (0): + The type has not been specified. + UNKNOWN (1): + The received value is not known in this + version. This is a response-only value. + DEFAULT_THUMBNAIL (2): + The default thumbnail. Can be auto-generated + or user-uploaded. + THUMBNAIL_1 (3): + Thumbnail 1, generated from the video. + THUMBNAIL_2 (4): + Thumbnail 2, generated from the video. + THUMBNAIL_3 (5): + Thumbnail 3, generated from the video. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DEFAULT_THUMBNAIL = 2 + THUMBNAIL_1 = 3 + THUMBNAIL_2 = 4 + THUMBNAIL_3 = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/webpage_condition_operand.py b/google/ads/googleads/v24/enums/types/webpage_condition_operand.py new file mode 100644 index 000000000..978e17e17 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/webpage_condition_operand.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "WebpageConditionOperandEnum", + }, +) + + +class WebpageConditionOperandEnum(proto.Message): + r"""Container for enum describing webpage condition operand in + webpage criterion. + + """ + + class WebpageConditionOperand(proto.Enum): + r"""The webpage condition operand in webpage criterion. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + URL (2): + Operand denoting a webpage URL targeting + condition. + CATEGORY (3): + Operand denoting a webpage category targeting + condition. + PAGE_TITLE (4): + Operand denoting a webpage title targeting + condition. + PAGE_CONTENT (5): + Operand denoting a webpage content targeting + condition. + CUSTOM_LABEL (6): + Operand denoting a webpage custom label + targeting condition. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + URL = 2 + CATEGORY = 3 + PAGE_TITLE = 4 + PAGE_CONTENT = 5 + CUSTOM_LABEL = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/webpage_condition_operator.py b/google/ads/googleads/v24/enums/types/webpage_condition_operator.py new file mode 100644 index 000000000..19d77e615 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/webpage_condition_operator.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "WebpageConditionOperatorEnum", + }, +) + + +class WebpageConditionOperatorEnum(proto.Message): + r"""Container for enum describing webpage condition operator in + webpage criterion. + + """ + + class WebpageConditionOperator(proto.Enum): + r"""The webpage condition operator in webpage criterion. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + EQUALS (2): + The argument web condition is equal to the + compared web condition. + CONTAINS (3): + The argument web condition is part of the + compared web condition. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EQUALS = 2 + CONTAINS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/youtube_video_privacy.py b/google/ads/googleads/v24/enums/types/youtube_video_privacy.py new file mode 100644 index 000000000..245426209 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/youtube_video_privacy.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "YouTubeVideoPrivacyEnum", + }, +) + + +class YouTubeVideoPrivacyEnum(proto.Message): + r"""Container for enum describing the privacy status of a YouTube + video. + + """ + + class YouTubeVideoPrivacy(proto.Enum): + r"""Describes the privacy status of a YouTube video. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + PUBLIC (2): + Video is public. + UNLISTED (3): + Video is unlisted. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PUBLIC = 2 + UNLISTED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/youtube_video_property.py b/google/ads/googleads/v24/enums/types/youtube_video_property.py new file mode 100644 index 000000000..5d0e59bc4 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/youtube_video_property.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "YouTubeVideoPropertyEnum", + }, +) + + +class YouTubeVideoPropertyEnum(proto.Message): + r"""Container for enum describing the property of a YouTube + video. + + """ + + class YouTubeVideoProperty(proto.Enum): + r"""Describes a property of a YouTube video. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + LIVE_STREAM (2): + Video is a live stream. + SHORTS (3): + Video is Shorts eligible. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LIVE_STREAM = 2 + SHORTS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/enums/types/youtube_video_upload_state.py b/google/ads/googleads/v24/enums/types/youtube_video_upload_state.py new file mode 100644 index 000000000..438a5b9f8 --- /dev/null +++ b/google/ads/googleads/v24/enums/types/youtube_video_upload_state.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.enums", + marshal="google.ads.googleads.v24", + manifest={ + "YouTubeVideoUploadStateEnum", + }, +) + + +class YouTubeVideoUploadStateEnum(proto.Message): + r"""Container for enum describing the state of a YouTube video + upload. + + """ + + class YouTubeVideoUploadState(proto.Enum): + r"""Represents the current state of a video within its upload and + processing lifecycle. It tracks the full progression from upload + initiation through processing and completion, including failure, + rejection, or deletion outcomes. It helps determine whether a + video is still being uploaded, ready for use, or no longer + available. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + The value is unknown in this version. + PENDING (2): + The video is currently being uploaded. + UPLOADED (3): + The video was uploaded and is being + processed. + PROCESSED (4): + The video was successfully uploaded and + processed. + FAILED (5): + The video upload or processing did not + complete successfully. + REJECTED (6): + The video was not accepted due to validation + or policy reasons. + UNAVAILABLE (7): + The video upload state is unavailable. It may + have been removed from YouTube. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + UPLOADED = 3 + PROCESSED = 4 + FAILED = 5 + REJECTED = 6 + UNAVAILABLE = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/__init__.py b/google/ads/googleads/v24/errors/__init__.py new file mode 100644 index 000000000..7ecb8f2e1 --- /dev/null +++ b/google/ads/googleads/v24/errors/__init__.py @@ -0,0 +1,529 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 google.ads.googleads.v24 import gapic_version as package_version + +import google.api_core as api_core +import sys + +__version__ = package_version.__version__ + +if sys.version_info >= (3, 8): # pragma: NO COVER + from importlib import metadata +else: # pragma: NO COVER + # TODO(https://github.com/googleapis/python-api-core/issues/835): Remove + # this code path once we drop support for Python 3.7 + import importlib_metadata as metadata + + +from .types.access_invitation_error import AccessInvitationErrorEnum +from .types.account_budget_proposal_error import AccountBudgetProposalErrorEnum +from .types.account_link_error import AccountLinkErrorEnum +from .types.action_error import ActionErrorEnum +from .types.ad_customizer_error import AdCustomizerErrorEnum +from .types.ad_error import AdErrorEnum +from .types.ad_group_ad_error import AdGroupAdErrorEnum +from .types.ad_group_bid_modifier_error import AdGroupBidModifierErrorEnum +from .types.ad_group_criterion_customizer_error import ( + AdGroupCriterionCustomizerErrorEnum, +) +from .types.ad_group_criterion_error import AdGroupCriterionErrorEnum +from .types.ad_group_customizer_error import AdGroupCustomizerErrorEnum +from .types.ad_group_error import AdGroupErrorEnum +from .types.ad_group_feed_error import AdGroupFeedErrorEnum +from .types.ad_parameter_error import AdParameterErrorEnum +from .types.ad_sharing_error import AdSharingErrorEnum +from .types.adx_error import AdxErrorEnum +from .types.asset_error import AssetErrorEnum +from .types.asset_generation_error import AssetGenerationErrorEnum +from .types.asset_group_asset_error import AssetGroupAssetErrorEnum +from .types.asset_group_error import AssetGroupErrorEnum +from .types.asset_group_listing_group_filter_error import ( + AssetGroupListingGroupFilterErrorEnum, +) +from .types.asset_group_signal_error import AssetGroupSignalErrorEnum +from .types.asset_link_error import AssetLinkErrorEnum +from .types.asset_set_asset_error import AssetSetAssetErrorEnum +from .types.asset_set_error import AssetSetErrorEnum +from .types.asset_set_link_error import AssetSetLinkErrorEnum +from .types.audience_error import AudienceErrorEnum +from .types.audience_insights_error import AudienceInsightsErrorEnum +from .types.authentication_error import AuthenticationErrorEnum +from .types.authorization_error import AuthorizationErrorEnum +from .types.automatically_created_asset_removal_error import ( + AutomaticallyCreatedAssetRemovalErrorEnum, +) +from .types.batch_job_error import BatchJobErrorEnum +from .types.benchmarks_error import BenchmarksErrorEnum +from .types.bidding_error import BiddingErrorEnum +from .types.bidding_strategy_error import BiddingStrategyErrorEnum +from .types.billing_setup_error import BillingSetupErrorEnum +from .types.brand_guidelines_migration_error import ( + BrandGuidelinesMigrationErrorEnum, +) +from .types.campaign_budget_error import CampaignBudgetErrorEnum +from .types.campaign_conversion_goal_error import ( + CampaignConversionGoalErrorEnum, +) +from .types.campaign_criterion_error import CampaignCriterionErrorEnum +from .types.campaign_customizer_error import CampaignCustomizerErrorEnum +from .types.campaign_draft_error import CampaignDraftErrorEnum +from .types.campaign_error import CampaignErrorEnum +from .types.campaign_experiment_error import CampaignExperimentErrorEnum +from .types.campaign_feed_error import CampaignFeedErrorEnum +from .types.campaign_goal_config_error import CampaignGoalConfigErrorEnum +from .types.campaign_lifecycle_goal_error import CampaignLifecycleGoalErrorEnum +from .types.campaign_shared_set_error import CampaignSharedSetErrorEnum +from .types.change_event_error import ChangeEventErrorEnum +from .types.change_status_error import ChangeStatusErrorEnum +from .types.click_view_error import ClickViewErrorEnum +from .types.collection_size_error import CollectionSizeErrorEnum +from .types.content_creator_insights_error import ( + ContentCreatorInsightsErrorEnum, +) +from .types.context_error import ContextErrorEnum +from .types.conversion_action_error import ConversionActionErrorEnum +from .types.conversion_adjustment_upload_error import ( + ConversionAdjustmentUploadErrorEnum, +) +from .types.conversion_custom_variable_error import ( + ConversionCustomVariableErrorEnum, +) +from .types.conversion_goal_campaign_config_error import ( + ConversionGoalCampaignConfigErrorEnum, +) +from .types.conversion_upload_error import ConversionUploadErrorEnum +from .types.conversion_value_rule_error import ConversionValueRuleErrorEnum +from .types.conversion_value_rule_set_error import ( + ConversionValueRuleSetErrorEnum, +) +from .types.country_code_error import CountryCodeErrorEnum +from .types.criterion_error import CriterionErrorEnum +from .types.currency_code_error import CurrencyCodeErrorEnum +from .types.currency_error import CurrencyErrorEnum +from .types.custom_audience_error import CustomAudienceErrorEnum +from .types.custom_conversion_goal_error import CustomConversionGoalErrorEnum +from .types.custom_interest_error import CustomInterestErrorEnum +from .types.customer_client_link_error import CustomerClientLinkErrorEnum +from .types.customer_customizer_error import CustomerCustomizerErrorEnum +from .types.customer_error import CustomerErrorEnum +from .types.customer_feed_error import CustomerFeedErrorEnum +from .types.customer_lifecycle_goal_error import CustomerLifecycleGoalErrorEnum +from .types.customer_manager_link_error import CustomerManagerLinkErrorEnum +from .types.customer_sk_ad_network_conversion_value_schema_error import ( + CustomerSkAdNetworkConversionValueSchemaErrorEnum, +) +from .types.customer_user_access_error import CustomerUserAccessErrorEnum +from .types.customizer_attribute_error import CustomizerAttributeErrorEnum +from .types.data_link_error import DataLinkErrorEnum +from .types.database_error import DatabaseErrorEnum +from .types.date_error import DateErrorEnum +from .types.date_range_error import DateRangeErrorEnum +from .types.distinct_error import DistinctErrorEnum +from .types.enum_error import EnumErrorEnum +from .types.errors import BudgetPerDayMinimumErrorDetails +from .types.errors import ErrorCode +from .types.errors import ErrorDetails +from .types.errors import ErrorLocation +from .types.errors import GoogleAdsError +from .types.errors import GoogleAdsFailure +from .types.errors import PolicyFindingDetails +from .types.errors import PolicyViolationDetails +from .types.errors import QuotaErrorDetails +from .types.errors import ReservationErrorDetails +from .types.errors import ResourceCountDetails +from .types.experiment_arm_error import ExperimentArmErrorEnum +from .types.experiment_error import ExperimentErrorEnum +from .types.extension_feed_item_error import ExtensionFeedItemErrorEnum +from .types.extension_setting_error import ExtensionSettingErrorEnum +from .types.feed_attribute_reference_error import ( + FeedAttributeReferenceErrorEnum, +) +from .types.feed_error import FeedErrorEnum +from .types.feed_item_error import FeedItemErrorEnum +from .types.feed_item_set_error import FeedItemSetErrorEnum +from .types.feed_item_set_link_error import FeedItemSetLinkErrorEnum +from .types.feed_item_target_error import FeedItemTargetErrorEnum +from .types.feed_item_validation_error import FeedItemValidationErrorEnum +from .types.feed_mapping_error import FeedMappingErrorEnum +from .types.field_error import FieldErrorEnum +from .types.field_mask_error import FieldMaskErrorEnum +from .types.final_url_expansion_asset_view_error import ( + FinalUrlExpansionAssetViewErrorEnum, +) +from .types.function_error import FunctionErrorEnum +from .types.function_parsing_error import FunctionParsingErrorEnum +from .types.geo_target_constant_suggestion_error import ( + GeoTargetConstantSuggestionErrorEnum, +) +from .types.goal_error import GoalErrorEnum +from .types.header_error import HeaderErrorEnum +from .types.id_error import IdErrorEnum +from .types.identity_verification_error import IdentityVerificationErrorEnum +from .types.image_error import ImageErrorEnum +from .types.incentive_error import IncentiveErrorEnum +from .types.internal_error import InternalErrorEnum +from .types.invoice_error import InvoiceErrorEnum +from .types.keyword_plan_ad_group_error import KeywordPlanAdGroupErrorEnum +from .types.keyword_plan_ad_group_keyword_error import ( + KeywordPlanAdGroupKeywordErrorEnum, +) +from .types.keyword_plan_campaign_error import KeywordPlanCampaignErrorEnum +from .types.keyword_plan_campaign_keyword_error import ( + KeywordPlanCampaignKeywordErrorEnum, +) +from .types.keyword_plan_error import KeywordPlanErrorEnum +from .types.keyword_plan_idea_error import KeywordPlanIdeaErrorEnum +from .types.label_error import LabelErrorEnum +from .types.language_code_error import LanguageCodeErrorEnum +from .types.list_operation_error import ListOperationErrorEnum +from .types.manager_link_error import ManagerLinkErrorEnum +from .types.media_bundle_error import MediaBundleErrorEnum +from .types.media_file_error import MediaFileErrorEnum +from .types.media_upload_error import MediaUploadErrorEnum +from .types.merchant_center_error import MerchantCenterErrorEnum +from .types.multiplier_error import MultiplierErrorEnum +from .types.mutate_error import MutateErrorEnum +from .types.new_resource_creation_error import NewResourceCreationErrorEnum +from .types.not_allowlisted_error import NotAllowlistedErrorEnum +from .types.not_empty_error import NotEmptyErrorEnum +from .types.null_error import NullErrorEnum +from .types.offline_user_data_job_error import OfflineUserDataJobErrorEnum +from .types.operation_access_denied_error import OperationAccessDeniedErrorEnum +from .types.operator_error import OperatorErrorEnum +from .types.partial_failure_error import PartialFailureErrorEnum +from .types.payments_account_error import PaymentsAccountErrorEnum +from .types.policy_finding_error import PolicyFindingErrorEnum +from .types.policy_validation_parameter_error import ( + PolicyValidationParameterErrorEnum, +) +from .types.policy_violation_error import PolicyViolationErrorEnum +from .types.product_link_error import ProductLinkErrorEnum +from .types.product_link_invitation_error import ProductLinkInvitationErrorEnum +from .types.query_error import QueryErrorEnum +from .types.quota_error import QuotaErrorEnum +from .types.range_error import RangeErrorEnum +from .types.reach_plan_error import ReachPlanErrorEnum +from .types.recommendation_error import RecommendationErrorEnum +from .types.recommendation_subscription_error import ( + RecommendationSubscriptionErrorEnum, +) +from .types.region_code_error import RegionCodeErrorEnum +from .types.request_error import RequestErrorEnum +from .types.resource_access_denied_error import ResourceAccessDeniedErrorEnum +from .types.resource_count_limit_exceeded_error import ( + ResourceCountLimitExceededErrorEnum, +) +from .types.search_term_insight_error import SearchTermInsightErrorEnum +from .types.setting_error import SettingErrorEnum +from .types.shareable_preview_error import ShareablePreviewErrorEnum +from .types.shared_criterion_error import SharedCriterionErrorEnum +from .types.shared_set_error import SharedSetErrorEnum +from .types.shopping_product_error import ShoppingProductErrorEnum +from .types.size_limit_error import SizeLimitErrorEnum +from .types.smart_campaign_error import SmartCampaignErrorEnum +from .types.string_format_error import StringFormatErrorEnum +from .types.string_length_error import StringLengthErrorEnum +from .types.third_party_app_analytics_link_error import ( + ThirdPartyAppAnalyticsLinkErrorEnum, +) +from .types.time_zone_error import TimeZoneErrorEnum +from .types.url_field_error import UrlFieldErrorEnum +from .types.user_data_error import UserDataErrorEnum +from .types.user_list_customer_type_error import UserListCustomerTypeErrorEnum +from .types.user_list_error import UserListErrorEnum +from .types.video_campaign_error import VideoCampaignErrorEnum +from .types.video_reservation_error import VideoReservationErrorEnum +from .types.youtube_video_registration_error import ( + YoutubeVideoRegistrationErrorEnum, +) + +if hasattr(api_core, "check_python_version") and hasattr( + api_core, "check_dependency_versions" +): # pragma: NO COVER + api_core.check_python_version("google.ads.googleads.v24") # type: ignore + api_core.check_dependency_versions("google.ads.googleads.v24") # type: ignore +else: # pragma: NO COVER + # An older version of api_core is installed which does not define the + # functions above. We do equivalent checks manually. + try: + import warnings + import sys + + _py_version_str = sys.version.split()[0] + _package_label = "google.ads.googleads.v24" + if sys.version_info < (3, 9): + warnings.warn( + "You are using a non-supported Python version " + + f"({_py_version_str}). Google will not post any further " + + f"updates to {_package_label} supporting this Python version. " + + "Please upgrade to the latest Python version, or at " + + f"least to Python 3.9, and then update {_package_label}.", + FutureWarning, + ) + if sys.version_info[:2] == (3, 9): + warnings.warn( + f"You are using a Python version ({_py_version_str}) " + + f"which Google will stop supporting in {_package_label} in " + + "January 2026. Please " + + "upgrade to the latest Python version, or at " + + "least to Python 3.10, before then, and " + + f"then update {_package_label}.", + FutureWarning, + ) + + def parse_version_to_tuple(version_string: str): + """Safely converts a semantic version string to a comparable tuple of integers. + Example: "4.25.8" -> (4, 25, 8) + Ignores non-numeric parts and handles common version formats. + Args: + version_string: Version string in the format "x.y.z" or "x.y.z" + Returns: + Tuple of integers for the parsed version string. + """ + parts = [] + for part in version_string.split("."): + try: + parts.append(int(part)) + except ValueError: + # If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here. + # This is a simplification compared to 'packaging.parse_version', but sufficient + # for comparing strictly numeric semantic versions. + break + return tuple(parts) + + def _get_version(dependency_name): + try: + version_string: str = metadata.version(dependency_name) + parsed_version = parse_version_to_tuple(version_string) + return (parsed_version, version_string) + except Exception: + # Catch exceptions from metadata.version() (e.g., PackageNotFoundError) + # or errors during parse_version_to_tuple + return (None, "--") + + _dependency_package = "google.protobuf" + _next_supported_version = "4.25.8" + _next_supported_version_tuple = (4, 25, 8) + _recommendation = " (we recommend 6.x)" + (_version_used, _version_used_string) = _get_version( + _dependency_package + ) + if _version_used and _version_used < _next_supported_version_tuple: + warnings.warn( + f"Package {_package_label} depends on " + + f"{_dependency_package}, currently installed at version " + + f"{_version_used_string}. Future updates to " + + f"{_package_label} will require {_dependency_package} at " + + f"version {_next_supported_version} or higher{_recommendation}." + + " Please ensure " + + "that either (a) your Python environment doesn't pin the " + + f"version of {_dependency_package}, so that updates to " + + f"{_package_label} can require the higher version, or " + + "(b) you manually update your Python environment to use at " + + f"least version {_next_supported_version} of " + + f"{_dependency_package}.", + FutureWarning, + ) + except Exception: + warnings.warn( + "Could not determine the version of Python " + + "currently being used. To continue receiving " + + "updates for {_package_label}, ensure you are " + + "using a supported version of Python; see " + + "https://devguide.python.org/versions/" + ) + +__all__ = ( + "AccessInvitationErrorEnum", + "AccountBudgetProposalErrorEnum", + "AccountLinkErrorEnum", + "ActionErrorEnum", + "AdCustomizerErrorEnum", + "AdErrorEnum", + "AdGroupAdErrorEnum", + "AdGroupBidModifierErrorEnum", + "AdGroupCriterionCustomizerErrorEnum", + "AdGroupCriterionErrorEnum", + "AdGroupCustomizerErrorEnum", + "AdGroupErrorEnum", + "AdGroupFeedErrorEnum", + "AdParameterErrorEnum", + "AdSharingErrorEnum", + "AdxErrorEnum", + "AssetErrorEnum", + "AssetGenerationErrorEnum", + "AssetGroupAssetErrorEnum", + "AssetGroupErrorEnum", + "AssetGroupListingGroupFilterErrorEnum", + "AssetGroupSignalErrorEnum", + "AssetLinkErrorEnum", + "AssetSetAssetErrorEnum", + "AssetSetErrorEnum", + "AssetSetLinkErrorEnum", + "AudienceErrorEnum", + "AudienceInsightsErrorEnum", + "AuthenticationErrorEnum", + "AuthorizationErrorEnum", + "AutomaticallyCreatedAssetRemovalErrorEnum", + "BatchJobErrorEnum", + "BenchmarksErrorEnum", + "BiddingErrorEnum", + "BiddingStrategyErrorEnum", + "BillingSetupErrorEnum", + "BrandGuidelinesMigrationErrorEnum", + "BudgetPerDayMinimumErrorDetails", + "CampaignBudgetErrorEnum", + "CampaignConversionGoalErrorEnum", + "CampaignCriterionErrorEnum", + "CampaignCustomizerErrorEnum", + "CampaignDraftErrorEnum", + "CampaignErrorEnum", + "CampaignExperimentErrorEnum", + "CampaignFeedErrorEnum", + "CampaignGoalConfigErrorEnum", + "CampaignLifecycleGoalErrorEnum", + "CampaignSharedSetErrorEnum", + "ChangeEventErrorEnum", + "ChangeStatusErrorEnum", + "ClickViewErrorEnum", + "CollectionSizeErrorEnum", + "ContentCreatorInsightsErrorEnum", + "ContextErrorEnum", + "ConversionActionErrorEnum", + "ConversionAdjustmentUploadErrorEnum", + "ConversionCustomVariableErrorEnum", + "ConversionGoalCampaignConfigErrorEnum", + "ConversionUploadErrorEnum", + "ConversionValueRuleErrorEnum", + "ConversionValueRuleSetErrorEnum", + "CountryCodeErrorEnum", + "CriterionErrorEnum", + "CurrencyCodeErrorEnum", + "CurrencyErrorEnum", + "CustomAudienceErrorEnum", + "CustomConversionGoalErrorEnum", + "CustomInterestErrorEnum", + "CustomerClientLinkErrorEnum", + "CustomerCustomizerErrorEnum", + "CustomerErrorEnum", + "CustomerFeedErrorEnum", + "CustomerLifecycleGoalErrorEnum", + "CustomerManagerLinkErrorEnum", + "CustomerSkAdNetworkConversionValueSchemaErrorEnum", + "CustomerUserAccessErrorEnum", + "CustomizerAttributeErrorEnum", + "DataLinkErrorEnum", + "DatabaseErrorEnum", + "DateErrorEnum", + "DateRangeErrorEnum", + "DistinctErrorEnum", + "EnumErrorEnum", + "ErrorCode", + "ErrorDetails", + "ErrorLocation", + "ExperimentArmErrorEnum", + "ExperimentErrorEnum", + "ExtensionFeedItemErrorEnum", + "ExtensionSettingErrorEnum", + "FeedAttributeReferenceErrorEnum", + "FeedErrorEnum", + "FeedItemErrorEnum", + "FeedItemSetErrorEnum", + "FeedItemSetLinkErrorEnum", + "FeedItemTargetErrorEnum", + "FeedItemValidationErrorEnum", + "FeedMappingErrorEnum", + "FieldErrorEnum", + "FieldMaskErrorEnum", + "FinalUrlExpansionAssetViewErrorEnum", + "FunctionErrorEnum", + "FunctionParsingErrorEnum", + "GeoTargetConstantSuggestionErrorEnum", + "GoalErrorEnum", + "GoogleAdsError", + "GoogleAdsFailure", + "HeaderErrorEnum", + "IdErrorEnum", + "IdentityVerificationErrorEnum", + "ImageErrorEnum", + "IncentiveErrorEnum", + "InternalErrorEnum", + "InvoiceErrorEnum", + "KeywordPlanAdGroupErrorEnum", + "KeywordPlanAdGroupKeywordErrorEnum", + "KeywordPlanCampaignErrorEnum", + "KeywordPlanCampaignKeywordErrorEnum", + "KeywordPlanErrorEnum", + "KeywordPlanIdeaErrorEnum", + "LabelErrorEnum", + "LanguageCodeErrorEnum", + "ListOperationErrorEnum", + "ManagerLinkErrorEnum", + "MediaBundleErrorEnum", + "MediaFileErrorEnum", + "MediaUploadErrorEnum", + "MerchantCenterErrorEnum", + "MultiplierErrorEnum", + "MutateErrorEnum", + "NewResourceCreationErrorEnum", + "NotAllowlistedErrorEnum", + "NotEmptyErrorEnum", + "NullErrorEnum", + "OfflineUserDataJobErrorEnum", + "OperationAccessDeniedErrorEnum", + "OperatorErrorEnum", + "PartialFailureErrorEnum", + "PaymentsAccountErrorEnum", + "PolicyFindingDetails", + "PolicyFindingErrorEnum", + "PolicyValidationParameterErrorEnum", + "PolicyViolationDetails", + "PolicyViolationErrorEnum", + "ProductLinkErrorEnum", + "ProductLinkInvitationErrorEnum", + "QueryErrorEnum", + "QuotaErrorDetails", + "QuotaErrorEnum", + "RangeErrorEnum", + "ReachPlanErrorEnum", + "RecommendationErrorEnum", + "RecommendationSubscriptionErrorEnum", + "RegionCodeErrorEnum", + "RequestErrorEnum", + "ReservationErrorDetails", + "ResourceAccessDeniedErrorEnum", + "ResourceCountDetails", + "ResourceCountLimitExceededErrorEnum", + "SearchTermInsightErrorEnum", + "SettingErrorEnum", + "ShareablePreviewErrorEnum", + "SharedCriterionErrorEnum", + "SharedSetErrorEnum", + "ShoppingProductErrorEnum", + "SizeLimitErrorEnum", + "SmartCampaignErrorEnum", + "StringFormatErrorEnum", + "StringLengthErrorEnum", + "ThirdPartyAppAnalyticsLinkErrorEnum", + "TimeZoneErrorEnum", + "UrlFieldErrorEnum", + "UserDataErrorEnum", + "UserListCustomerTypeErrorEnum", + "UserListErrorEnum", + "VideoCampaignErrorEnum", + "VideoReservationErrorEnum", + "YoutubeVideoRegistrationErrorEnum", +) diff --git a/google/ads/googleads/v24/errors/services/__init__.py b/google/ads/googleads/v24/errors/services/__init__.py new file mode 100644 index 000000000..cbf94b283 --- /dev/null +++ b/google/ads/googleads/v24/errors/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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. +# diff --git a/google/ads/googleads/v24/errors/types/__init__.py b/google/ads/googleads/v24/errors/types/__init__.py new file mode 100644 index 000000000..e43bfd04a --- /dev/null +++ b/google/ads/googleads/v24/errors/types/__init__.py @@ -0,0 +1,714 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .access_invitation_error import ( + AccessInvitationErrorEnum, +) +from .account_budget_proposal_error import ( + AccountBudgetProposalErrorEnum, +) +from .account_link_error import ( + AccountLinkErrorEnum, +) +from .action_error import ( + ActionErrorEnum, +) +from .ad_customizer_error import ( + AdCustomizerErrorEnum, +) +from .ad_error import ( + AdErrorEnum, +) +from .ad_group_ad_error import ( + AdGroupAdErrorEnum, +) +from .ad_group_bid_modifier_error import ( + AdGroupBidModifierErrorEnum, +) +from .ad_group_criterion_customizer_error import ( + AdGroupCriterionCustomizerErrorEnum, +) +from .ad_group_criterion_error import ( + AdGroupCriterionErrorEnum, +) +from .ad_group_customizer_error import ( + AdGroupCustomizerErrorEnum, +) +from .ad_group_error import ( + AdGroupErrorEnum, +) +from .ad_group_feed_error import ( + AdGroupFeedErrorEnum, +) +from .ad_parameter_error import ( + AdParameterErrorEnum, +) +from .ad_sharing_error import ( + AdSharingErrorEnum, +) +from .adx_error import ( + AdxErrorEnum, +) +from .asset_error import ( + AssetErrorEnum, +) +from .asset_generation_error import ( + AssetGenerationErrorEnum, +) +from .asset_group_asset_error import ( + AssetGroupAssetErrorEnum, +) +from .asset_group_error import ( + AssetGroupErrorEnum, +) +from .asset_group_listing_group_filter_error import ( + AssetGroupListingGroupFilterErrorEnum, +) +from .asset_group_signal_error import ( + AssetGroupSignalErrorEnum, +) +from .asset_link_error import ( + AssetLinkErrorEnum, +) +from .asset_set_asset_error import ( + AssetSetAssetErrorEnum, +) +from .asset_set_error import ( + AssetSetErrorEnum, +) +from .asset_set_link_error import ( + AssetSetLinkErrorEnum, +) +from .audience_error import ( + AudienceErrorEnum, +) +from .audience_insights_error import ( + AudienceInsightsErrorEnum, +) +from .authentication_error import ( + AuthenticationErrorEnum, +) +from .authorization_error import ( + AuthorizationErrorEnum, +) +from .automatically_created_asset_removal_error import ( + AutomaticallyCreatedAssetRemovalErrorEnum, +) +from .batch_job_error import ( + BatchJobErrorEnum, +) +from .benchmarks_error import ( + BenchmarksErrorEnum, +) +from .bidding_error import ( + BiddingErrorEnum, +) +from .bidding_strategy_error import ( + BiddingStrategyErrorEnum, +) +from .billing_setup_error import ( + BillingSetupErrorEnum, +) +from .brand_guidelines_migration_error import ( + BrandGuidelinesMigrationErrorEnum, +) +from .campaign_budget_error import ( + CampaignBudgetErrorEnum, +) +from .campaign_conversion_goal_error import ( + CampaignConversionGoalErrorEnum, +) +from .campaign_criterion_error import ( + CampaignCriterionErrorEnum, +) +from .campaign_customizer_error import ( + CampaignCustomizerErrorEnum, +) +from .campaign_draft_error import ( + CampaignDraftErrorEnum, +) +from .campaign_error import ( + CampaignErrorEnum, +) +from .campaign_experiment_error import ( + CampaignExperimentErrorEnum, +) +from .campaign_feed_error import ( + CampaignFeedErrorEnum, +) +from .campaign_goal_config_error import ( + CampaignGoalConfigErrorEnum, +) +from .campaign_lifecycle_goal_error import ( + CampaignLifecycleGoalErrorEnum, +) +from .campaign_shared_set_error import ( + CampaignSharedSetErrorEnum, +) +from .change_event_error import ( + ChangeEventErrorEnum, +) +from .change_status_error import ( + ChangeStatusErrorEnum, +) +from .click_view_error import ( + ClickViewErrorEnum, +) +from .collection_size_error import ( + CollectionSizeErrorEnum, +) +from .content_creator_insights_error import ( + ContentCreatorInsightsErrorEnum, +) +from .context_error import ( + ContextErrorEnum, +) +from .conversion_action_error import ( + ConversionActionErrorEnum, +) +from .conversion_adjustment_upload_error import ( + ConversionAdjustmentUploadErrorEnum, +) +from .conversion_custom_variable_error import ( + ConversionCustomVariableErrorEnum, +) +from .conversion_goal_campaign_config_error import ( + ConversionGoalCampaignConfigErrorEnum, +) +from .conversion_upload_error import ( + ConversionUploadErrorEnum, +) +from .conversion_value_rule_error import ( + ConversionValueRuleErrorEnum, +) +from .conversion_value_rule_set_error import ( + ConversionValueRuleSetErrorEnum, +) +from .country_code_error import ( + CountryCodeErrorEnum, +) +from .criterion_error import ( + CriterionErrorEnum, +) +from .currency_code_error import ( + CurrencyCodeErrorEnum, +) +from .currency_error import ( + CurrencyErrorEnum, +) +from .custom_audience_error import ( + CustomAudienceErrorEnum, +) +from .custom_conversion_goal_error import ( + CustomConversionGoalErrorEnum, +) +from .custom_interest_error import ( + CustomInterestErrorEnum, +) +from .customer_client_link_error import ( + CustomerClientLinkErrorEnum, +) +from .customer_customizer_error import ( + CustomerCustomizerErrorEnum, +) +from .customer_error import ( + CustomerErrorEnum, +) +from .customer_feed_error import ( + CustomerFeedErrorEnum, +) +from .customer_lifecycle_goal_error import ( + CustomerLifecycleGoalErrorEnum, +) +from .customer_manager_link_error import ( + CustomerManagerLinkErrorEnum, +) +from .customer_sk_ad_network_conversion_value_schema_error import ( + CustomerSkAdNetworkConversionValueSchemaErrorEnum, +) +from .customer_user_access_error import ( + CustomerUserAccessErrorEnum, +) +from .customizer_attribute_error import ( + CustomizerAttributeErrorEnum, +) +from .data_link_error import ( + DataLinkErrorEnum, +) +from .database_error import ( + DatabaseErrorEnum, +) +from .date_error import ( + DateErrorEnum, +) +from .date_range_error import ( + DateRangeErrorEnum, +) +from .distinct_error import ( + DistinctErrorEnum, +) +from .enum_error import ( + EnumErrorEnum, +) +from .errors import ( + BudgetPerDayMinimumErrorDetails, + ErrorCode, + ErrorDetails, + ErrorLocation, + GoogleAdsError, + GoogleAdsFailure, + PolicyFindingDetails, + PolicyViolationDetails, + QuotaErrorDetails, + ReservationErrorDetails, + ResourceCountDetails, +) +from .experiment_arm_error import ( + ExperimentArmErrorEnum, +) +from .experiment_error import ( + ExperimentErrorEnum, +) +from .extension_feed_item_error import ( + ExtensionFeedItemErrorEnum, +) +from .extension_setting_error import ( + ExtensionSettingErrorEnum, +) +from .feed_attribute_reference_error import ( + FeedAttributeReferenceErrorEnum, +) +from .feed_error import ( + FeedErrorEnum, +) +from .feed_item_error import ( + FeedItemErrorEnum, +) +from .feed_item_set_error import ( + FeedItemSetErrorEnum, +) +from .feed_item_set_link_error import ( + FeedItemSetLinkErrorEnum, +) +from .feed_item_target_error import ( + FeedItemTargetErrorEnum, +) +from .feed_item_validation_error import ( + FeedItemValidationErrorEnum, +) +from .feed_mapping_error import ( + FeedMappingErrorEnum, +) +from .field_error import ( + FieldErrorEnum, +) +from .field_mask_error import ( + FieldMaskErrorEnum, +) +from .final_url_expansion_asset_view_error import ( + FinalUrlExpansionAssetViewErrorEnum, +) +from .function_error import ( + FunctionErrorEnum, +) +from .function_parsing_error import ( + FunctionParsingErrorEnum, +) +from .geo_target_constant_suggestion_error import ( + GeoTargetConstantSuggestionErrorEnum, +) +from .goal_error import ( + GoalErrorEnum, +) +from .header_error import ( + HeaderErrorEnum, +) +from .id_error import ( + IdErrorEnum, +) +from .identity_verification_error import ( + IdentityVerificationErrorEnum, +) +from .image_error import ( + ImageErrorEnum, +) +from .incentive_error import ( + IncentiveErrorEnum, +) +from .internal_error import ( + InternalErrorEnum, +) +from .invoice_error import ( + InvoiceErrorEnum, +) +from .keyword_plan_ad_group_error import ( + KeywordPlanAdGroupErrorEnum, +) +from .keyword_plan_ad_group_keyword_error import ( + KeywordPlanAdGroupKeywordErrorEnum, +) +from .keyword_plan_campaign_error import ( + KeywordPlanCampaignErrorEnum, +) +from .keyword_plan_campaign_keyword_error import ( + KeywordPlanCampaignKeywordErrorEnum, +) +from .keyword_plan_error import ( + KeywordPlanErrorEnum, +) +from .keyword_plan_idea_error import ( + KeywordPlanIdeaErrorEnum, +) +from .label_error import ( + LabelErrorEnum, +) +from .language_code_error import ( + LanguageCodeErrorEnum, +) +from .list_operation_error import ( + ListOperationErrorEnum, +) +from .manager_link_error import ( + ManagerLinkErrorEnum, +) +from .media_bundle_error import ( + MediaBundleErrorEnum, +) +from .media_file_error import ( + MediaFileErrorEnum, +) +from .media_upload_error import ( + MediaUploadErrorEnum, +) +from .merchant_center_error import ( + MerchantCenterErrorEnum, +) +from .multiplier_error import ( + MultiplierErrorEnum, +) +from .mutate_error import ( + MutateErrorEnum, +) +from .new_resource_creation_error import ( + NewResourceCreationErrorEnum, +) +from .not_allowlisted_error import ( + NotAllowlistedErrorEnum, +) +from .not_empty_error import ( + NotEmptyErrorEnum, +) +from .null_error import ( + NullErrorEnum, +) +from .offline_user_data_job_error import ( + OfflineUserDataJobErrorEnum, +) +from .operation_access_denied_error import ( + OperationAccessDeniedErrorEnum, +) +from .operator_error import ( + OperatorErrorEnum, +) +from .partial_failure_error import ( + PartialFailureErrorEnum, +) +from .payments_account_error import ( + PaymentsAccountErrorEnum, +) +from .policy_finding_error import ( + PolicyFindingErrorEnum, +) +from .policy_validation_parameter_error import ( + PolicyValidationParameterErrorEnum, +) +from .policy_violation_error import ( + PolicyViolationErrorEnum, +) +from .product_link_error import ( + ProductLinkErrorEnum, +) +from .product_link_invitation_error import ( + ProductLinkInvitationErrorEnum, +) +from .query_error import ( + QueryErrorEnum, +) +from .quota_error import ( + QuotaErrorEnum, +) +from .range_error import ( + RangeErrorEnum, +) +from .reach_plan_error import ( + ReachPlanErrorEnum, +) +from .recommendation_error import ( + RecommendationErrorEnum, +) +from .recommendation_subscription_error import ( + RecommendationSubscriptionErrorEnum, +) +from .region_code_error import ( + RegionCodeErrorEnum, +) +from .request_error import ( + RequestErrorEnum, +) +from .resource_access_denied_error import ( + ResourceAccessDeniedErrorEnum, +) +from .resource_count_limit_exceeded_error import ( + ResourceCountLimitExceededErrorEnum, +) +from .search_term_insight_error import ( + SearchTermInsightErrorEnum, +) +from .setting_error import ( + SettingErrorEnum, +) +from .shareable_preview_error import ( + ShareablePreviewErrorEnum, +) +from .shared_criterion_error import ( + SharedCriterionErrorEnum, +) +from .shared_set_error import ( + SharedSetErrorEnum, +) +from .shopping_product_error import ( + ShoppingProductErrorEnum, +) +from .size_limit_error import ( + SizeLimitErrorEnum, +) +from .smart_campaign_error import ( + SmartCampaignErrorEnum, +) +from .string_format_error import ( + StringFormatErrorEnum, +) +from .string_length_error import ( + StringLengthErrorEnum, +) +from .third_party_app_analytics_link_error import ( + ThirdPartyAppAnalyticsLinkErrorEnum, +) +from .time_zone_error import ( + TimeZoneErrorEnum, +) +from .url_field_error import ( + UrlFieldErrorEnum, +) +from .user_data_error import ( + UserDataErrorEnum, +) +from .user_list_customer_type_error import ( + UserListCustomerTypeErrorEnum, +) +from .user_list_error import ( + UserListErrorEnum, +) +from .video_campaign_error import ( + VideoCampaignErrorEnum, +) +from .video_reservation_error import ( + VideoReservationErrorEnum, +) +from .youtube_video_registration_error import ( + YoutubeVideoRegistrationErrorEnum, +) + +__all__ = ( + "AccessInvitationErrorEnum", + "AccountBudgetProposalErrorEnum", + "AccountLinkErrorEnum", + "ActionErrorEnum", + "AdCustomizerErrorEnum", + "AdErrorEnum", + "AdGroupAdErrorEnum", + "AdGroupBidModifierErrorEnum", + "AdGroupCriterionCustomizerErrorEnum", + "AdGroupCriterionErrorEnum", + "AdGroupCustomizerErrorEnum", + "AdGroupErrorEnum", + "AdGroupFeedErrorEnum", + "AdParameterErrorEnum", + "AdSharingErrorEnum", + "AdxErrorEnum", + "AssetErrorEnum", + "AssetGenerationErrorEnum", + "AssetGroupAssetErrorEnum", + "AssetGroupErrorEnum", + "AssetGroupListingGroupFilterErrorEnum", + "AssetGroupSignalErrorEnum", + "AssetLinkErrorEnum", + "AssetSetAssetErrorEnum", + "AssetSetErrorEnum", + "AssetSetLinkErrorEnum", + "AudienceErrorEnum", + "AudienceInsightsErrorEnum", + "AuthenticationErrorEnum", + "AuthorizationErrorEnum", + "AutomaticallyCreatedAssetRemovalErrorEnum", + "BatchJobErrorEnum", + "BenchmarksErrorEnum", + "BiddingErrorEnum", + "BiddingStrategyErrorEnum", + "BillingSetupErrorEnum", + "BrandGuidelinesMigrationErrorEnum", + "CampaignBudgetErrorEnum", + "CampaignConversionGoalErrorEnum", + "CampaignCriterionErrorEnum", + "CampaignCustomizerErrorEnum", + "CampaignDraftErrorEnum", + "CampaignErrorEnum", + "CampaignExperimentErrorEnum", + "CampaignFeedErrorEnum", + "CampaignGoalConfigErrorEnum", + "CampaignLifecycleGoalErrorEnum", + "CampaignSharedSetErrorEnum", + "ChangeEventErrorEnum", + "ChangeStatusErrorEnum", + "ClickViewErrorEnum", + "CollectionSizeErrorEnum", + "ContentCreatorInsightsErrorEnum", + "ContextErrorEnum", + "ConversionActionErrorEnum", + "ConversionAdjustmentUploadErrorEnum", + "ConversionCustomVariableErrorEnum", + "ConversionGoalCampaignConfigErrorEnum", + "ConversionUploadErrorEnum", + "ConversionValueRuleErrorEnum", + "ConversionValueRuleSetErrorEnum", + "CountryCodeErrorEnum", + "CriterionErrorEnum", + "CurrencyCodeErrorEnum", + "CurrencyErrorEnum", + "CustomAudienceErrorEnum", + "CustomConversionGoalErrorEnum", + "CustomInterestErrorEnum", + "CustomerClientLinkErrorEnum", + "CustomerCustomizerErrorEnum", + "CustomerErrorEnum", + "CustomerFeedErrorEnum", + "CustomerLifecycleGoalErrorEnum", + "CustomerManagerLinkErrorEnum", + "CustomerSkAdNetworkConversionValueSchemaErrorEnum", + "CustomerUserAccessErrorEnum", + "CustomizerAttributeErrorEnum", + "DataLinkErrorEnum", + "DatabaseErrorEnum", + "DateErrorEnum", + "DateRangeErrorEnum", + "DistinctErrorEnum", + "EnumErrorEnum", + "BudgetPerDayMinimumErrorDetails", + "ErrorCode", + "ErrorDetails", + "ErrorLocation", + "GoogleAdsError", + "GoogleAdsFailure", + "PolicyFindingDetails", + "PolicyViolationDetails", + "QuotaErrorDetails", + "ReservationErrorDetails", + "ResourceCountDetails", + "ExperimentArmErrorEnum", + "ExperimentErrorEnum", + "ExtensionFeedItemErrorEnum", + "ExtensionSettingErrorEnum", + "FeedAttributeReferenceErrorEnum", + "FeedErrorEnum", + "FeedItemErrorEnum", + "FeedItemSetErrorEnum", + "FeedItemSetLinkErrorEnum", + "FeedItemTargetErrorEnum", + "FeedItemValidationErrorEnum", + "FeedMappingErrorEnum", + "FieldErrorEnum", + "FieldMaskErrorEnum", + "FinalUrlExpansionAssetViewErrorEnum", + "FunctionErrorEnum", + "FunctionParsingErrorEnum", + "GeoTargetConstantSuggestionErrorEnum", + "GoalErrorEnum", + "HeaderErrorEnum", + "IdErrorEnum", + "IdentityVerificationErrorEnum", + "ImageErrorEnum", + "IncentiveErrorEnum", + "InternalErrorEnum", + "InvoiceErrorEnum", + "KeywordPlanAdGroupErrorEnum", + "KeywordPlanAdGroupKeywordErrorEnum", + "KeywordPlanCampaignErrorEnum", + "KeywordPlanCampaignKeywordErrorEnum", + "KeywordPlanErrorEnum", + "KeywordPlanIdeaErrorEnum", + "LabelErrorEnum", + "LanguageCodeErrorEnum", + "ListOperationErrorEnum", + "ManagerLinkErrorEnum", + "MediaBundleErrorEnum", + "MediaFileErrorEnum", + "MediaUploadErrorEnum", + "MerchantCenterErrorEnum", + "MultiplierErrorEnum", + "MutateErrorEnum", + "NewResourceCreationErrorEnum", + "NotAllowlistedErrorEnum", + "NotEmptyErrorEnum", + "NullErrorEnum", + "OfflineUserDataJobErrorEnum", + "OperationAccessDeniedErrorEnum", + "OperatorErrorEnum", + "PartialFailureErrorEnum", + "PaymentsAccountErrorEnum", + "PolicyFindingErrorEnum", + "PolicyValidationParameterErrorEnum", + "PolicyViolationErrorEnum", + "ProductLinkErrorEnum", + "ProductLinkInvitationErrorEnum", + "QueryErrorEnum", + "QuotaErrorEnum", + "RangeErrorEnum", + "ReachPlanErrorEnum", + "RecommendationErrorEnum", + "RecommendationSubscriptionErrorEnum", + "RegionCodeErrorEnum", + "RequestErrorEnum", + "ResourceAccessDeniedErrorEnum", + "ResourceCountLimitExceededErrorEnum", + "SearchTermInsightErrorEnum", + "SettingErrorEnum", + "ShareablePreviewErrorEnum", + "SharedCriterionErrorEnum", + "SharedSetErrorEnum", + "ShoppingProductErrorEnum", + "SizeLimitErrorEnum", + "SmartCampaignErrorEnum", + "StringFormatErrorEnum", + "StringLengthErrorEnum", + "ThirdPartyAppAnalyticsLinkErrorEnum", + "TimeZoneErrorEnum", + "UrlFieldErrorEnum", + "UserDataErrorEnum", + "UserListCustomerTypeErrorEnum", + "UserListErrorEnum", + "VideoCampaignErrorEnum", + "VideoReservationErrorEnum", + "YoutubeVideoRegistrationErrorEnum", +) diff --git a/google/ads/googleads/v24/errors/types/access_invitation_error.py b/google/ads/googleads/v24/errors/types/access_invitation_error.py new file mode 100644 index 000000000..e18f602e7 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/access_invitation_error.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AccessInvitationErrorEnum", + }, +) + + +class AccessInvitationErrorEnum(proto.Message): + r"""Container for enum describing possible AccessInvitation + errors. + + """ + + class AccessInvitationError(proto.Enum): + r"""Enum describing possible AccessInvitation errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_EMAIL_ADDRESS (2): + The email address is invalid for sending an + invitation. + EMAIL_ADDRESS_ALREADY_HAS_ACCESS (3): + Email address already has access to this + customer. + INVALID_INVITATION_STATUS (4): + Invalid invitation status for the operation. + GOOGLE_CONSUMER_ACCOUNT_NOT_ALLOWED (5): + Email address cannot be like + abc+foo@google.com. + INVALID_INVITATION_ID (6): + Invalid invitation ID. + EMAIL_ADDRESS_ALREADY_HAS_PENDING_INVITATION (7): + Email address already has a pending + invitation. + PENDING_INVITATIONS_LIMIT_EXCEEDED (8): + Pending invitation limit exceeded for the + customer. + EMAIL_DOMAIN_POLICY_VIOLATED (9): + Email address doesn't conform to the email + domain policy. See + https://support.google.com/google-ads/answer/2375456 + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_EMAIL_ADDRESS = 2 + EMAIL_ADDRESS_ALREADY_HAS_ACCESS = 3 + INVALID_INVITATION_STATUS = 4 + GOOGLE_CONSUMER_ACCOUNT_NOT_ALLOWED = 5 + INVALID_INVITATION_ID = 6 + EMAIL_ADDRESS_ALREADY_HAS_PENDING_INVITATION = 7 + PENDING_INVITATIONS_LIMIT_EXCEEDED = 8 + EMAIL_DOMAIN_POLICY_VIOLATED = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/account_budget_proposal_error.py b/google/ads/googleads/v24/errors/types/account_budget_proposal_error.py new file mode 100644 index 000000000..b85341117 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/account_budget_proposal_error.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AccountBudgetProposalErrorEnum", + }, +) + + +class AccountBudgetProposalErrorEnum(proto.Message): + r"""Container for enum describing possible account budget + proposal errors. + + """ + + class AccountBudgetProposalError(proto.Enum): + r"""Enum describing possible account budget proposal errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + FIELD_MASK_NOT_ALLOWED (2): + The field mask must be empty for + create/end/remove proposals. + IMMUTABLE_FIELD (3): + The field cannot be set because of the + proposal type. + REQUIRED_FIELD_MISSING (4): + The field is required because of the proposal + type. + CANNOT_CANCEL_APPROVED_PROPOSAL (5): + Proposals that have been approved cannot be + cancelled. + CANNOT_REMOVE_UNAPPROVED_BUDGET (6): + Budgets that haven't been approved cannot be + removed. + CANNOT_REMOVE_RUNNING_BUDGET (7): + Budgets that are currently running cannot be + removed. + CANNOT_END_UNAPPROVED_BUDGET (8): + Budgets that haven't been approved cannot be + truncated. + CANNOT_END_INACTIVE_BUDGET (9): + Only budgets that are currently running can + be truncated. + BUDGET_NAME_REQUIRED (10): + All budgets must have names. + CANNOT_UPDATE_OLD_BUDGET (11): + Expired budgets cannot be edited after a + sufficient amount of time has passed. + CANNOT_END_IN_PAST (12): + It is not permissible a propose a new budget + that ends in the past. + CANNOT_EXTEND_END_TIME (13): + An expired budget cannot be extended to + overlap with the running budget. + PURCHASE_ORDER_NUMBER_REQUIRED (14): + A purchase order number is required. + PENDING_UPDATE_PROPOSAL_EXISTS (15): + Budgets that have a pending update cannot be + updated. + MULTIPLE_BUDGETS_NOT_ALLOWED_FOR_UNAPPROVED_BILLING_SETUP (16): + Cannot propose more than one budget when the + corresponding billing setup hasn't been + approved. + CANNOT_UPDATE_START_TIME_FOR_STARTED_BUDGET (17): + Cannot update the start time of a budget that + has already started. + SPENDING_LIMIT_LOWER_THAN_ACCRUED_COST_NOT_ALLOWED (18): + Cannot update the spending limit of a budget + with an amount lower than what has already been + spent. + UPDATE_IS_NO_OP (19): + Cannot propose a budget update without + actually changing any fields. + END_TIME_MUST_FOLLOW_START_TIME (20): + The end time must come after the start time. + BUDGET_DATE_RANGE_INCOMPATIBLE_WITH_BILLING_SETUP (21): + The budget's date range must fall within the + date range of its billing setup. + NOT_AUTHORIZED (22): + The user is not authorized to mutate budgets + for the given billing setup. + INVALID_BILLING_SETUP (23): + Mutates are not allowed for the given billing + setup. + OVERLAPS_EXISTING_BUDGET (24): + Budget creation failed as it overlaps with a + pending budget proposal or an approved budget. + CANNOT_CREATE_BUDGET_THROUGH_API (25): + The control setting in user's payments + profile doesn't allow budget creation through + API. Log in to Google Ads to create budget. + INVALID_MASTER_SERVICE_AGREEMENT (26): + Master service agreement has not been signed + yet for the Payments Profile. + CANCELED_BILLING_SETUP (27): + Budget mutates are not allowed because the + given billing setup is canceled. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + FIELD_MASK_NOT_ALLOWED = 2 + IMMUTABLE_FIELD = 3 + REQUIRED_FIELD_MISSING = 4 + CANNOT_CANCEL_APPROVED_PROPOSAL = 5 + CANNOT_REMOVE_UNAPPROVED_BUDGET = 6 + CANNOT_REMOVE_RUNNING_BUDGET = 7 + CANNOT_END_UNAPPROVED_BUDGET = 8 + CANNOT_END_INACTIVE_BUDGET = 9 + BUDGET_NAME_REQUIRED = 10 + CANNOT_UPDATE_OLD_BUDGET = 11 + CANNOT_END_IN_PAST = 12 + CANNOT_EXTEND_END_TIME = 13 + PURCHASE_ORDER_NUMBER_REQUIRED = 14 + PENDING_UPDATE_PROPOSAL_EXISTS = 15 + MULTIPLE_BUDGETS_NOT_ALLOWED_FOR_UNAPPROVED_BILLING_SETUP = 16 + CANNOT_UPDATE_START_TIME_FOR_STARTED_BUDGET = 17 + SPENDING_LIMIT_LOWER_THAN_ACCRUED_COST_NOT_ALLOWED = 18 + UPDATE_IS_NO_OP = 19 + END_TIME_MUST_FOLLOW_START_TIME = 20 + BUDGET_DATE_RANGE_INCOMPATIBLE_WITH_BILLING_SETUP = 21 + NOT_AUTHORIZED = 22 + INVALID_BILLING_SETUP = 23 + OVERLAPS_EXISTING_BUDGET = 24 + CANNOT_CREATE_BUDGET_THROUGH_API = 25 + INVALID_MASTER_SERVICE_AGREEMENT = 26 + CANCELED_BILLING_SETUP = 27 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/account_link_error.py b/google/ads/googleads/v24/errors/types/account_link_error.py new file mode 100644 index 000000000..9e557e094 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/account_link_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AccountLinkErrorEnum", + }, +) + + +class AccountLinkErrorEnum(proto.Message): + r"""Container for enum describing possible account link errors.""" + + class AccountLinkError(proto.Enum): + r"""Enum describing possible account link errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_STATUS (2): + The new link status is invalid. + PERMISSION_DENIED (3): + The authenticated user doesn't have the + permission to do the change. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_STATUS = 2 + PERMISSION_DENIED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/action_error.py b/google/ads/googleads/v24/errors/types/action_error.py new file mode 100644 index 000000000..9e36e3bdd --- /dev/null +++ b/google/ads/googleads/v24/errors/types/action_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ActionErrorEnum", + }, +) + + +class ActionErrorEnum(proto.Message): + r"""Container for enum describing possible action errors.""" + + class ActionError(proto.Enum): + r"""Enum describing possible action errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + REQUIRED_FIELD_MISSING (2): + The action is missing a required field. + INVALID_ARGUMENT (3): + The action has invalid arguments in the + request. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + REQUIRED_FIELD_MISSING = 2 + INVALID_ARGUMENT = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/ad_customizer_error.py b/google/ads/googleads/v24/errors/types/ad_customizer_error.py new file mode 100644 index 000000000..707ec4291 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/ad_customizer_error.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AdCustomizerErrorEnum", + }, +) + + +class AdCustomizerErrorEnum(proto.Message): + r"""Container for enum describing possible ad customizer errors.""" + + class AdCustomizerError(proto.Enum): + r"""Enum describing possible ad customizer errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + COUNTDOWN_INVALID_DATE_FORMAT (2): + Invalid date argument in countdown function. + COUNTDOWN_DATE_IN_PAST (3): + Countdown end date is in the past. + COUNTDOWN_INVALID_LOCALE (4): + Invalid locale string in countdown function. + COUNTDOWN_INVALID_START_DAYS_BEFORE (5): + Days-before argument to countdown function is + not positive. + UNKNOWN_USER_LIST (6): + A user list referenced in an IF function does + not exist. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + COUNTDOWN_INVALID_DATE_FORMAT = 2 + COUNTDOWN_DATE_IN_PAST = 3 + COUNTDOWN_INVALID_LOCALE = 4 + COUNTDOWN_INVALID_START_DAYS_BEFORE = 5 + UNKNOWN_USER_LIST = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/ad_error.py b/google/ads/googleads/v24/errors/types/ad_error.py new file mode 100644 index 000000000..fd65abdde --- /dev/null +++ b/google/ads/googleads/v24/errors/types/ad_error.py @@ -0,0 +1,612 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AdErrorEnum", + }, +) + + +class AdErrorEnum(proto.Message): + r"""Container for enum describing possible ad errors.""" + + class AdError(proto.Enum): + r"""Enum describing possible ad errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + AD_CUSTOMIZERS_NOT_SUPPORTED_FOR_AD_TYPE (2): + Ad customizers are not supported for ad type. + APPROXIMATELY_TOO_LONG (3): + Estimating character sizes the string is too + long. + APPROXIMATELY_TOO_SHORT (4): + Estimating character sizes the string is too + short. + BAD_SNIPPET (5): + There is a problem with the snippet. + CANNOT_MODIFY_AD (6): + Cannot modify an ad. + CANNOT_SET_BUSINESS_NAME_IF_URL_SET (7): + business name and url cannot be set at the + same time + CANNOT_SET_FIELD (8): + The specified field is incompatible with this + ad's type or settings. + CANNOT_SET_FIELD_WITH_ORIGIN_AD_ID_SET (9): + Cannot set field when originAdId is set. + CANNOT_SET_FIELD_WITH_AD_ID_SET_FOR_SHARING (10): + Cannot set field when an existing ad id is + set for sharing. + CANNOT_SET_ALLOW_FLEXIBLE_COLOR_FALSE (11): + Cannot set allowFlexibleColor false if no + color is provided by user. + CANNOT_SET_COLOR_CONTROL_WHEN_NATIVE_FORMAT_SETTING (12): + When user select native, no color control is + allowed because we will always respect publisher + color for native format serving. + CANNOT_SET_URL (13): + Cannot specify a url for the ad type + CANNOT_SET_WITHOUT_FINAL_URLS (14): + Cannot specify a tracking or mobile url + without also setting final urls + CANNOT_SET_WITH_FINAL_URLS (15): + Cannot specify a legacy url and a final url + simultaneously + CANNOT_SET_WITH_URL_DATA (17): + Cannot specify a urls in UrlData and in + template fields simultaneously. + CANNOT_USE_AD_SUBCLASS_FOR_OPERATOR (18): + This operator cannot be used with a subclass + of Ad. + CUSTOMER_NOT_APPROVED_MOBILEADS (19): + Customer is not approved for mobile ads. + CUSTOMER_NOT_APPROVED_THIRDPARTY_ADS (20): + Customer is not approved for 3PAS richmedia + ads. + CUSTOMER_NOT_APPROVED_THIRDPARTY_REDIRECT_ADS (21): + Customer is not approved for 3PAS redirect + richmedia (Ad Exchange) ads. + CUSTOMER_NOT_ELIGIBLE (22): + Not an eligible customer + CUSTOMER_NOT_ELIGIBLE_FOR_UPDATING_BEACON_URL (23): + Customer is not eligible for updating beacon + url + DIMENSION_ALREADY_IN_UNION (24): + There already exists an ad with the same + dimensions in the union. + DIMENSION_MUST_BE_SET (25): + Ad's dimension must be set before setting + union dimension. + DIMENSION_NOT_IN_UNION (26): + Ad's dimension must be included in the union + dimensions. + DISPLAY_URL_CANNOT_BE_SPECIFIED (27): + Display Url cannot be specified (applies to + Ad Exchange Ads) + DOMESTIC_PHONE_NUMBER_FORMAT (28): + Telephone number contains invalid characters + or invalid format. Re-enter your number using + digits (0-9), dashes (-), and parentheses only. + EMERGENCY_PHONE_NUMBER (29): + Emergency telephone numbers are not allowed. + Enter a valid domestic phone number to connect + customers to your business. + EMPTY_FIELD (30): + A required field was not specified or is an + empty string. + FEED_ATTRIBUTE_MUST_HAVE_MAPPING_FOR_TYPE_ID (31): + A feed attribute referenced in an ad + customizer tag is not in the ad customizer + mapping for the feed. + FEED_ATTRIBUTE_MAPPING_TYPE_MISMATCH (32): + The ad customizer field mapping for the feed + attribute does not match the expected field + type. + ILLEGAL_AD_CUSTOMIZER_TAG_USE (33): + The use of ad customizer tags in the ad text + is disallowed. Details in trigger. + ILLEGAL_TAG_USE (34): + Tags of the form {PH_x}, where x is a number, are disallowed + in ad text. + INCONSISTENT_DIMENSIONS (35): + The dimensions of the ad are specified or + derived in multiple ways and are not consistent. + INCONSISTENT_STATUS_IN_TEMPLATE_UNION (36): + The status cannot differ among template ads + of the same union. + INCORRECT_LENGTH (37): + The length of the string is not valid. + INELIGIBLE_FOR_UPGRADE (38): + The ad is ineligible for upgrade. + INVALID_AD_ADDRESS_CAMPAIGN_TARGET (39): + User cannot create mobile ad for countries + targeted in specified campaign. + INVALID_AD_TYPE (40): + Invalid Ad type. A specific type of Ad is + required. + INVALID_ATTRIBUTES_FOR_MOBILE_IMAGE (41): + Headline, description or phone cannot be + present when creating mobile image ad. + INVALID_ATTRIBUTES_FOR_MOBILE_TEXT (42): + Image cannot be present when creating mobile + text ad. + INVALID_CALL_TO_ACTION_TEXT (43): + Invalid call to action text. + INVALID_CHARACTER_FOR_URL (44): + Invalid character in URL. + INVALID_COUNTRY_CODE (45): + Creative's country code is not valid. + INVALID_EXPANDED_DYNAMIC_SEARCH_AD_TAG (47): + Invalid use of Expanded Dynamic Search Ads + tags ({lpurl} etc.) + INVALID_INPUT (48): + An input error whose real reason was not + properly mapped (should not happen). + INVALID_MARKUP_LANGUAGE (49): + An invalid markup language was entered. + INVALID_MOBILE_CARRIER (50): + An invalid mobile carrier was entered. + INVALID_MOBILE_CARRIER_TARGET (51): + Specified mobile carriers target a country + not targeted by the campaign. + INVALID_NUMBER_OF_ELEMENTS (52): + Wrong number of elements for given element + type + INVALID_PHONE_NUMBER_FORMAT (53): + The format of the telephone number is + incorrect. Re-enter the number using the correct + format. + INVALID_RICH_MEDIA_CERTIFIED_VENDOR_FORMAT_ID (54): + The certified vendor format id is incorrect. + INVALID_TEMPLATE_DATA (55): + The template ad data contains validation + errors. + INVALID_TEMPLATE_ELEMENT_FIELD_TYPE (56): + The template field doesn't have have the + correct type. + INVALID_TEMPLATE_ID (57): + Invalid template id. + LINE_TOO_WIDE (58): + After substituting replacement strings, the + line is too wide. + MISSING_AD_CUSTOMIZER_MAPPING (59): + The feed referenced must have ad customizer + mapping to be used in a customizer tag. + MISSING_ADDRESS_COMPONENT (60): + Missing address component in template element + address field. + MISSING_ADVERTISEMENT_NAME (61): + An ad name must be entered. + MISSING_BUSINESS_NAME (62): + Business name must be entered. + MISSING_DESCRIPTION1 (63): + Description (line 2) must be entered. + MISSING_DESCRIPTION2 (64): + Description (line 3) must be entered. + MISSING_DESTINATION_URL_TAG (65): + The destination url must contain at least one + tag (for example, {lpurl}) + MISSING_LANDING_PAGE_URL_TAG (66): + The tracking url template of + ExpandedDynamicSearchAd must contain at least + one tag. (for example, {lpurl}) + MISSING_DIMENSION (67): + A valid dimension must be specified for this + ad. + MISSING_DISPLAY_URL (68): + A display URL must be entered. + MISSING_HEADLINE (69): + Headline must be entered. + MISSING_HEIGHT (70): + A height must be entered. + MISSING_IMAGE (71): + An image must be entered. + MISSING_MARKETING_IMAGE_OR_PRODUCT_VIDEOS (72): + Marketing image or product videos are + required. + MISSING_MARKUP_LANGUAGES (73): + The markup language in which your site is + written must be entered. + MISSING_MOBILE_CARRIER (74): + A mobile carrier must be entered. + MISSING_PHONE (75): + Phone number must be entered. + MISSING_REQUIRED_TEMPLATE_FIELDS (76): + Missing required template fields + MISSING_TEMPLATE_FIELD_VALUE (77): + Missing a required field value + MISSING_TEXT (78): + The ad must have text. + MISSING_VISIBLE_URL (79): + A visible URL must be entered. + MISSING_WIDTH (80): + A width must be entered. + MULTIPLE_DISTINCT_FEEDS_UNSUPPORTED (81): + Only 1 feed can be used as the source of ad + customizer substitutions in a single ad. + MUST_USE_TEMP_AD_UNION_ID_ON_ADD (82): + TempAdUnionId must be use when adding + template ads. + TOO_LONG (83): + The string has too many characters. + TOO_SHORT (84): + The string has too few characters. + UNION_DIMENSIONS_CANNOT_CHANGE (85): + Ad union dimensions cannot change for saved + ads. + UNKNOWN_ADDRESS_COMPONENT (86): + Address component is not {country, lat, lng}. + UNKNOWN_FIELD_NAME (87): + Unknown unique field name + UNKNOWN_UNIQUE_NAME (88): + Unknown unique name (template element type + specifier) + UNSUPPORTED_DIMENSIONS (89): + Unsupported ad dimension + URL_INVALID_SCHEME (90): + URL starts with an invalid scheme. + URL_INVALID_TOP_LEVEL_DOMAIN (91): + URL ends with an invalid top-level domain + name. + URL_MALFORMED (92): + URL contains illegal characters. + URL_NO_HOST (93): + URL must contain a host name. + URL_NOT_EQUIVALENT (94): + URL not equivalent during upgrade. + URL_HOST_NAME_TOO_LONG (95): + URL host name too long to be stored as + visible URL (applies to Ad Exchange ads) + URL_NO_SCHEME (96): + URL must start with a scheme. + URL_NO_TOP_LEVEL_DOMAIN (97): + URL should end in a valid domain extension, + such as .com or .net. + URL_PATH_NOT_ALLOWED (98): + URL must not end with a path. + URL_PORT_NOT_ALLOWED (99): + URL must not specify a port. + URL_QUERY_NOT_ALLOWED (100): + URL must not contain a query. + URL_SCHEME_BEFORE_EXPANDED_DYNAMIC_SEARCH_AD_TAG (102): + A url scheme is not allowed in front of tag + in tracking url template (for example, + http://{lpurl}) + USER_DOES_NOT_HAVE_ACCESS_TO_TEMPLATE (103): + The user does not have permissions to create + a template ad for the given template. + INCONSISTENT_EXPANDABLE_SETTINGS (104): + Expandable setting is inconsistent/wrong. For + example, an AdX ad is invalid if it has a + expandable vendor format but no expanding + directions specified, or expanding directions is + specified, but the vendor format is not + expandable. + INVALID_FORMAT (105): + Format is invalid + INVALID_FIELD_TEXT (106): + The text of this field did not match a + pattern of allowed values. + ELEMENT_NOT_PRESENT (107): + Template element is mising + IMAGE_ERROR (108): + Error occurred during image processing + VALUE_NOT_IN_RANGE (109): + The value is not within the valid range + FIELD_NOT_PRESENT (110): + Template element field is not present + ADDRESS_NOT_COMPLETE (111): + Address is incomplete + ADDRESS_INVALID (112): + Invalid address + VIDEO_RETRIEVAL_ERROR (113): + Error retrieving specified video + AUDIO_ERROR (114): + Error processing audio + INVALID_YOUTUBE_DISPLAY_URL (115): + Display URL is incorrect for YouTube PYV ads + TOO_MANY_PRODUCT_IMAGES (116): + Too many product Images in GmailAd + TOO_MANY_PRODUCT_VIDEOS (117): + Too many product Videos in GmailAd + INCOMPATIBLE_AD_TYPE_AND_DEVICE_PREFERENCE (118): + The device preference is not compatible with + the ad type + CALLTRACKING_NOT_SUPPORTED_FOR_COUNTRY (119): + Call tracking is not supported for specified + country. + CARRIER_SPECIFIC_SHORT_NUMBER_NOT_ALLOWED (120): + Carrier specific short number is not allowed. + DISALLOWED_NUMBER_TYPE (121): + Specified phone number type is disallowed. + PHONE_NUMBER_NOT_SUPPORTED_FOR_COUNTRY (122): + Phone number not supported for country. + PHONE_NUMBER_NOT_SUPPORTED_WITH_CALLTRACKING_FOR_COUNTRY (123): + Phone number not supported with call tracking + enabled for country. + PREMIUM_RATE_NUMBER_NOT_ALLOWED (124): + Premium rate phone number is not allowed. + VANITY_PHONE_NUMBER_NOT_ALLOWED (125): + Vanity phone number is not allowed. + INVALID_CALL_CONVERSION_TYPE_ID (126): + Invalid call conversion type id. + CANNOT_DISABLE_CALL_CONVERSION_AND_SET_CONVERSION_TYPE_ID (127): + Cannot disable call conversion and set + conversion type id. + CANNOT_SET_PATH2_WITHOUT_PATH1 (128): + Cannot set path2 without path1. + MISSING_DYNAMIC_SEARCH_ADS_SETTING_DOMAIN_NAME (129): + Missing domain name in campaign setting when + adding expanded dynamic search ad. + INCOMPATIBLE_WITH_RESTRICTION_TYPE (130): + The associated ad is not compatible with + restriction type. + CUSTOMER_CONSENT_FOR_CALL_RECORDING_REQUIRED (131): + Consent for call recording is required for + creating/updating call only ads. See + https://support.google.com/google-ads/answer/7412639. + MISSING_IMAGE_OR_MEDIA_BUNDLE (132): + Either an image or a media bundle is required + in a display upload ad. + PRODUCT_TYPE_NOT_SUPPORTED_IN_THIS_CAMPAIGN (133): + The display upload product type is not + supported in this campaign. + PLACEHOLDER_CANNOT_HAVE_EMPTY_DEFAULT_VALUE (134): + The default value of an ad placeholder can + not be the empty string. + PLACEHOLDER_COUNTDOWN_FUNCTION_CANNOT_HAVE_DEFAULT_VALUE (135): + Ad placeholders with countdown functions must + not have a default value. + PLACEHOLDER_DEFAULT_VALUE_MISSING (136): + A previous ad placeholder that had a default + value was found which means that all + (non-countdown) placeholders must have a default + value. This ad placeholder does not have a + default value. + UNEXPECTED_PLACEHOLDER_DEFAULT_VALUE (137): + A previous ad placeholder that did not have a + default value was found which means that no + placeholders may have a default value. This ad + placeholder does have a default value. + AD_CUSTOMIZERS_MAY_NOT_BE_ADJACENT (138): + Two ad customizers may not be directly + adjacent in an ad text. They must be separated + by at least one character. + UPDATING_AD_WITH_NO_ENABLED_ASSOCIATION (139): + The ad is not associated with any enabled + AdGroupAd, and cannot be updated. + CALL_AD_VERIFICATION_URL_FINAL_URL_DOES_NOT_HAVE_SAME_DOMAIN (140): + Call Ad verification url and final url don't + have same domain. + CALL_AD_FINAL_URL_AND_VERIFICATION_URL_CANNOT_BOTH_BE_EMPTY (154): + Final url and verification url cannot both be + empty for call ads. + TOO_MANY_AD_CUSTOMIZERS (141): + Too many ad customizers in one asset. + INVALID_AD_CUSTOMIZER_FORMAT (142): + The ad customizer tag is recognized, but the + format is invalid. + NESTED_AD_CUSTOMIZER_SYNTAX (143): + Customizer tags cannot be nested. + UNSUPPORTED_AD_CUSTOMIZER_SYNTAX (144): + The ad customizer syntax used in the ad is + not supported. + UNPAIRED_BRACE_IN_AD_CUSTOMIZER_TAG (145): + There exists unpaired brace in the ad + customizer tag. + MORE_THAN_ONE_COUNTDOWN_TAG_TYPE_EXISTS (146): + More than one type of countdown tag exists + among all text lines. + DATE_TIME_IN_COUNTDOWN_TAG_IS_INVALID (147): + Date time in the countdown tag is invalid. + DATE_TIME_IN_COUNTDOWN_TAG_IS_PAST (148): + Date time in the countdown tag is in the + past. + UNRECOGNIZED_AD_CUSTOMIZER_TAG_FOUND (149): + Cannot recognize the ad customizer tag. + CUSTOMIZER_TYPE_FORBIDDEN_FOR_FIELD (150): + Customizer type forbidden for this field. + INVALID_CUSTOMIZER_ATTRIBUTE_NAME (151): + Customizer attribute name is invalid. + STORE_MISMATCH (152): + App store value does not match the value of + the app store in the app specified in the + campaign. + MISSING_REQUIRED_IMAGE_ASPECT_RATIO (153): + Missing required image aspect ratio. + MISMATCHED_ASPECT_RATIOS (155): + Aspect ratios mismatch between different + assets. + DUPLICATE_IMAGE_ACROSS_CAROUSEL_CARDS (156): + Images must be unique between different + carousel card assets. + INVALID_YOUTUBE_VIDEO_ASSET_ID_FOR_VIDEO_ADS_SEQUENCING (157): + For video ads sequencing, YouTube video asset ID has to be + defined in + ``campaign.video_campaign_settings.video_ad_sequence.steps.asset_id``. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AD_CUSTOMIZERS_NOT_SUPPORTED_FOR_AD_TYPE = 2 + APPROXIMATELY_TOO_LONG = 3 + APPROXIMATELY_TOO_SHORT = 4 + BAD_SNIPPET = 5 + CANNOT_MODIFY_AD = 6 + CANNOT_SET_BUSINESS_NAME_IF_URL_SET = 7 + CANNOT_SET_FIELD = 8 + CANNOT_SET_FIELD_WITH_ORIGIN_AD_ID_SET = 9 + CANNOT_SET_FIELD_WITH_AD_ID_SET_FOR_SHARING = 10 + CANNOT_SET_ALLOW_FLEXIBLE_COLOR_FALSE = 11 + CANNOT_SET_COLOR_CONTROL_WHEN_NATIVE_FORMAT_SETTING = 12 + CANNOT_SET_URL = 13 + CANNOT_SET_WITHOUT_FINAL_URLS = 14 + CANNOT_SET_WITH_FINAL_URLS = 15 + CANNOT_SET_WITH_URL_DATA = 17 + CANNOT_USE_AD_SUBCLASS_FOR_OPERATOR = 18 + CUSTOMER_NOT_APPROVED_MOBILEADS = 19 + CUSTOMER_NOT_APPROVED_THIRDPARTY_ADS = 20 + CUSTOMER_NOT_APPROVED_THIRDPARTY_REDIRECT_ADS = 21 + CUSTOMER_NOT_ELIGIBLE = 22 + CUSTOMER_NOT_ELIGIBLE_FOR_UPDATING_BEACON_URL = 23 + DIMENSION_ALREADY_IN_UNION = 24 + DIMENSION_MUST_BE_SET = 25 + DIMENSION_NOT_IN_UNION = 26 + DISPLAY_URL_CANNOT_BE_SPECIFIED = 27 + DOMESTIC_PHONE_NUMBER_FORMAT = 28 + EMERGENCY_PHONE_NUMBER = 29 + EMPTY_FIELD = 30 + FEED_ATTRIBUTE_MUST_HAVE_MAPPING_FOR_TYPE_ID = 31 + FEED_ATTRIBUTE_MAPPING_TYPE_MISMATCH = 32 + ILLEGAL_AD_CUSTOMIZER_TAG_USE = 33 + ILLEGAL_TAG_USE = 34 + INCONSISTENT_DIMENSIONS = 35 + INCONSISTENT_STATUS_IN_TEMPLATE_UNION = 36 + INCORRECT_LENGTH = 37 + INELIGIBLE_FOR_UPGRADE = 38 + INVALID_AD_ADDRESS_CAMPAIGN_TARGET = 39 + INVALID_AD_TYPE = 40 + INVALID_ATTRIBUTES_FOR_MOBILE_IMAGE = 41 + INVALID_ATTRIBUTES_FOR_MOBILE_TEXT = 42 + INVALID_CALL_TO_ACTION_TEXT = 43 + INVALID_CHARACTER_FOR_URL = 44 + INVALID_COUNTRY_CODE = 45 + INVALID_EXPANDED_DYNAMIC_SEARCH_AD_TAG = 47 + INVALID_INPUT = 48 + INVALID_MARKUP_LANGUAGE = 49 + INVALID_MOBILE_CARRIER = 50 + INVALID_MOBILE_CARRIER_TARGET = 51 + INVALID_NUMBER_OF_ELEMENTS = 52 + INVALID_PHONE_NUMBER_FORMAT = 53 + INVALID_RICH_MEDIA_CERTIFIED_VENDOR_FORMAT_ID = 54 + INVALID_TEMPLATE_DATA = 55 + INVALID_TEMPLATE_ELEMENT_FIELD_TYPE = 56 + INVALID_TEMPLATE_ID = 57 + LINE_TOO_WIDE = 58 + MISSING_AD_CUSTOMIZER_MAPPING = 59 + MISSING_ADDRESS_COMPONENT = 60 + MISSING_ADVERTISEMENT_NAME = 61 + MISSING_BUSINESS_NAME = 62 + MISSING_DESCRIPTION1 = 63 + MISSING_DESCRIPTION2 = 64 + MISSING_DESTINATION_URL_TAG = 65 + MISSING_LANDING_PAGE_URL_TAG = 66 + MISSING_DIMENSION = 67 + MISSING_DISPLAY_URL = 68 + MISSING_HEADLINE = 69 + MISSING_HEIGHT = 70 + MISSING_IMAGE = 71 + MISSING_MARKETING_IMAGE_OR_PRODUCT_VIDEOS = 72 + MISSING_MARKUP_LANGUAGES = 73 + MISSING_MOBILE_CARRIER = 74 + MISSING_PHONE = 75 + MISSING_REQUIRED_TEMPLATE_FIELDS = 76 + MISSING_TEMPLATE_FIELD_VALUE = 77 + MISSING_TEXT = 78 + MISSING_VISIBLE_URL = 79 + MISSING_WIDTH = 80 + MULTIPLE_DISTINCT_FEEDS_UNSUPPORTED = 81 + MUST_USE_TEMP_AD_UNION_ID_ON_ADD = 82 + TOO_LONG = 83 + TOO_SHORT = 84 + UNION_DIMENSIONS_CANNOT_CHANGE = 85 + UNKNOWN_ADDRESS_COMPONENT = 86 + UNKNOWN_FIELD_NAME = 87 + UNKNOWN_UNIQUE_NAME = 88 + UNSUPPORTED_DIMENSIONS = 89 + URL_INVALID_SCHEME = 90 + URL_INVALID_TOP_LEVEL_DOMAIN = 91 + URL_MALFORMED = 92 + URL_NO_HOST = 93 + URL_NOT_EQUIVALENT = 94 + URL_HOST_NAME_TOO_LONG = 95 + URL_NO_SCHEME = 96 + URL_NO_TOP_LEVEL_DOMAIN = 97 + URL_PATH_NOT_ALLOWED = 98 + URL_PORT_NOT_ALLOWED = 99 + URL_QUERY_NOT_ALLOWED = 100 + URL_SCHEME_BEFORE_EXPANDED_DYNAMIC_SEARCH_AD_TAG = 102 + USER_DOES_NOT_HAVE_ACCESS_TO_TEMPLATE = 103 + INCONSISTENT_EXPANDABLE_SETTINGS = 104 + INVALID_FORMAT = 105 + INVALID_FIELD_TEXT = 106 + ELEMENT_NOT_PRESENT = 107 + IMAGE_ERROR = 108 + VALUE_NOT_IN_RANGE = 109 + FIELD_NOT_PRESENT = 110 + ADDRESS_NOT_COMPLETE = 111 + ADDRESS_INVALID = 112 + VIDEO_RETRIEVAL_ERROR = 113 + AUDIO_ERROR = 114 + INVALID_YOUTUBE_DISPLAY_URL = 115 + TOO_MANY_PRODUCT_IMAGES = 116 + TOO_MANY_PRODUCT_VIDEOS = 117 + INCOMPATIBLE_AD_TYPE_AND_DEVICE_PREFERENCE = 118 + CALLTRACKING_NOT_SUPPORTED_FOR_COUNTRY = 119 + CARRIER_SPECIFIC_SHORT_NUMBER_NOT_ALLOWED = 120 + DISALLOWED_NUMBER_TYPE = 121 + PHONE_NUMBER_NOT_SUPPORTED_FOR_COUNTRY = 122 + PHONE_NUMBER_NOT_SUPPORTED_WITH_CALLTRACKING_FOR_COUNTRY = 123 + PREMIUM_RATE_NUMBER_NOT_ALLOWED = 124 + VANITY_PHONE_NUMBER_NOT_ALLOWED = 125 + INVALID_CALL_CONVERSION_TYPE_ID = 126 + CANNOT_DISABLE_CALL_CONVERSION_AND_SET_CONVERSION_TYPE_ID = 127 + CANNOT_SET_PATH2_WITHOUT_PATH1 = 128 + MISSING_DYNAMIC_SEARCH_ADS_SETTING_DOMAIN_NAME = 129 + INCOMPATIBLE_WITH_RESTRICTION_TYPE = 130 + CUSTOMER_CONSENT_FOR_CALL_RECORDING_REQUIRED = 131 + MISSING_IMAGE_OR_MEDIA_BUNDLE = 132 + PRODUCT_TYPE_NOT_SUPPORTED_IN_THIS_CAMPAIGN = 133 + PLACEHOLDER_CANNOT_HAVE_EMPTY_DEFAULT_VALUE = 134 + PLACEHOLDER_COUNTDOWN_FUNCTION_CANNOT_HAVE_DEFAULT_VALUE = 135 + PLACEHOLDER_DEFAULT_VALUE_MISSING = 136 + UNEXPECTED_PLACEHOLDER_DEFAULT_VALUE = 137 + AD_CUSTOMIZERS_MAY_NOT_BE_ADJACENT = 138 + UPDATING_AD_WITH_NO_ENABLED_ASSOCIATION = 139 + CALL_AD_VERIFICATION_URL_FINAL_URL_DOES_NOT_HAVE_SAME_DOMAIN = 140 + CALL_AD_FINAL_URL_AND_VERIFICATION_URL_CANNOT_BOTH_BE_EMPTY = 154 + TOO_MANY_AD_CUSTOMIZERS = 141 + INVALID_AD_CUSTOMIZER_FORMAT = 142 + NESTED_AD_CUSTOMIZER_SYNTAX = 143 + UNSUPPORTED_AD_CUSTOMIZER_SYNTAX = 144 + UNPAIRED_BRACE_IN_AD_CUSTOMIZER_TAG = 145 + MORE_THAN_ONE_COUNTDOWN_TAG_TYPE_EXISTS = 146 + DATE_TIME_IN_COUNTDOWN_TAG_IS_INVALID = 147 + DATE_TIME_IN_COUNTDOWN_TAG_IS_PAST = 148 + UNRECOGNIZED_AD_CUSTOMIZER_TAG_FOUND = 149 + CUSTOMIZER_TYPE_FORBIDDEN_FOR_FIELD = 150 + INVALID_CUSTOMIZER_ATTRIBUTE_NAME = 151 + STORE_MISMATCH = 152 + MISSING_REQUIRED_IMAGE_ASPECT_RATIO = 153 + MISMATCHED_ASPECT_RATIOS = 155 + DUPLICATE_IMAGE_ACROSS_CAROUSEL_CARDS = 156 + INVALID_YOUTUBE_VIDEO_ASSET_ID_FOR_VIDEO_ADS_SEQUENCING = 157 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/ad_group_ad_error.py b/google/ads/googleads/v24/errors/types/ad_group_ad_error.py new file mode 100644 index 000000000..04d7291e1 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/ad_group_ad_error.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupAdErrorEnum", + }, +) + + +class AdGroupAdErrorEnum(proto.Message): + r"""Container for enum describing possible ad group ad errors.""" + + class AdGroupAdError(proto.Enum): + r"""Enum describing possible ad group ad errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + AD_GROUP_AD_LABEL_DOES_NOT_EXIST (2): + No link found between the adgroup ad and the + label. + AD_GROUP_AD_LABEL_ALREADY_EXISTS (3): + The label has already been attached to the + adgroup ad. + AD_NOT_UNDER_ADGROUP (4): + The specified ad was not found in the adgroup + CANNOT_OPERATE_ON_REMOVED_ADGROUPAD (5): + Removed ads may not be modified + CANNOT_CREATE_DEPRECATED_ADS (6): + An ad of this type is deprecated and cannot + be created. Only deletions are permitted. + CANNOT_CREATE_TEXT_ADS (7): + Text ads are deprecated and cannot be + created. Use expanded text ads instead. + EMPTY_FIELD (8): + A required field was not specified or is an + empty string. + RESOURCE_REFERENCED_IN_MULTIPLE_OPS (9): + An ad may only be modified once per call + AD_TYPE_CANNOT_BE_PAUSED (10): + AdGroupAds with the given ad type cannot be + paused. + AD_TYPE_CANNOT_BE_REMOVED (11): + AdGroupAds with the given ad type cannot be + removed. + CANNOT_UPDATE_DEPRECATED_ADS (12): + An ad of this type is deprecated and cannot + be updated. Only removals are permitted. + AD_SHARING_NOT_ALLOWED (13): + Ad sharing is not allowed. + DURATION_TOO_SHORT (14): + The duration of the AdGroupAd is too short. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AD_GROUP_AD_LABEL_DOES_NOT_EXIST = 2 + AD_GROUP_AD_LABEL_ALREADY_EXISTS = 3 + AD_NOT_UNDER_ADGROUP = 4 + CANNOT_OPERATE_ON_REMOVED_ADGROUPAD = 5 + CANNOT_CREATE_DEPRECATED_ADS = 6 + CANNOT_CREATE_TEXT_ADS = 7 + EMPTY_FIELD = 8 + RESOURCE_REFERENCED_IN_MULTIPLE_OPS = 9 + AD_TYPE_CANNOT_BE_PAUSED = 10 + AD_TYPE_CANNOT_BE_REMOVED = 11 + CANNOT_UPDATE_DEPRECATED_ADS = 12 + AD_SHARING_NOT_ALLOWED = 13 + DURATION_TOO_SHORT = 14 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/ad_group_bid_modifier_error.py b/google/ads/googleads/v24/errors/types/ad_group_bid_modifier_error.py new file mode 100644 index 000000000..e865a5c76 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/ad_group_bid_modifier_error.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupBidModifierErrorEnum", + }, +) + + +class AdGroupBidModifierErrorEnum(proto.Message): + r"""Container for enum describing possible ad group bid modifier + errors. + + """ + + class AdGroupBidModifierError(proto.Enum): + r"""Enum describing possible ad group bid modifier errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CRITERION_ID_NOT_SUPPORTED (2): + The criterion ID does not support bid + modification. + CANNOT_OVERRIDE_OPTED_OUT_CAMPAIGN_CRITERION_BID_MODIFIER (3): + Cannot override the bid modifier for the + given criterion ID if the parent campaign is + opted out of the same criterion. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CRITERION_ID_NOT_SUPPORTED = 2 + CANNOT_OVERRIDE_OPTED_OUT_CAMPAIGN_CRITERION_BID_MODIFIER = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/ad_group_criterion_customizer_error.py b/google/ads/googleads/v24/errors/types/ad_group_criterion_customizer_error.py new file mode 100644 index 000000000..1999140cb --- /dev/null +++ b/google/ads/googleads/v24/errors/types/ad_group_criterion_customizer_error.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupCriterionCustomizerErrorEnum", + }, +) + + +class AdGroupCriterionCustomizerErrorEnum(proto.Message): + r"""Container for enum describing possible ad group criterion + customizer errors. + + """ + + class AdGroupCriterionCustomizerError(proto.Enum): + r"""Enum describing possible ad group criterion customizer + errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CRITERION_IS_NOT_KEYWORD (2): + Only keyword type criterion is allowed to + link customizer attribute. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CRITERION_IS_NOT_KEYWORD = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/ad_group_criterion_error.py b/google/ads/googleads/v24/errors/types/ad_group_criterion_error.py new file mode 100644 index 000000000..c7956fa8a --- /dev/null +++ b/google/ads/googleads/v24/errors/types/ad_group_criterion_error.py @@ -0,0 +1,166 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupCriterionErrorEnum", + }, +) + + +class AdGroupCriterionErrorEnum(proto.Message): + r"""Container for enum describing possible ad group criterion + errors. + + """ + + class AdGroupCriterionError(proto.Enum): + r"""Enum describing possible ad group criterion errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + AD_GROUP_CRITERION_LABEL_DOES_NOT_EXIST (2): + No link found between the AdGroupCriterion + and the label. + AD_GROUP_CRITERION_LABEL_ALREADY_EXISTS (3): + The label has already been attached to the + AdGroupCriterion. + CANNOT_ADD_LABEL_TO_NEGATIVE_CRITERION (4): + Negative AdGroupCriterion cannot have labels. + TOO_MANY_OPERATIONS (5): + Too many operations for a single call. + CANT_UPDATE_NEGATIVE (6): + Negative ad group criteria are not + updateable. + CONCRETE_TYPE_REQUIRED (7): + Concrete type of criterion (keyword v.s. + placement) is required for ADD and SET + operations. + BID_INCOMPATIBLE_WITH_ADGROUP (8): + Bid is incompatible with ad group's bidding + settings. + CANNOT_TARGET_AND_EXCLUDE (9): + Cannot target and exclude the same criterion + at once. + ILLEGAL_URL (10): + The URL of a placement is invalid. + INVALID_KEYWORD_TEXT (11): + Keyword text was invalid. + INVALID_DESTINATION_URL (12): + Destination URL was invalid. + MISSING_DESTINATION_URL_TAG (13): + The destination url must contain at least one + tag (for example, {lpurl}) + KEYWORD_LEVEL_BID_NOT_SUPPORTED_FOR_MANUALCPM (14): + Keyword-level cpm bid is not supported + INVALID_USER_STATUS (15): + For example, cannot add a biddable ad group + criterion that had been removed. + CANNOT_ADD_CRITERIA_TYPE (16): + Criteria type cannot be targeted for the ad + group. Either the account is restricted to + keywords only, the criteria type is incompatible + with the campaign's bidding strategy, or the + criteria type can only be applied to campaigns. + CANNOT_EXCLUDE_CRITERIA_TYPE (17): + Criteria type cannot be excluded for the ad + group. Refer to the documentation for a specific + criterion to check if it is excludable. + CAMPAIGN_TYPE_NOT_COMPATIBLE_WITH_PARTIAL_FAILURE (27): + Partial failure is not supported for shopping + campaign mutate operations. + OPERATIONS_FOR_TOO_MANY_SHOPPING_ADGROUPS (28): + Operations in the mutate request changes too + many shopping ad groups. Split requests for + multiple shopping ad groups across multiple + requests. + CANNOT_MODIFY_URL_FIELDS_WITH_DUPLICATE_ELEMENTS (29): + Not allowed to modify url fields of an ad + group criterion if there are duplicate elements + for that ad group criterion in the request. + CANNOT_SET_WITHOUT_FINAL_URLS (30): + Cannot set url fields without also setting + final urls. + CANNOT_CLEAR_FINAL_URLS_IF_FINAL_MOBILE_URLS_EXIST (31): + Cannot clear final urls if final mobile urls + exist. + CANNOT_CLEAR_FINAL_URLS_IF_FINAL_APP_URLS_EXIST (32): + Cannot clear final urls if final app urls + exist. + CANNOT_CLEAR_FINAL_URLS_IF_TRACKING_URL_TEMPLATE_EXISTS (33): + Cannot clear final urls if tracking url + template exists. + CANNOT_CLEAR_FINAL_URLS_IF_URL_CUSTOM_PARAMETERS_EXIST (34): + Cannot clear final urls if url custom + parameters exist. + CANNOT_SET_BOTH_DESTINATION_URL_AND_FINAL_URLS (35): + Cannot set both destination url and final + urls. + CANNOT_SET_BOTH_DESTINATION_URL_AND_TRACKING_URL_TEMPLATE (36): + Cannot set both destination url and tracking + url template. + FINAL_URLS_NOT_SUPPORTED_FOR_CRITERION_TYPE (37): + Final urls are not supported for this + criterion type. + FINAL_MOBILE_URLS_NOT_SUPPORTED_FOR_CRITERION_TYPE (38): + Final mobile urls are not supported for this + criterion type. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AD_GROUP_CRITERION_LABEL_DOES_NOT_EXIST = 2 + AD_GROUP_CRITERION_LABEL_ALREADY_EXISTS = 3 + CANNOT_ADD_LABEL_TO_NEGATIVE_CRITERION = 4 + TOO_MANY_OPERATIONS = 5 + CANT_UPDATE_NEGATIVE = 6 + CONCRETE_TYPE_REQUIRED = 7 + BID_INCOMPATIBLE_WITH_ADGROUP = 8 + CANNOT_TARGET_AND_EXCLUDE = 9 + ILLEGAL_URL = 10 + INVALID_KEYWORD_TEXT = 11 + INVALID_DESTINATION_URL = 12 + MISSING_DESTINATION_URL_TAG = 13 + KEYWORD_LEVEL_BID_NOT_SUPPORTED_FOR_MANUALCPM = 14 + INVALID_USER_STATUS = 15 + CANNOT_ADD_CRITERIA_TYPE = 16 + CANNOT_EXCLUDE_CRITERIA_TYPE = 17 + CAMPAIGN_TYPE_NOT_COMPATIBLE_WITH_PARTIAL_FAILURE = 27 + OPERATIONS_FOR_TOO_MANY_SHOPPING_ADGROUPS = 28 + CANNOT_MODIFY_URL_FIELDS_WITH_DUPLICATE_ELEMENTS = 29 + CANNOT_SET_WITHOUT_FINAL_URLS = 30 + CANNOT_CLEAR_FINAL_URLS_IF_FINAL_MOBILE_URLS_EXIST = 31 + CANNOT_CLEAR_FINAL_URLS_IF_FINAL_APP_URLS_EXIST = 32 + CANNOT_CLEAR_FINAL_URLS_IF_TRACKING_URL_TEMPLATE_EXISTS = 33 + CANNOT_CLEAR_FINAL_URLS_IF_URL_CUSTOM_PARAMETERS_EXIST = 34 + CANNOT_SET_BOTH_DESTINATION_URL_AND_FINAL_URLS = 35 + CANNOT_SET_BOTH_DESTINATION_URL_AND_TRACKING_URL_TEMPLATE = 36 + FINAL_URLS_NOT_SUPPORTED_FOR_CRITERION_TYPE = 37 + FINAL_MOBILE_URLS_NOT_SUPPORTED_FOR_CRITERION_TYPE = 38 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/ad_group_customizer_error.py b/google/ads/googleads/v24/errors/types/ad_group_customizer_error.py new file mode 100644 index 000000000..374de18da --- /dev/null +++ b/google/ads/googleads/v24/errors/types/ad_group_customizer_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupCustomizerErrorEnum", + }, +) + + +class AdGroupCustomizerErrorEnum(proto.Message): + r"""Container for enum describing possible ad group customizer + errors. + + """ + + class AdGroupCustomizerError(proto.Enum): + r"""Enum describing possible ad group customizer errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/ad_group_error.py b/google/ads/googleads/v24/errors/types/ad_group_error.py new file mode 100644 index 000000000..806cf114e --- /dev/null +++ b/google/ads/googleads/v24/errors/types/ad_group_error.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupErrorEnum", + }, +) + + +class AdGroupErrorEnum(proto.Message): + r"""Container for enum describing possible ad group errors.""" + + class AdGroupError(proto.Enum): + r"""Enum describing possible ad group errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + DUPLICATE_ADGROUP_NAME (2): + AdGroup with the same name already exists for + the campaign. + INVALID_ADGROUP_NAME (3): + AdGroup name is not valid. + ADVERTISER_NOT_ON_CONTENT_NETWORK (5): + Advertiser is not allowed to target sites or + set site bids that are not on the Google Search + Network. + BID_TOO_BIG (6): + Bid amount is too big. + BID_TYPE_AND_BIDDING_STRATEGY_MISMATCH (7): + AdGroup bid does not match the campaign's + bidding strategy. + MISSING_ADGROUP_NAME (8): + AdGroup name is required for Add. + ADGROUP_LABEL_DOES_NOT_EXIST (9): + No link found between the ad group and the + label. + ADGROUP_LABEL_ALREADY_EXISTS (10): + The label has already been attached to the ad + group. + INVALID_CONTENT_BID_CRITERION_TYPE_GROUP (11): + The CriterionTypeGroup is not supported for + the content bid dimension. + AD_GROUP_TYPE_NOT_VALID_FOR_ADVERTISING_CHANNEL_TYPE (12): + The ad group type is not compatible with the + campaign channel type. + ADGROUP_TYPE_NOT_SUPPORTED_FOR_CAMPAIGN_SALES_COUNTRY (13): + The ad group type is not supported in the + country of sale of the campaign. + CANNOT_ADD_ADGROUP_OF_TYPE_DSA_TO_CAMPAIGN_WITHOUT_DSA_SETTING (14): + Ad groups of AdGroupType.SEARCH_DYNAMIC_ADS can only be + added to campaigns that have DynamicSearchAdsSetting + attached. + PROMOTED_HOTEL_AD_GROUPS_NOT_AVAILABLE_FOR_CUSTOMER (15): + Promoted hotels ad groups are only available + to customers on the allow-list. + INVALID_EXCLUDED_PARENT_ASSET_FIELD_TYPE (16): + The field type cannot be excluded because an + active ad group-asset link of this type exists. + INVALID_EXCLUDED_PARENT_ASSET_SET_TYPE (17): + The asset set type is invalid for setting the + excluded_parent_asset_set_types field. + CANNOT_ADD_AD_GROUP_FOR_CAMPAIGN_TYPE (18): + Cannot add ad groups for the campaign type. + INVALID_STATUS (19): + Invalid status for the ad group. + INVALID_STEP_ID_FOR_VIDEO_ADS_SEQUENCING (20): + For video ads sequencing, AdGroup ``step_id`` has to use a + ``step_id`` defined in + ``campaign.video_campaign_settings.video_ad_sequence``. + INVALID_AD_GROUP_TYPE_FOR_VIDEO_ADS_SEQUENCING (21): + For video ads sequencing, AdGroup type has to use a type + defined in + ``campaign.video_campaign_settings.video_ad_sequence``. + DUPLICATE_STEP_ID (22): + Only one AdGroup is allowed for each step ID + in video ads sequencing. + INVALID_VERTICAL_ADS_FORMAT_SETTING (23): + At least one Vertical Ads format must be + enabled for a campaign under Travel Ads in + Search Campaigns. + VERTICAL_ADS_FORMAT_SETTING_NOT_SUPPORTED_FOR_CAMPAIGNS_WITHOUT_AI_MAX (24): + AI max setting must be enabled to enable + Vertical Ads formats for a campaign under Travel + Ads in Search Campaigns. + VERTICAL_ADS_FORMAT_SETTING_NOT_SUPPORTED_FOR_CAMPAIGNS_WITHOUT_ENABLED_TRAVEL_FEED (25): + An enabled travel feed must be linked to + enable Vertical Ads formats for a campaign under + Travel Ads in Search Campaigns. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DUPLICATE_ADGROUP_NAME = 2 + INVALID_ADGROUP_NAME = 3 + ADVERTISER_NOT_ON_CONTENT_NETWORK = 5 + BID_TOO_BIG = 6 + BID_TYPE_AND_BIDDING_STRATEGY_MISMATCH = 7 + MISSING_ADGROUP_NAME = 8 + ADGROUP_LABEL_DOES_NOT_EXIST = 9 + ADGROUP_LABEL_ALREADY_EXISTS = 10 + INVALID_CONTENT_BID_CRITERION_TYPE_GROUP = 11 + AD_GROUP_TYPE_NOT_VALID_FOR_ADVERTISING_CHANNEL_TYPE = 12 + ADGROUP_TYPE_NOT_SUPPORTED_FOR_CAMPAIGN_SALES_COUNTRY = 13 + CANNOT_ADD_ADGROUP_OF_TYPE_DSA_TO_CAMPAIGN_WITHOUT_DSA_SETTING = 14 + PROMOTED_HOTEL_AD_GROUPS_NOT_AVAILABLE_FOR_CUSTOMER = 15 + INVALID_EXCLUDED_PARENT_ASSET_FIELD_TYPE = 16 + INVALID_EXCLUDED_PARENT_ASSET_SET_TYPE = 17 + CANNOT_ADD_AD_GROUP_FOR_CAMPAIGN_TYPE = 18 + INVALID_STATUS = 19 + INVALID_STEP_ID_FOR_VIDEO_ADS_SEQUENCING = 20 + INVALID_AD_GROUP_TYPE_FOR_VIDEO_ADS_SEQUENCING = 21 + DUPLICATE_STEP_ID = 22 + INVALID_VERTICAL_ADS_FORMAT_SETTING = 23 + VERTICAL_ADS_FORMAT_SETTING_NOT_SUPPORTED_FOR_CAMPAIGNS_WITHOUT_AI_MAX = ( + 24 + ) + VERTICAL_ADS_FORMAT_SETTING_NOT_SUPPORTED_FOR_CAMPAIGNS_WITHOUT_ENABLED_TRAVEL_FEED = ( + 25 + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/ad_group_feed_error.py b/google/ads/googleads/v24/errors/types/ad_group_feed_error.py new file mode 100644 index 000000000..e673e0dc7 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/ad_group_feed_error.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupFeedErrorEnum", + }, +) + + +class AdGroupFeedErrorEnum(proto.Message): + r"""Container for enum describing possible ad group feed errors.""" + + class AdGroupFeedError(proto.Enum): + r"""Enum describing possible ad group feed errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + FEED_ALREADY_EXISTS_FOR_PLACEHOLDER_TYPE (2): + An active feed already exists for this ad + group and place holder type. + CANNOT_CREATE_FOR_REMOVED_FEED (3): + The specified feed is removed. + ADGROUP_FEED_ALREADY_EXISTS (4): + The AdGroupFeed already exists. UPDATE + operation should be used to modify the existing + AdGroupFeed. + CANNOT_OPERATE_ON_REMOVED_ADGROUP_FEED (5): + Cannot operate on removed AdGroupFeed. + INVALID_PLACEHOLDER_TYPE (6): + Invalid placeholder type. + MISSING_FEEDMAPPING_FOR_PLACEHOLDER_TYPE (7): + Feed mapping for this placeholder type does + not exist. + NO_EXISTING_LOCATION_CUSTOMER_FEED (8): + Location AdGroupFeeds cannot be created + unless there is a location CustomerFeed for the + specified feed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + FEED_ALREADY_EXISTS_FOR_PLACEHOLDER_TYPE = 2 + CANNOT_CREATE_FOR_REMOVED_FEED = 3 + ADGROUP_FEED_ALREADY_EXISTS = 4 + CANNOT_OPERATE_ON_REMOVED_ADGROUP_FEED = 5 + INVALID_PLACEHOLDER_TYPE = 6 + MISSING_FEEDMAPPING_FOR_PLACEHOLDER_TYPE = 7 + NO_EXISTING_LOCATION_CUSTOMER_FEED = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/ad_parameter_error.py b/google/ads/googleads/v24/errors/types/ad_parameter_error.py new file mode 100644 index 000000000..f60f7fb68 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/ad_parameter_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AdParameterErrorEnum", + }, +) + + +class AdParameterErrorEnum(proto.Message): + r"""Container for enum describing possible ad parameter errors.""" + + class AdParameterError(proto.Enum): + r"""Enum describing possible ad parameter errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + AD_GROUP_CRITERION_MUST_BE_KEYWORD (2): + The ad group criterion must be a keyword + criterion. + INVALID_INSERTION_TEXT_FORMAT (3): + The insertion text is invalid. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AD_GROUP_CRITERION_MUST_BE_KEYWORD = 2 + INVALID_INSERTION_TEXT_FORMAT = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/ad_sharing_error.py b/google/ads/googleads/v24/errors/types/ad_sharing_error.py new file mode 100644 index 000000000..c246704be --- /dev/null +++ b/google/ads/googleads/v24/errors/types/ad_sharing_error.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AdSharingErrorEnum", + }, +) + + +class AdSharingErrorEnum(proto.Message): + r"""Container for enum describing possible ad sharing errors.""" + + class AdSharingError(proto.Enum): + r"""Enum describing possible ad sharing errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + AD_GROUP_ALREADY_CONTAINS_AD (2): + Error resulting in attempting to add an Ad to + an AdGroup that already contains the Ad. + INCOMPATIBLE_AD_UNDER_AD_GROUP (3): + Ad is not compatible with the AdGroup it is + being shared with. + CANNOT_SHARE_INACTIVE_AD (4): + Cannot add AdGroupAd on inactive Ad. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AD_GROUP_ALREADY_CONTAINS_AD = 2 + INCOMPATIBLE_AD_UNDER_AD_GROUP = 3 + CANNOT_SHARE_INACTIVE_AD = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/adx_error.py b/google/ads/googleads/v24/errors/types/adx_error.py new file mode 100644 index 000000000..cbfda985d --- /dev/null +++ b/google/ads/googleads/v24/errors/types/adx_error.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AdxErrorEnum", + }, +) + + +class AdxErrorEnum(proto.Message): + r"""Container for enum describing possible adx errors.""" + + class AdxError(proto.Enum): + r"""Enum describing possible adx errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + UNSUPPORTED_FEATURE (2): + Attempt to use non-AdX feature by AdX + customer. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UNSUPPORTED_FEATURE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/asset_error.py b/google/ads/googleads/v24/errors/types/asset_error.py new file mode 100644 index 000000000..856cf02f5 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/asset_error.py @@ -0,0 +1,212 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AssetErrorEnum", + }, +) + + +class AssetErrorEnum(proto.Message): + r"""Container for enum describing possible asset errors.""" + + class AssetError(proto.Enum): + r"""Enum describing possible asset errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CUSTOMER_NOT_ON_ALLOWLIST_FOR_ASSET_TYPE (13): + The customer is not on the allow-list for + this asset type. + DUPLICATE_ASSET (3): + Assets are duplicated across operations. + DUPLICATE_ASSET_NAME (4): + The asset name is duplicated, either across + operations or with an existing asset. + ASSET_DATA_IS_MISSING (5): + The ``Asset.asset_data`` oneof is empty. + CANNOT_MODIFY_ASSET_NAME (6): + The asset has a name which is different from + an existing duplicate that represents the same + content. + FIELD_INCOMPATIBLE_WITH_ASSET_TYPE (7): + The field cannot be set for this asset type. + INVALID_CALL_TO_ACTION_TEXT (8): + Call to action must come from the list of + supported values. + LEAD_FORM_INVALID_FIELDS_COMBINATION (9): + A lead form asset is created with an invalid + combination of input fields. + LEAD_FORM_MISSING_AGREEMENT (10): + Lead forms require that the Terms of Service + have been agreed to before mutates can be + executed. + INVALID_ASSET_STATUS (11): + Asset status is invalid in this operation. + FIELD_CANNOT_BE_MODIFIED_FOR_ASSET_TYPE (12): + The field cannot be modified by this asset + type. + SCHEDULES_CANNOT_OVERLAP (14): + Ad schedules for the same asset cannot + overlap. + PROMOTION_CANNOT_SET_PERCENT_OFF_AND_MONEY_AMOUNT_OFF (15): + Cannot set both percent off and money amount + off fields of promotion asset. + PROMOTION_CANNOT_SET_PROMOTION_CODE_AND_ORDERS_OVER_AMOUNT (16): + Cannot set both promotion code and orders + over amount fields of promotion asset. + TOO_MANY_DECIMAL_PLACES_SPECIFIED (17): + The field has too many decimal places + specified. + DUPLICATE_ASSETS_WITH_DIFFERENT_FIELD_VALUE (18): + Duplicate assets across operations, which have identical + ``Asset.asset_data`` oneof, cannot have different asset + level fields for asset types which are deduped. + CALL_CARRIER_SPECIFIC_SHORT_NUMBER_NOT_ALLOWED (19): + Carrier-specific short number is not allowed. + CALL_CUSTOMER_CONSENT_FOR_CALL_RECORDING_REQUIRED (20): + Customer consent required for call recording + Terms of Service. + CALL_DISALLOWED_NUMBER_TYPE (21): + The type of the specified phone number is not + allowed. + CALL_INVALID_CONVERSION_ACTION (22): + If the default ``call_conversion_action`` is not used, the + customer must have a ``ConversionAction`` with the same id + and the ``ConversionAction`` must be call conversion type. + CALL_INVALID_COUNTRY_CODE (23): + The country code of the phone number is + invalid. + CALL_INVALID_DOMESTIC_PHONE_NUMBER_FORMAT (24): + The format of the phone number is incorrect. + CALL_INVALID_PHONE_NUMBER (25): + The input phone number is not a valid phone + number. + CALL_PHONE_NUMBER_NOT_SUPPORTED_FOR_COUNTRY (26): + The phone number is not supported for this + country. + CALL_PREMIUM_RATE_NUMBER_NOT_ALLOWED (27): + Premium rate phone number is not allowed. + CALL_VANITY_PHONE_NUMBER_NOT_ALLOWED (28): + Vanity phone number is not allowed. + PRICE_HEADER_SAME_AS_DESCRIPTION (29): + ``PriceOffering`` cannot have the same value for header and + description. + MOBILE_APP_INVALID_APP_ID (30): + ``AppId`` is invalid. + MOBILE_APP_INVALID_FINAL_URL_FOR_APP_DOWNLOAD_URL (31): + Invalid App download URL in final URLs. + NAME_REQUIRED_FOR_ASSET_TYPE (32): + Asset name is required for the asset type. + LEAD_FORM_LEGACY_QUALIFYING_QUESTIONS_DISALLOWED (33): + Legacy qualifying questions cannot be in the + same Lead Form as custom questions. + NAME_CONFLICT_FOR_ASSET_TYPE (34): + Unique name is required for this asset type. + CANNOT_MODIFY_ASSET_SOURCE (35): + Cannot modify asset source. + CANNOT_MODIFY_AUTOMATICALLY_CREATED_ASSET (36): + User can not modify the automatically created + asset. + LEAD_FORM_LOCATION_ANSWER_TYPE_DISALLOWED (37): + Lead Form is disallowed to use ``LOCATION`` answer type. + PAGE_FEED_INVALID_LABEL_TEXT (38): + Page Feed label text contains invalid + characters. + CUSTOMER_NOT_ON_ALLOWLIST_FOR_WHATSAPP_MESSAGE_ASSETS (39): + The customer is not in the allow-list for + whatsapp message asset type. + CUSTOMER_NOT_ON_ALLOWLIST_FOR_APP_DEEP_LINK_ASSETS (40): + Only customers on the allowlist can create + ``AppDeepLinkAsset``. + PROMOTION_BARCODE_CANNOT_CONTAIN_LINKS (41): + Promotion barcode cannot contain links. + PROMOTION_BARCODE_INVALID_FORMAT (42): + Failed to encode promotion barcode: Invalid + format. + UNSUPPORTED_BARCODE_TYPE (43): + Barcode type is not supported. + PROMOTION_QR_CODE_CANNOT_CONTAIN_LINKS (44): + Promotion QR code cannot contain links. + PROMOTION_QR_CODE_INVALID_FORMAT (45): + Failed to encode promotion QR code: Invalid + format. + CUSTOMER_NOT_ON_ALLOWLIST_FOR_MESSAGE_ASSETS (46): + The customer is not in the allow-list for + Business message asset type. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER_NOT_ON_ALLOWLIST_FOR_ASSET_TYPE = 13 + DUPLICATE_ASSET = 3 + DUPLICATE_ASSET_NAME = 4 + ASSET_DATA_IS_MISSING = 5 + CANNOT_MODIFY_ASSET_NAME = 6 + FIELD_INCOMPATIBLE_WITH_ASSET_TYPE = 7 + INVALID_CALL_TO_ACTION_TEXT = 8 + LEAD_FORM_INVALID_FIELDS_COMBINATION = 9 + LEAD_FORM_MISSING_AGREEMENT = 10 + INVALID_ASSET_STATUS = 11 + FIELD_CANNOT_BE_MODIFIED_FOR_ASSET_TYPE = 12 + SCHEDULES_CANNOT_OVERLAP = 14 + PROMOTION_CANNOT_SET_PERCENT_OFF_AND_MONEY_AMOUNT_OFF = 15 + PROMOTION_CANNOT_SET_PROMOTION_CODE_AND_ORDERS_OVER_AMOUNT = 16 + TOO_MANY_DECIMAL_PLACES_SPECIFIED = 17 + DUPLICATE_ASSETS_WITH_DIFFERENT_FIELD_VALUE = 18 + CALL_CARRIER_SPECIFIC_SHORT_NUMBER_NOT_ALLOWED = 19 + CALL_CUSTOMER_CONSENT_FOR_CALL_RECORDING_REQUIRED = 20 + CALL_DISALLOWED_NUMBER_TYPE = 21 + CALL_INVALID_CONVERSION_ACTION = 22 + CALL_INVALID_COUNTRY_CODE = 23 + CALL_INVALID_DOMESTIC_PHONE_NUMBER_FORMAT = 24 + CALL_INVALID_PHONE_NUMBER = 25 + CALL_PHONE_NUMBER_NOT_SUPPORTED_FOR_COUNTRY = 26 + CALL_PREMIUM_RATE_NUMBER_NOT_ALLOWED = 27 + CALL_VANITY_PHONE_NUMBER_NOT_ALLOWED = 28 + PRICE_HEADER_SAME_AS_DESCRIPTION = 29 + MOBILE_APP_INVALID_APP_ID = 30 + MOBILE_APP_INVALID_FINAL_URL_FOR_APP_DOWNLOAD_URL = 31 + NAME_REQUIRED_FOR_ASSET_TYPE = 32 + LEAD_FORM_LEGACY_QUALIFYING_QUESTIONS_DISALLOWED = 33 + NAME_CONFLICT_FOR_ASSET_TYPE = 34 + CANNOT_MODIFY_ASSET_SOURCE = 35 + CANNOT_MODIFY_AUTOMATICALLY_CREATED_ASSET = 36 + LEAD_FORM_LOCATION_ANSWER_TYPE_DISALLOWED = 37 + PAGE_FEED_INVALID_LABEL_TEXT = 38 + CUSTOMER_NOT_ON_ALLOWLIST_FOR_WHATSAPP_MESSAGE_ASSETS = 39 + CUSTOMER_NOT_ON_ALLOWLIST_FOR_APP_DEEP_LINK_ASSETS = 40 + PROMOTION_BARCODE_CANNOT_CONTAIN_LINKS = 41 + PROMOTION_BARCODE_INVALID_FORMAT = 42 + UNSUPPORTED_BARCODE_TYPE = 43 + PROMOTION_QR_CODE_CANNOT_CONTAIN_LINKS = 44 + PROMOTION_QR_CODE_INVALID_FORMAT = 45 + CUSTOMER_NOT_ON_ALLOWLIST_FOR_MESSAGE_ASSETS = 46 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/asset_generation_error.py b/google/ads/googleads/v24/errors/types/asset_generation_error.py new file mode 100644 index 000000000..c17a71480 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/asset_generation_error.py @@ -0,0 +1,188 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGenerationErrorEnum", + }, +) + + +class AssetGenerationErrorEnum(proto.Message): + r"""Container for enum describing GenAI asset generation errors.""" + + class AssetGenerationError(proto.Enum): + r"""Enum describing GenAI asset generation errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + NO_ASSETS_GENERATED (2): + No assets were generated for the given + request. + FINAL_URL_REQUIRED (3): + A final URL is required but was not provided, + and could not be sourced from the existing + generation context because no existing + generation context was provided. + GENERATION_CONTEXT_MISSING_FINAL_URL (4): + A final URL is required but was not provided, + and could not be sourced from the provided + existing generation context. + FINAL_URL_SENSITIVE (5): + The provided final URL is considered + sensitive, and assets cannot be generated. + FINAL_URL_UNSUPPORTED_LANGUAGE (6): + The language of the provided final URL is not + supported. + FINAL_URL_UNAVAILABLE (7): + The provided final URL was not indexed or + could otherwise not be processed. + CAMPAIGN_TYPE_REQUIRED (8): + Campaign type is required but was not + provided, and could not be sourced from the + existing generation context because no existing + generation context was provided. + UNSUPPORTED_CAMPAIGN_TYPE (9): + The provided campaign type is not supported + for this asset generation operation. + UNSUPPORTED_FIELD_TYPE (10): + The provided field type is not supported for + this asset generation operation. + UNSUPPORTED_FIELD_TYPE_FOR_CAMPAIGN_TYPE (11): + The provided field type is not supported for + the given campaign type. + FREEFORM_PROMPT_UNSUPPORTED_LANGUAGE (12): + The language of the provided freeform prompt + is not supported. + FREEFORM_PROMPT_SENSITIVE (13): + The provided freeform prompt is considered + sensitive, and assets cannot be generated. + INPUT_IMAGE_FILE_SIZE_TOO_LARGE (14): + The provided image file size exceeds the + limit. + INPUT_IMAGE_EMPTY (15): + The provided image is empty. + GENERATION_TYPE_REQUIRED (16): + Exactly one generation type must be provided. + TOO_MANY_KEYWORDS (17): + Too many keywords provided in request. + KEYWORD_INVALID_LENGTH (18): + A provided keyword does not have a valid + length. + NO_VALID_KEYWORDS (19): + All keywords were filtered out. + FREEFORM_PROMPT_INVALID_LENGTH (20): + The provided freeform prompt does not have a + valid length. + FREEFORM_PROMPT_REFERENCES_CHILDREN (21): + The provided freeform prompt references + children. + FREEFORM_PROMPT_REFERENCES_SPECIFIC_PEOPLE (22): + The provided freeform prompt references + specific people. + FREEFORM_PROMPT_VIOLATES_ADS_POLICY (23): + The provided freeform prompt violates Ads + Policy. + FREEFORM_PROMPT_BRAND_CONTENT (24): + The provided freeform prompt contains brand + content. + INPUT_IMAGE_DEPICTS_CHILDREN (25): + The provided image depicts children. + INPUT_IMAGE_CONTAINS_BRAND_CONTENT (26): + The provided image contains brand content. + INPUT_IMAGE_SENSITIVE (27): + The provided image contains sensitive subject + matter. + INPUT_IMAGE_VIOLATES_POLICY (28): + The provided image may violate Google Ads + policies. + ALL_OUTPUT_IMAGES_FILTERED_OUT_CHILDREN_DEPICTION (29): + All output images were filtered out because + they included depictions of children. + ALL_OUTPUT_IMAGES_FILTERED_OUT_SPECIFIC_PEOPLE (30): + All output images were filtered out because + they included depictions of specific people. + ALL_OUTPUT_IMAGES_FILTERED_OUT (31): + All output images were filtered out for a + reason not covered by a more specific error + code. + INPUT_IMAGE_REQUIRED (32): + At least one input image is required for + certain requests. + INPUT_IMAGE_UNSUPPORTED_IMAGE_TYPE (33): + The provided image is of an unsupported type. + CONTEXT_ASSET_GROUP_NOT_FOUND (34): + Asset Group could not be found with the + provided ID. + CONTEXT_AD_GROUP_AD_NOT_FOUND (35): + Ad Group Ad could not be found with the + provided ID combination. + CONTEXT_CAMPAIGN_NOT_FOUND (36): + Could not find Campaign associated with the + provided generation context. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NO_ASSETS_GENERATED = 2 + FINAL_URL_REQUIRED = 3 + GENERATION_CONTEXT_MISSING_FINAL_URL = 4 + FINAL_URL_SENSITIVE = 5 + FINAL_URL_UNSUPPORTED_LANGUAGE = 6 + FINAL_URL_UNAVAILABLE = 7 + CAMPAIGN_TYPE_REQUIRED = 8 + UNSUPPORTED_CAMPAIGN_TYPE = 9 + UNSUPPORTED_FIELD_TYPE = 10 + UNSUPPORTED_FIELD_TYPE_FOR_CAMPAIGN_TYPE = 11 + FREEFORM_PROMPT_UNSUPPORTED_LANGUAGE = 12 + FREEFORM_PROMPT_SENSITIVE = 13 + INPUT_IMAGE_FILE_SIZE_TOO_LARGE = 14 + INPUT_IMAGE_EMPTY = 15 + GENERATION_TYPE_REQUIRED = 16 + TOO_MANY_KEYWORDS = 17 + KEYWORD_INVALID_LENGTH = 18 + NO_VALID_KEYWORDS = 19 + FREEFORM_PROMPT_INVALID_LENGTH = 20 + FREEFORM_PROMPT_REFERENCES_CHILDREN = 21 + FREEFORM_PROMPT_REFERENCES_SPECIFIC_PEOPLE = 22 + FREEFORM_PROMPT_VIOLATES_ADS_POLICY = 23 + FREEFORM_PROMPT_BRAND_CONTENT = 24 + INPUT_IMAGE_DEPICTS_CHILDREN = 25 + INPUT_IMAGE_CONTAINS_BRAND_CONTENT = 26 + INPUT_IMAGE_SENSITIVE = 27 + INPUT_IMAGE_VIOLATES_POLICY = 28 + ALL_OUTPUT_IMAGES_FILTERED_OUT_CHILDREN_DEPICTION = 29 + ALL_OUTPUT_IMAGES_FILTERED_OUT_SPECIFIC_PEOPLE = 30 + ALL_OUTPUT_IMAGES_FILTERED_OUT = 31 + INPUT_IMAGE_REQUIRED = 32 + INPUT_IMAGE_UNSUPPORTED_IMAGE_TYPE = 33 + CONTEXT_ASSET_GROUP_NOT_FOUND = 34 + CONTEXT_AD_GROUP_AD_NOT_FOUND = 35 + CONTEXT_CAMPAIGN_NOT_FOUND = 36 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/asset_group_asset_error.py b/google/ads/googleads/v24/errors/types/asset_group_asset_error.py new file mode 100644 index 000000000..51bcc0ac3 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/asset_group_asset_error.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGroupAssetErrorEnum", + }, +) + + +class AssetGroupAssetErrorEnum(proto.Message): + r"""Container for enum describing possible asset group asset + errors. + + """ + + class AssetGroupAssetError(proto.Enum): + r"""Enum describing possible asset group asset errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + DUPLICATE_RESOURCE (2): + Cannot add duplicated asset group asset. + EXPANDABLE_TAGS_NOT_ALLOWED_IN_DESCRIPTION (3): + Expandable tags are not allowed in + description assets. + AD_CUSTOMIZER_NOT_SUPPORTED (4): + Ad customizers are not supported in + assetgroup's text assets. + HOTEL_PROPERTY_ASSET_NOT_LINKED_TO_CAMPAIGN (5): + Cannot add a HotelPropertyAsset to an AssetGroup that isn't + linked to the parent campaign's hotel_property_asset_set + field. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DUPLICATE_RESOURCE = 2 + EXPANDABLE_TAGS_NOT_ALLOWED_IN_DESCRIPTION = 3 + AD_CUSTOMIZER_NOT_SUPPORTED = 4 + HOTEL_PROPERTY_ASSET_NOT_LINKED_TO_CAMPAIGN = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/asset_group_error.py b/google/ads/googleads/v24/errors/types/asset_group_error.py new file mode 100644 index 000000000..5d59d545f --- /dev/null +++ b/google/ads/googleads/v24/errors/types/asset_group_error.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGroupErrorEnum", + }, +) + + +class AssetGroupErrorEnum(proto.Message): + r"""Container for enum describing possible asset group errors.""" + + class AssetGroupError(proto.Enum): + r"""Enum describing possible asset group errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + DUPLICATE_NAME (2): + Each asset group in a single campaign must + have a unique name. + CANNOT_ADD_ASSET_GROUP_FOR_CAMPAIGN_TYPE (3): + Cannot add asset group for the campaign type. + NOT_ENOUGH_HEADLINE_ASSET (4): + Not enough headline asset for a valid asset + group. + NOT_ENOUGH_LONG_HEADLINE_ASSET (5): + Not enough long headline asset for a valid + asset group. + NOT_ENOUGH_DESCRIPTION_ASSET (6): + Not enough description headline asset for a + valid asset group. + NOT_ENOUGH_BUSINESS_NAME_ASSET (7): + Not enough business name asset for a valid + asset group. + NOT_ENOUGH_MARKETING_IMAGE_ASSET (8): + Not enough marketing image asset for a valid + asset group. + NOT_ENOUGH_SQUARE_MARKETING_IMAGE_ASSET (9): + Not enough square marketing image asset for a + valid asset group. + NOT_ENOUGH_LOGO_ASSET (10): + Not enough logo asset for a valid asset + group. + FINAL_URL_SHOPPING_MERCHANT_HOME_PAGE_URL_DOMAINS_DIFFER (11): + Final url and shopping merchant url does not + have the same domain. + PATH1_REQUIRED_WHEN_PATH2_IS_SET (12): + Path1 required when path2 is set. + SHORT_DESCRIPTION_REQUIRED (13): + At least one short description asset is + required for a valid asset group. + FINAL_URL_REQUIRED (14): + Final url field is required for asset group. + FINAL_URL_CONTAINS_INVALID_DOMAIN_NAME (15): + Final url contains invalid domain name. + AD_CUSTOMIZER_NOT_SUPPORTED (16): + Ad customizers are not supported in asset + group's text field. + CANNOT_MUTATE_ASSET_GROUP_FOR_REMOVED_CAMPAIGN (17): + Cannot mutate asset group for campaign with + removed status. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DUPLICATE_NAME = 2 + CANNOT_ADD_ASSET_GROUP_FOR_CAMPAIGN_TYPE = 3 + NOT_ENOUGH_HEADLINE_ASSET = 4 + NOT_ENOUGH_LONG_HEADLINE_ASSET = 5 + NOT_ENOUGH_DESCRIPTION_ASSET = 6 + NOT_ENOUGH_BUSINESS_NAME_ASSET = 7 + NOT_ENOUGH_MARKETING_IMAGE_ASSET = 8 + NOT_ENOUGH_SQUARE_MARKETING_IMAGE_ASSET = 9 + NOT_ENOUGH_LOGO_ASSET = 10 + FINAL_URL_SHOPPING_MERCHANT_HOME_PAGE_URL_DOMAINS_DIFFER = 11 + PATH1_REQUIRED_WHEN_PATH2_IS_SET = 12 + SHORT_DESCRIPTION_REQUIRED = 13 + FINAL_URL_REQUIRED = 14 + FINAL_URL_CONTAINS_INVALID_DOMAIN_NAME = 15 + AD_CUSTOMIZER_NOT_SUPPORTED = 16 + CANNOT_MUTATE_ASSET_GROUP_FOR_REMOVED_CAMPAIGN = 17 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/asset_group_listing_group_filter_error.py b/google/ads/googleads/v24/errors/types/asset_group_listing_group_filter_error.py new file mode 100644 index 000000000..d7b489b76 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/asset_group_listing_group_filter_error.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGroupListingGroupFilterErrorEnum", + }, +) + + +class AssetGroupListingGroupFilterErrorEnum(proto.Message): + r"""Container for enum describing possible asset group listing + group filter errors. + + """ + + class AssetGroupListingGroupFilterError(proto.Enum): + r"""Enum describing possible asset group listing group filter + errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + TREE_TOO_DEEP (2): + Listing group tree is too deep. + UNIT_CANNOT_HAVE_CHILDREN (3): + Listing Group UNIT node cannot have children. + SUBDIVISION_MUST_HAVE_EVERYTHING_ELSE_CHILD (4): + Listing Group SUBDIVISION node must have + everything else child. + DIFFERENT_DIMENSION_TYPE_BETWEEN_SIBLINGS (5): + Dimension type of Listing Group must be the + same as that of its siblings. + SAME_DIMENSION_VALUE_BETWEEN_SIBLINGS (6): + The sibling Listing Groups target exactly the + same dimension value. + SAME_DIMENSION_TYPE_BETWEEN_ANCESTORS (7): + The dimension type is the same as one of the + ancestor Listing Groups. + MULTIPLE_ROOTS (8): + Each Listing Group tree must have a single + root. + INVALID_DIMENSION_VALUE (9): + Invalid Listing Group dimension value. + MUST_REFINE_HIERARCHICAL_PARENT_TYPE (10): + Hierarchical dimension must refine a + dimension of the same type. + INVALID_PRODUCT_BIDDING_CATEGORY (11): + Invalid Product Bidding Category. + CHANGING_CASE_VALUE_WITH_CHILDREN (12): + Modifying case value is allowed only while + updating the entire subtree at the same time. + SUBDIVISION_HAS_CHILDREN (13): + Subdivision node has children which must be + removed first. + CANNOT_REFINE_HIERARCHICAL_EVERYTHING_ELSE (14): + Dimension can't subdivide everything-else + node in its own hierarchy. + DIMENSION_TYPE_NOT_ALLOWED (15): + This dimension type is not allowed in this + context. + DUPLICATE_WEBPAGE_FILTER_UNDER_ASSET_GROUP (16): + All the webpage filters under an AssetGroup + should be distinct. + LISTING_SOURCE_NOT_ALLOWED (17): + Filter of the listing source type is not + allowed in the context. + FILTER_EXCLUSION_NOT_ALLOWED (18): + Exclusion filters are not allowed in the + context. + MULTIPLE_LISTING_SOURCES (19): + All the filters under an AssetGroup should + have the same listing source. + MULTIPLE_WEBPAGE_CONDITION_TYPES_NOT_ALLOWED (20): + All the conditions in a webpage needs to be + of same type. + MULTIPLE_WEBPAGE_TYPES_PER_ASSET_GROUP (21): + All the webpage types of the filters under an AssetGroup + should be of same type. Example: All the webpage types can + be of type custom_label or url_contains but not both. + PAGE_FEED_FILTER_HAS_PARENT (22): + All page feed filter nodes are root nodes and + they can't have a parent. + MULTIPLE_OPERATIONS_ON_ONE_NODE (23): + There cannot be more than one mutate + operation per request that targets a single + asset group listing group filter. + TREE_WAS_INVALID_BEFORE_MUTATION (24): + The tree is in an invalid state in the + database. Any changes that don't fix its issues + will fail validation. + RETAIL_INVALID_SHARED_SET_TYPE (25): + The shared set type is not supported for + RetailFilterBundle. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + TREE_TOO_DEEP = 2 + UNIT_CANNOT_HAVE_CHILDREN = 3 + SUBDIVISION_MUST_HAVE_EVERYTHING_ELSE_CHILD = 4 + DIFFERENT_DIMENSION_TYPE_BETWEEN_SIBLINGS = 5 + SAME_DIMENSION_VALUE_BETWEEN_SIBLINGS = 6 + SAME_DIMENSION_TYPE_BETWEEN_ANCESTORS = 7 + MULTIPLE_ROOTS = 8 + INVALID_DIMENSION_VALUE = 9 + MUST_REFINE_HIERARCHICAL_PARENT_TYPE = 10 + INVALID_PRODUCT_BIDDING_CATEGORY = 11 + CHANGING_CASE_VALUE_WITH_CHILDREN = 12 + SUBDIVISION_HAS_CHILDREN = 13 + CANNOT_REFINE_HIERARCHICAL_EVERYTHING_ELSE = 14 + DIMENSION_TYPE_NOT_ALLOWED = 15 + DUPLICATE_WEBPAGE_FILTER_UNDER_ASSET_GROUP = 16 + LISTING_SOURCE_NOT_ALLOWED = 17 + FILTER_EXCLUSION_NOT_ALLOWED = 18 + MULTIPLE_LISTING_SOURCES = 19 + MULTIPLE_WEBPAGE_CONDITION_TYPES_NOT_ALLOWED = 20 + MULTIPLE_WEBPAGE_TYPES_PER_ASSET_GROUP = 21 + PAGE_FEED_FILTER_HAS_PARENT = 22 + MULTIPLE_OPERATIONS_ON_ONE_NODE = 23 + TREE_WAS_INVALID_BEFORE_MUTATION = 24 + RETAIL_INVALID_SHARED_SET_TYPE = 25 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/asset_group_signal_error.py b/google/ads/googleads/v24/errors/types/asset_group_signal_error.py new file mode 100644 index 000000000..25ca509be --- /dev/null +++ b/google/ads/googleads/v24/errors/types/asset_group_signal_error.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGroupSignalErrorEnum", + }, +) + + +class AssetGroupSignalErrorEnum(proto.Message): + r"""Container for enum describing possible asset group signal + errors. + + """ + + class AssetGroupSignalError(proto.Enum): + r"""Enum describing possible asset group signal errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + TOO_MANY_WORDS (2): + The number of words in the Search Theme + signal exceed the allowed maximum. You can add + up to 10 words in a keyword. See + https://support.google.com/google-ads/answer/7476658 + for details. + SEARCH_THEME_POLICY_VIOLATION (3): + The search theme requested to be added + violates certain policy. See + https://support.google.com/adspolicy/answer/6008942. + AUDIENCE_WITH_WRONG_ASSET_GROUP_ID (4): + The asset group referenced by the asset group + signal does not match the asset group referenced + by the audience being used in the asset group + signal. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + TOO_MANY_WORDS = 2 + SEARCH_THEME_POLICY_VIOLATION = 3 + AUDIENCE_WITH_WRONG_ASSET_GROUP_ID = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/asset_link_error.py b/google/ads/googleads/v24/errors/types/asset_link_error.py new file mode 100644 index 000000000..9aa2139e7 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/asset_link_error.py @@ -0,0 +1,166 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AssetLinkErrorEnum", + }, +) + + +class AssetLinkErrorEnum(proto.Message): + r"""Container for enum describing possible asset link errors.""" + + class AssetLinkError(proto.Enum): + r"""Enum describing possible asset link errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + PINNING_UNSUPPORTED (2): + Pinning is not supported for the given asset + link field. + UNSUPPORTED_FIELD_TYPE (3): + The given field type is not supported to be + added directly through asset links. + FIELD_TYPE_INCOMPATIBLE_WITH_ASSET_TYPE (4): + The given asset's type and the specified + field type are incompatible. + FIELD_TYPE_INCOMPATIBLE_WITH_CAMPAIGN_TYPE (5): + The specified field type is incompatible with + the given campaign type. + INCOMPATIBLE_ADVERTISING_CHANNEL_TYPE (6): + The campaign advertising channel type cannot + be associated with the given asset due to + channel-based restrictions on the asset's + fields. + IMAGE_NOT_WITHIN_SPECIFIED_DIMENSION_RANGE (7): + The image asset provided is not within the + dimension constraints specified for the + submitted asset field. + INVALID_PINNED_FIELD (8): + The pinned field is not valid for the + submitted asset field. + MEDIA_BUNDLE_ASSET_FILE_SIZE_TOO_LARGE (9): + The media bundle asset provided is too large + for the submitted asset field. + NOT_ENOUGH_AVAILABLE_ASSET_LINKS_FOR_VALID_COMBINATION (10): + Not enough assets are available for use with + other fields since other assets are pinned to + specific fields. + NOT_ENOUGH_AVAILABLE_ASSET_LINKS_WITH_FALLBACK (11): + Not enough assets with fallback are + available. When validating the minimum number of + assets, assets without fallback (for example, + assets that contain location tag without default + value "{LOCATION(City)}") will not be counted. + NOT_ENOUGH_AVAILABLE_ASSET_LINKS_WITH_FALLBACK_FOR_VALID_COMBINATION (12): + This is a combination of the + NOT_ENOUGH_AVAILABLE_ASSET_LINKS_FOR_VALID_COMBINATION and + NOT_ENOUGH_AVAILABLE_ASSET_LINKS_WITH_FALLBACK errors. Not + enough assets with fallback are available since some assets + are pinned. + YOUTUBE_VIDEO_REMOVED (13): + The YouTube video referenced in the provided + asset has been removed. + YOUTUBE_VIDEO_TOO_LONG (14): + The YouTube video referenced in the provided + asset is too long for the field submitted. + YOUTUBE_VIDEO_TOO_SHORT (15): + The YouTube video referenced in the provided + asset is too short for the field submitted. + EXCLUDED_PARENT_FIELD_TYPE (16): + The specified field type is excluded for + given campaign or ad group. + INVALID_STATUS (17): + The status is invalid for the operation + specified. + YOUTUBE_VIDEO_DURATION_NOT_DEFINED (18): + The YouTube video referenced in the provided + asset has unknown duration. This might be the + case for a livestream video or a video being + currently uploaded to YouTube. In both cases, + the video duration should eventually get + resolved. + CANNOT_CREATE_AUTOMATICALLY_CREATED_LINKS (19): + User cannot create automatically created + links. + CANNOT_LINK_TO_AUTOMATICALLY_CREATED_ASSET (20): + Advertiser links cannot link to automatically + created asset. + CANNOT_MODIFY_ASSET_LINK_SOURCE (21): + Automatically created links cannot be changed + into advertiser links or the reverse. + CANNOT_LINK_LOCATION_LEAD_FORM_WITHOUT_LOCATION_ASSET (22): + Lead Form asset with Location answer type + can't be linked to the Customer/Campaign because + there are no Location assets. + CUSTOMER_NOT_VERIFIED (23): + Customer is not verified. + UNSUPPORTED_CALL_TO_ACTION (24): + Call to action value is not supported. + BRAND_ASSETS_NOT_LINKED_AT_ASSET_GROUP_LEVEL (25): + For Performance Max campaigns where brand_guidelines_enabled + is false, business name and logo assets must be linked as + AssetGroupAssets. + BRAND_ASSETS_NOT_LINKED_AT_CAMPAIGN_LEVEL (26): + For Performance Max campaigns where brand_guidelines_enabled + is true, business name and logo assets must be linked as + CampaignAssets. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PINNING_UNSUPPORTED = 2 + UNSUPPORTED_FIELD_TYPE = 3 + FIELD_TYPE_INCOMPATIBLE_WITH_ASSET_TYPE = 4 + FIELD_TYPE_INCOMPATIBLE_WITH_CAMPAIGN_TYPE = 5 + INCOMPATIBLE_ADVERTISING_CHANNEL_TYPE = 6 + IMAGE_NOT_WITHIN_SPECIFIED_DIMENSION_RANGE = 7 + INVALID_PINNED_FIELD = 8 + MEDIA_BUNDLE_ASSET_FILE_SIZE_TOO_LARGE = 9 + NOT_ENOUGH_AVAILABLE_ASSET_LINKS_FOR_VALID_COMBINATION = 10 + NOT_ENOUGH_AVAILABLE_ASSET_LINKS_WITH_FALLBACK = 11 + NOT_ENOUGH_AVAILABLE_ASSET_LINKS_WITH_FALLBACK_FOR_VALID_COMBINATION = ( + 12 + ) + YOUTUBE_VIDEO_REMOVED = 13 + YOUTUBE_VIDEO_TOO_LONG = 14 + YOUTUBE_VIDEO_TOO_SHORT = 15 + EXCLUDED_PARENT_FIELD_TYPE = 16 + INVALID_STATUS = 17 + YOUTUBE_VIDEO_DURATION_NOT_DEFINED = 18 + CANNOT_CREATE_AUTOMATICALLY_CREATED_LINKS = 19 + CANNOT_LINK_TO_AUTOMATICALLY_CREATED_ASSET = 20 + CANNOT_MODIFY_ASSET_LINK_SOURCE = 21 + CANNOT_LINK_LOCATION_LEAD_FORM_WITHOUT_LOCATION_ASSET = 22 + CUSTOMER_NOT_VERIFIED = 23 + UNSUPPORTED_CALL_TO_ACTION = 24 + BRAND_ASSETS_NOT_LINKED_AT_ASSET_GROUP_LEVEL = 25 + BRAND_ASSETS_NOT_LINKED_AT_CAMPAIGN_LEVEL = 26 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/asset_set_asset_error.py b/google/ads/googleads/v24/errors/types/asset_set_asset_error.py new file mode 100644 index 000000000..6cd62bc97 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/asset_set_asset_error.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AssetSetAssetErrorEnum", + }, +) + + +class AssetSetAssetErrorEnum(proto.Message): + r"""Container for enum describing possible asset set asset + errors. + + """ + + class AssetSetAssetError(proto.Enum): + r"""Enum describing possible asset set asset errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_ASSET_TYPE (2): + The asset type is not eligible to be linked + to the specific type of asset set. + INVALID_ASSET_SET_TYPE (3): + The asset set type is not eligible to contain + the specified type of assets. + DUPLICATE_EXTERNAL_KEY (4): + The asset contains duplicate external key + with another asset in the asset set. + PARENT_LINKAGE_DOES_NOT_EXIST (5): + When attaching a Location typed Asset to a + LocationGroup typed AssetSet, the AssetSetAsset + linkage between the parent LocationSync AssetSet + and the Asset doesn't exist. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_ASSET_TYPE = 2 + INVALID_ASSET_SET_TYPE = 3 + DUPLICATE_EXTERNAL_KEY = 4 + PARENT_LINKAGE_DOES_NOT_EXIST = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/asset_set_error.py b/google/ads/googleads/v24/errors/types/asset_set_error.py new file mode 100644 index 000000000..69762eaed --- /dev/null +++ b/google/ads/googleads/v24/errors/types/asset_set_error.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AssetSetErrorEnum", + }, +) + + +class AssetSetErrorEnum(proto.Message): + r"""Container for enum describing possible asset set errors.""" + + class AssetSetError(proto.Enum): + r"""Enum describing possible asset set errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + DUPLICATE_ASSET_SET_NAME (2): + The asset set name matches that of another + enabled asset set. + INVALID_PARENT_ASSET_SET_TYPE (3): + The type of AssetSet.asset_set_source does not match the + type of AssetSet.location_set.source in its parent AssetSet. + ASSET_SET_SOURCE_INCOMPATIBLE_WITH_PARENT_ASSET_SET (4): + The asset set source doesn't match its parent + AssetSet's data. + ASSET_SET_TYPE_CANNOT_BE_LINKED_TO_CUSTOMER (5): + This AssetSet type cannot be linked to + CustomerAssetSet. + INVALID_CHAIN_IDS (6): + The chain id(s) in ChainSet of a LOCATION_SYNC typed + AssetSet is invalid. + LOCATION_SYNC_ASSET_SET_DOES_NOT_SUPPORT_RELATIONSHIP_TYPE (7): + The relationship type in ChainSet of a LOCATION_SYNC typed + AssetSet is not supported. + NOT_UNIQUE_ENABLED_LOCATION_SYNC_TYPED_ASSET_SET (8): + There is more than one enabled LocationSync + typed AssetSet under one customer. + INVALID_PLACE_IDS (9): + The place id(s) in a LocationSync typed + AssetSet is invalid and can't be decoded. + OAUTH_INFO_INVALID (11): + The Google Business Profile OAuth info is + invalid. + OAUTH_INFO_MISSING (12): + The Google Business Profile OAuth info is + missing. + CANNOT_DELETE_AS_ENABLED_LINKAGES_EXIST (10): + Can't delete an AssetSet if it has any + enabled linkages (e.g. CustomerAssetSet), or + AssetSet is a parent AssetSet and has enabled + child AssetSet associated. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DUPLICATE_ASSET_SET_NAME = 2 + INVALID_PARENT_ASSET_SET_TYPE = 3 + ASSET_SET_SOURCE_INCOMPATIBLE_WITH_PARENT_ASSET_SET = 4 + ASSET_SET_TYPE_CANNOT_BE_LINKED_TO_CUSTOMER = 5 + INVALID_CHAIN_IDS = 6 + LOCATION_SYNC_ASSET_SET_DOES_NOT_SUPPORT_RELATIONSHIP_TYPE = 7 + NOT_UNIQUE_ENABLED_LOCATION_SYNC_TYPED_ASSET_SET = 8 + INVALID_PLACE_IDS = 9 + OAUTH_INFO_INVALID = 11 + OAUTH_INFO_MISSING = 12 + CANNOT_DELETE_AS_ENABLED_LINKAGES_EXIST = 10 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/asset_set_link_error.py b/google/ads/googleads/v24/errors/types/asset_set_link_error.py new file mode 100644 index 000000000..30dcd4c1e --- /dev/null +++ b/google/ads/googleads/v24/errors/types/asset_set_link_error.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AssetSetLinkErrorEnum", + }, +) + + +class AssetSetLinkErrorEnum(proto.Message): + r"""Container for enum describing possible asset set link errors.""" + + class AssetSetLinkError(proto.Enum): + r"""Enum describing possible asset set link errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INCOMPATIBLE_ADVERTISING_CHANNEL_TYPE (2): + Advertising channel type cannot be attached + to the asset set due to channel-based + restrictions. + DUPLICATE_FEED_LINK (3): + For this asset set type, only one campaign to + feed linkage is allowed. + INCOMPATIBLE_ASSET_SET_TYPE_WITH_CAMPAIGN_TYPE (4): + The asset set type and campaign type are + incompatible. + DUPLICATE_ASSET_SET_LINK (5): + Cannot link duplicate asset sets to the same + campaign. + ASSET_SET_LINK_CANNOT_BE_REMOVED (6): + Cannot remove the asset set link. If a + campaign is linked with only one asset set and + you attempt to unlink them, this error will be + triggered. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INCOMPATIBLE_ADVERTISING_CHANNEL_TYPE = 2 + DUPLICATE_FEED_LINK = 3 + INCOMPATIBLE_ASSET_SET_TYPE_WITH_CAMPAIGN_TYPE = 4 + DUPLICATE_ASSET_SET_LINK = 5 + ASSET_SET_LINK_CANNOT_BE_REMOVED = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/audience_error.py b/google/ads/googleads/v24/errors/types/audience_error.py new file mode 100644 index 000000000..e024461ef --- /dev/null +++ b/google/ads/googleads/v24/errors/types/audience_error.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AudienceErrorEnum", + }, +) + + +class AudienceErrorEnum(proto.Message): + r"""Container for enum describing possible audience errors.""" + + class AudienceError(proto.Enum): + r"""Enum describing possible audience errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + NAME_ALREADY_IN_USE (2): + An audience with this name already exists. + DIMENSION_INVALID (3): + A dimension within the audience definition is + not valid. + AUDIENCE_SEGMENT_NOT_FOUND (4): + One of the audience segment added is not + found. + AUDIENCE_SEGMENT_TYPE_NOT_SUPPORTED (5): + One of the audience segment type is not + supported. + DUPLICATE_AUDIENCE_SEGMENT (6): + The same segment already exists in this + audience. + TOO_MANY_SEGMENTS (7): + Audience can't have more than allowed number + segments. + TOO_MANY_DIMENSIONS_OF_SAME_TYPE (8): + Audience can't have multiple dimensions of + same type. + IN_USE (9): + The audience cannot be removed, because it is + currently used in an ad group criterion or asset + group signal in an (enabled or paused) ad group + or campaign. + MISSING_ASSET_GROUP_ID (10): + Asset Group scoped audience requires an asset + group ID. + CANNOT_CHANGE_FROM_CUSTOMER_TO_ASSET_GROUP_SCOPE (11): + Audience scope may not be changed from + Customer to AssetGroup. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NAME_ALREADY_IN_USE = 2 + DIMENSION_INVALID = 3 + AUDIENCE_SEGMENT_NOT_FOUND = 4 + AUDIENCE_SEGMENT_TYPE_NOT_SUPPORTED = 5 + DUPLICATE_AUDIENCE_SEGMENT = 6 + TOO_MANY_SEGMENTS = 7 + TOO_MANY_DIMENSIONS_OF_SAME_TYPE = 8 + IN_USE = 9 + MISSING_ASSET_GROUP_ID = 10 + CANNOT_CHANGE_FROM_CUSTOMER_TO_ASSET_GROUP_SCOPE = 11 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/audience_insights_error.py b/google/ads/googleads/v24/errors/types/audience_insights_error.py new file mode 100644 index 000000000..633e9e286 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/audience_insights_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AudienceInsightsErrorEnum", + }, +) + + +class AudienceInsightsErrorEnum(proto.Message): + r"""Container for enum describing possible errors returned from + the AudienceInsightsService. + + """ + + class AudienceInsightsError(proto.Enum): + r"""Enum describing possible errors from AudienceInsightsService. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + DIMENSION_INCOMPATIBLE_WITH_TOPIC_AUDIENCE_COMBINATIONS (2): + The dimensions cannot be used with topic + audience combinations. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DIMENSION_INCOMPATIBLE_WITH_TOPIC_AUDIENCE_COMBINATIONS = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/authentication_error.py b/google/ads/googleads/v24/errors/types/authentication_error.py new file mode 100644 index 000000000..a5e742e51 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/authentication_error.py @@ -0,0 +1,138 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AuthenticationErrorEnum", + }, +) + + +class AuthenticationErrorEnum(proto.Message): + r"""Container for enum describing possible authentication errors.""" + + class AuthenticationError(proto.Enum): + r"""Enum describing possible authentication errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + AUTHENTICATION_ERROR (2): + Authentication of the request failed. + CLIENT_CUSTOMER_ID_INVALID (5): + Client customer ID is not a number. + CUSTOMER_NOT_FOUND (8): + No customer found for the provided customer + ID. + GOOGLE_ACCOUNT_DELETED (9): + Client's Google account is deleted. + GOOGLE_ACCOUNT_COOKIE_INVALID (10): + Google account login token in the cookie is + invalid. + GOOGLE_ACCOUNT_AUTHENTICATION_FAILED (25): + A problem occurred during Google account + authentication. + GOOGLE_ACCOUNT_USER_AND_ADS_USER_MISMATCH (12): + The user in the Google account login token + does not match the user ID in the cookie. + LOGIN_COOKIE_REQUIRED (13): + Login cookie is required for authentication. + NOT_ADS_USER (14): + The Google account that generated the OAuth + access token is not associated with a Google Ads + account. Create a new account, or add the Google + account to an existing Google Ads account. + OAUTH_TOKEN_INVALID (15): + OAuth token in the header is not valid. + OAUTH_TOKEN_EXPIRED (16): + OAuth token in the header has expired. + OAUTH_TOKEN_DISABLED (17): + OAuth token in the header has been disabled. + OAUTH_TOKEN_REVOKED (18): + OAuth token in the header has been revoked. + OAUTH_TOKEN_HEADER_INVALID (19): + OAuth token HTTP header is malformed. + LOGIN_COOKIE_INVALID (20): + Login cookie is not valid. + INVALID_EMAIL_ADDRESS (21): + The email address provided is invalid or does + not exist. + USER_ID_INVALID (22): + User ID in the header is not a valid ID. + TWO_STEP_VERIFICATION_NOT_ENROLLED (23): + An account administrator changed this + account's authentication settings. To access + this Google Ads account, enable 2-Step + Verification in your Google account at + https://www.google.com/landing/2step. + ADVANCED_PROTECTION_NOT_ENROLLED (24): + An account administrator changed this + account's authentication settings. To access + this Google Ads account, enable Advanced + Protection in your Google account at + https://landing.google.com/advancedprotection. + ORGANIZATION_NOT_RECOGNIZED (26): + The Cloud organization associated with the + project is not recognized. + ORGANIZATION_NOT_APPROVED (27): + The Cloud organization associated with the + project is not approved for prod access. + ORGANIZATION_NOT_ASSOCIATED_WITH_DEVELOPER_TOKEN (28): + The Cloud organization associated with the + project is not associated with the developer + token. + DEVELOPER_TOKEN_INVALID (29): + The developer token is not valid. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AUTHENTICATION_ERROR = 2 + CLIENT_CUSTOMER_ID_INVALID = 5 + CUSTOMER_NOT_FOUND = 8 + GOOGLE_ACCOUNT_DELETED = 9 + GOOGLE_ACCOUNT_COOKIE_INVALID = 10 + GOOGLE_ACCOUNT_AUTHENTICATION_FAILED = 25 + GOOGLE_ACCOUNT_USER_AND_ADS_USER_MISMATCH = 12 + LOGIN_COOKIE_REQUIRED = 13 + NOT_ADS_USER = 14 + OAUTH_TOKEN_INVALID = 15 + OAUTH_TOKEN_EXPIRED = 16 + OAUTH_TOKEN_DISABLED = 17 + OAUTH_TOKEN_REVOKED = 18 + OAUTH_TOKEN_HEADER_INVALID = 19 + LOGIN_COOKIE_INVALID = 20 + INVALID_EMAIL_ADDRESS = 21 + USER_ID_INVALID = 22 + TWO_STEP_VERIFICATION_NOT_ENROLLED = 23 + ADVANCED_PROTECTION_NOT_ENROLLED = 24 + ORGANIZATION_NOT_RECOGNIZED = 26 + ORGANIZATION_NOT_APPROVED = 27 + ORGANIZATION_NOT_ASSOCIATED_WITH_DEVELOPER_TOKEN = 28 + DEVELOPER_TOKEN_INVALID = 29 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/authorization_error.py b/google/ads/googleads/v24/errors/types/authorization_error.py new file mode 100644 index 000000000..14b65e7f9 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/authorization_error.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AuthorizationErrorEnum", + }, +) + + +class AuthorizationErrorEnum(proto.Message): + r"""Container for enum describing possible authorization errors.""" + + class AuthorizationError(proto.Enum): + r"""Enum describing possible authorization errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + USER_PERMISSION_DENIED (2): + User doesn't have permission to access customer. Note: If + you're accessing a client customer, the manager's customer + ID must be set in the ``login-customer-id`` header. Learn + more at + https://developers.google.com/google-ads/api/docs/concepts/call-structure#cid + DEVELOPER_TOKEN_NOT_ON_ALLOWLIST (13): + The developer token is not on the allow-list. + DEVELOPER_TOKEN_PROHIBITED (4): + The developer token is not allowed with the + project sent in the request. + PROJECT_DISABLED (5): + The Google Cloud project sent in the request + does not have permission to access the api. + AUTHORIZATION_ERROR (6): + Authorization of the client failed. + ACTION_NOT_PERMITTED (7): + The user does not have permission to perform + this action (for example, ADD, UPDATE, REMOVE) + on the resource or call a method. + INCOMPLETE_SIGNUP (8): + Signup not complete. + CUSTOMER_NOT_ENABLED (24): + The customer account can't be accessed + because it is not yet enabled or has been + deactivated. + MISSING_TOS (9): + The developer must sign the terms of service. + They can be found here: + ads.google.com/aw/apicenter + DEVELOPER_TOKEN_NOT_APPROVED (10): + The developer token is only approved for use + with test accounts. To access non-test accounts, + apply for Basic or Standard access. + INVALID_LOGIN_CUSTOMER_ID_SERVING_CUSTOMER_ID_COMBINATION (11): + The login customer specified does not have + access to the account specified, so the request + is invalid. + SERVICE_ACCESS_DENIED (12): + The developer specified does not have access + to the service. + ACCESS_DENIED_FOR_ACCOUNT_TYPE (25): + The customer (or login customer) isn't in + Google Ads. It belongs to another ads system. + METRIC_ACCESS_DENIED (26): + The developer does not have access to the + metrics queried. + CLOUD_PROJECT_NOT_UNDER_ORGANIZATION (27): + The Google Cloud project is not under the + required organization. + ACTION_NOT_PERMITTED_FOR_SUSPENDED_ACCOUNT (28): + The user does not have permission to perform + this action on the resource or method because + the Google Ads account is suspended. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + USER_PERMISSION_DENIED = 2 + DEVELOPER_TOKEN_NOT_ON_ALLOWLIST = 13 + DEVELOPER_TOKEN_PROHIBITED = 4 + PROJECT_DISABLED = 5 + AUTHORIZATION_ERROR = 6 + ACTION_NOT_PERMITTED = 7 + INCOMPLETE_SIGNUP = 8 + CUSTOMER_NOT_ENABLED = 24 + MISSING_TOS = 9 + DEVELOPER_TOKEN_NOT_APPROVED = 10 + INVALID_LOGIN_CUSTOMER_ID_SERVING_CUSTOMER_ID_COMBINATION = 11 + SERVICE_ACCESS_DENIED = 12 + ACCESS_DENIED_FOR_ACCOUNT_TYPE = 25 + METRIC_ACCESS_DENIED = 26 + CLOUD_PROJECT_NOT_UNDER_ORGANIZATION = 27 + ACTION_NOT_PERMITTED_FOR_SUSPENDED_ACCOUNT = 28 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/automatically_created_asset_removal_error.py b/google/ads/googleads/v24/errors/types/automatically_created_asset_removal_error.py new file mode 100644 index 000000000..b6b04b4d9 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/automatically_created_asset_removal_error.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "AutomaticallyCreatedAssetRemovalErrorEnum", + }, +) + + +class AutomaticallyCreatedAssetRemovalErrorEnum(proto.Message): + r"""Container for enum describing possible automatically created + asset removal errors. + + """ + + class AutomaticallyCreatedAssetRemovalError(proto.Enum): + r"""Enum describing possible automatically created asset removal + errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + AD_DOES_NOT_EXIST (2): + The ad does not exist. + INVALID_AD_TYPE (3): + Ad type is not supported. Only Responsive + Search Ad type is supported. + ASSET_DOES_NOT_EXIST (4): + The asset does not exist. + ASSET_FIELD_TYPE_DOES_NOT_MATCH (5): + The asset field type does not match. + NOT_AN_AUTOMATICALLY_CREATED_ASSET (6): + Not an automatically created asset. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + AD_DOES_NOT_EXIST = 2 + INVALID_AD_TYPE = 3 + ASSET_DOES_NOT_EXIST = 4 + ASSET_FIELD_TYPE_DOES_NOT_MATCH = 5 + NOT_AN_AUTOMATICALLY_CREATED_ASSET = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/batch_job_error.py b/google/ads/googleads/v24/errors/types/batch_job_error.py new file mode 100644 index 000000000..798f45765 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/batch_job_error.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "BatchJobErrorEnum", + }, +) + + +class BatchJobErrorEnum(proto.Message): + r"""Container for enum describing possible batch job errors.""" + + class BatchJobError(proto.Enum): + r"""Enum describing possible request errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CANNOT_MODIFY_JOB_AFTER_JOB_STARTS_RUNNING (2): + The batch job cannot add more operations or + run after it has started running. + EMPTY_OPERATIONS (3): + The operations for an AddBatchJobOperations + request were empty. + INVALID_SEQUENCE_TOKEN (4): + The sequence token for an + AddBatchJobOperations request was invalid. + RESULTS_NOT_READY (5): + Batch job results can only be retrieved once + the job is finished. + INVALID_PAGE_SIZE (6): + The page size for ListBatchJobResults was + invalid. + CAN_ONLY_REMOVE_PENDING_JOB (7): + The batch job cannot be removed because it + has started running. + CANNOT_LIST_RESULTS (8): + The batch job cannot be listed due to + unexpected errors such as duplicate checkpoints. + ASSET_GROUP_AND_ASSET_GROUP_ASSET_TRANSACTION_FAILURE (9): + The request contains interdependent + AssetGroup and AssetGroupAsset operations that + are treated atomically as a single transaction, + and one or more of the operations in that + transaction failed, which caused the entire + transaction, and therefore this mutate + operation, to fail. The operations that caused + the transaction to fail can be found in the + consecutive AssetGroup or AssetGroupAsset + results with the same asset group id. The mutate + operation will be successful once the remaining + errors in the transaction are fixed. + ASSET_GROUP_LISTING_GROUP_FILTER_TRANSACTION_FAILURE (10): + The request contains interdependent + AssetGroupListingGroupFilter operations that are + treated atomically as a single transaction, and + one or more of the operations in that + transaction failed, which caused the entire + transaction, and therefore this mutate + operation, to fail. The operations that caused + the transaction to fail can be found in the + consecutive AssetGroupListingGroupFilter results + with the same asset group id. The mutate + operation will be successful once the remaining + errors in the transaction are fixed. + REQUEST_TOO_LARGE (11): + The AddBatchJobOperationsRequest is too + large. Split the request into smaller requests. + The maximum allowed request size is 10484504 + bytes. + CAMPAIGN_AND_CAMPAIGN_ASSET_TRANSACTION_FAILURE (12): + This error indicates a failed transaction + involving interdependent Campaign and + CampaignAsset operations that are treated + atomically as a single transaction. Because some + operations within the transaction failed, the + entire set of changes was rejected. Related + error details are found in the results for the + Campaign and CampaignAssets sharing the same + Campaign ID. The transaction will succeed after + all associated errors are resolved. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CANNOT_MODIFY_JOB_AFTER_JOB_STARTS_RUNNING = 2 + EMPTY_OPERATIONS = 3 + INVALID_SEQUENCE_TOKEN = 4 + RESULTS_NOT_READY = 5 + INVALID_PAGE_SIZE = 6 + CAN_ONLY_REMOVE_PENDING_JOB = 7 + CANNOT_LIST_RESULTS = 8 + ASSET_GROUP_AND_ASSET_GROUP_ASSET_TRANSACTION_FAILURE = 9 + ASSET_GROUP_LISTING_GROUP_FILTER_TRANSACTION_FAILURE = 10 + REQUEST_TOO_LARGE = 11 + CAMPAIGN_AND_CAMPAIGN_ASSET_TRANSACTION_FAILURE = 12 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/benchmarks_error.py b/google/ads/googleads/v24/errors/types/benchmarks_error.py new file mode 100644 index 000000000..b74df7bf8 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/benchmarks_error.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "BenchmarksErrorEnum", + }, +) + + +class BenchmarksErrorEnum(proto.Message): + r"""Container for enum describing possible errors returned from + the BenchmarksService. + + """ + + class BenchmarksError(proto.Enum): + r"""Enum describing possible errors from BenchmarksService. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + MAX_QUERY_COMPLEXITY_EXCEEDED (2): + The combination of inputs to generate + benchmarks is too complex. To reduce complexity, + try selecting a more granular benchmarks source, + a smaller date range, or a smaller set of + products. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MAX_QUERY_COMPLEXITY_EXCEEDED = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/bidding_error.py b/google/ads/googleads/v24/errors/types/bidding_error.py new file mode 100644 index 000000000..073935d61 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/bidding_error.py @@ -0,0 +1,152 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "BiddingErrorEnum", + }, +) + + +class BiddingErrorEnum(proto.Message): + r"""Container for enum describing possible bidding errors.""" + + class BiddingError(proto.Enum): + r"""Enum describing possible bidding errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + BIDDING_STRATEGY_TRANSITION_NOT_ALLOWED (2): + Cannot transition to new bidding strategy. + CANNOT_ATTACH_BIDDING_STRATEGY_TO_CAMPAIGN (7): + Cannot attach bidding strategy to campaign. + INVALID_ANONYMOUS_BIDDING_STRATEGY_TYPE (10): + Bidding strategy is not supported or cannot + be used as anonymous. + INVALID_BIDDING_STRATEGY_TYPE (14): + The type does not match the named strategy's + type. + INVALID_BID (17): + The bid is invalid. + BIDDING_STRATEGY_NOT_AVAILABLE_FOR_ACCOUNT_TYPE (18): + Bidding strategy is not available for the + account type. + CANNOT_CREATE_CAMPAIGN_WITH_BIDDING_STRATEGY (21): + Campaign can not be created with given + bidding strategy. It can be transitioned to the + strategy, once eligible. + CANNOT_TARGET_CONTENT_NETWORK_ONLY_WITH_CAMPAIGN_LEVEL_POP_BIDDING_STRATEGY (23): + Cannot target content network only as + campaign uses Page One Promoted bidding + strategy. + BIDDING_STRATEGY_NOT_SUPPORTED_WITH_AD_SCHEDULE (24): + Budget Optimizer and Target Spend bidding + strategies are not supported for campaigns with + AdSchedule targeting. + PAY_PER_CONVERSION_NOT_AVAILABLE_FOR_CUSTOMER (25): + Pay per conversion is not available to all + the customer, only few customers on the + allow-list can use this. + PAY_PER_CONVERSION_NOT_ALLOWED_WITH_TARGET_CPA (26): + Pay per conversion is not allowed with Target + CPA. + BIDDING_STRATEGY_NOT_ALLOWED_FOR_SEARCH_ONLY_CAMPAIGNS (27): + Cannot set bidding strategy to Manual CPM for + search network only campaigns. + BIDDING_STRATEGY_NOT_SUPPORTED_IN_DRAFTS_OR_EXPERIMENTS (28): + The bidding strategy is not supported for use + in drafts or experiments. + BIDDING_STRATEGY_TYPE_DOES_NOT_SUPPORT_PRODUCT_TYPE_ADGROUP_CRITERION (29): + Bidding strategy type does not support + product type ad group criterion. + BID_TOO_SMALL (30): + Bid amount is too small. + BID_TOO_BIG (31): + Bid amount is too big. + BID_TOO_MANY_FRACTIONAL_DIGITS (32): + Bid has too many fractional digit precision. + INVALID_DOMAIN_NAME (33): + Invalid domain name specified. + NOT_COMPATIBLE_WITH_PAYMENT_MODE (34): + The field is not compatible with the payment + mode. + BIDDING_STRATEGY_TYPE_INCOMPATIBLE_WITH_SHARED_BUDGET (37): + Bidding strategy type is incompatible with + shared budget. + BIDDING_STRATEGY_AND_BUDGET_MUST_BE_ALIGNED (38): + The attached bidding strategy and budget must + be aligned with each other if alignment is + specified on either entity. + BIDDING_STRATEGY_AND_BUDGET_MUST_BE_ATTACHED_TO_THE_SAME_CAMPAIGNS_TO_ALIGN (39): + The attached bidding strategy and budget must + be attached to the same campaigns to become + aligned. + BIDDING_STRATEGY_AND_BUDGET_MUST_BE_REMOVED_TOGETHER (40): + The aligned bidding strategy and budget must + be removed at the same time. + CPC_BID_FLOOR_MICROS_GREATER_THAN_CPC_BID_CEILING_MICROS (41): + cpc_bid_floor_micros is greater than cpc_bid_ceiling_micros. + TARGET_ROAS_TOLERANCE_PERCENT_MILLIS_MUST_BE_INTEGER (42): + target_roas_tolerance_percent_millis must be integer. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BIDDING_STRATEGY_TRANSITION_NOT_ALLOWED = 2 + CANNOT_ATTACH_BIDDING_STRATEGY_TO_CAMPAIGN = 7 + INVALID_ANONYMOUS_BIDDING_STRATEGY_TYPE = 10 + INVALID_BIDDING_STRATEGY_TYPE = 14 + INVALID_BID = 17 + BIDDING_STRATEGY_NOT_AVAILABLE_FOR_ACCOUNT_TYPE = 18 + CANNOT_CREATE_CAMPAIGN_WITH_BIDDING_STRATEGY = 21 + CANNOT_TARGET_CONTENT_NETWORK_ONLY_WITH_CAMPAIGN_LEVEL_POP_BIDDING_STRATEGY = ( + 23 + ) + BIDDING_STRATEGY_NOT_SUPPORTED_WITH_AD_SCHEDULE = 24 + PAY_PER_CONVERSION_NOT_AVAILABLE_FOR_CUSTOMER = 25 + PAY_PER_CONVERSION_NOT_ALLOWED_WITH_TARGET_CPA = 26 + BIDDING_STRATEGY_NOT_ALLOWED_FOR_SEARCH_ONLY_CAMPAIGNS = 27 + BIDDING_STRATEGY_NOT_SUPPORTED_IN_DRAFTS_OR_EXPERIMENTS = 28 + BIDDING_STRATEGY_TYPE_DOES_NOT_SUPPORT_PRODUCT_TYPE_ADGROUP_CRITERION = ( + 29 + ) + BID_TOO_SMALL = 30 + BID_TOO_BIG = 31 + BID_TOO_MANY_FRACTIONAL_DIGITS = 32 + INVALID_DOMAIN_NAME = 33 + NOT_COMPATIBLE_WITH_PAYMENT_MODE = 34 + BIDDING_STRATEGY_TYPE_INCOMPATIBLE_WITH_SHARED_BUDGET = 37 + BIDDING_STRATEGY_AND_BUDGET_MUST_BE_ALIGNED = 38 + BIDDING_STRATEGY_AND_BUDGET_MUST_BE_ATTACHED_TO_THE_SAME_CAMPAIGNS_TO_ALIGN = ( + 39 + ) + BIDDING_STRATEGY_AND_BUDGET_MUST_BE_REMOVED_TOGETHER = 40 + CPC_BID_FLOOR_MICROS_GREATER_THAN_CPC_BID_CEILING_MICROS = 41 + TARGET_ROAS_TOLERANCE_PERCENT_MILLIS_MUST_BE_INTEGER = 42 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/bidding_strategy_error.py b/google/ads/googleads/v24/errors/types/bidding_strategy_error.py new file mode 100644 index 000000000..c7ce798f9 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/bidding_strategy_error.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "BiddingStrategyErrorEnum", + }, +) + + +class BiddingStrategyErrorEnum(proto.Message): + r"""Container for enum describing possible bidding strategy + errors. + + """ + + class BiddingStrategyError(proto.Enum): + r"""Enum describing possible bidding strategy errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + DUPLICATE_NAME (2): + Each bidding strategy must have a unique + name. + CANNOT_CHANGE_BIDDING_STRATEGY_TYPE (3): + Bidding strategy type is immutable. + CANNOT_REMOVE_ASSOCIATED_STRATEGY (4): + Only bidding strategies not linked to + campaigns, adgroups or adgroup criteria can be + removed. + BIDDING_STRATEGY_NOT_SUPPORTED (5): + The specified bidding strategy is not + supported. + INCOMPATIBLE_BIDDING_STRATEGY_AND_BIDDING_STRATEGY_GOAL_TYPE (6): + The bidding strategy is incompatible with the + campaign's bidding strategy goal type. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DUPLICATE_NAME = 2 + CANNOT_CHANGE_BIDDING_STRATEGY_TYPE = 3 + CANNOT_REMOVE_ASSOCIATED_STRATEGY = 4 + BIDDING_STRATEGY_NOT_SUPPORTED = 5 + INCOMPATIBLE_BIDDING_STRATEGY_AND_BIDDING_STRATEGY_GOAL_TYPE = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/billing_setup_error.py b/google/ads/googleads/v24/errors/types/billing_setup_error.py new file mode 100644 index 000000000..6f76b2d66 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/billing_setup_error.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "BillingSetupErrorEnum", + }, +) + + +class BillingSetupErrorEnum(proto.Message): + r"""Container for enum describing possible billing setup errors.""" + + class BillingSetupError(proto.Enum): + r"""Enum describing possible billing setup errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CANNOT_USE_EXISTING_AND_NEW_ACCOUNT (2): + Cannot specify both an existing payments + account and a new payments account when setting + up billing. + CANNOT_REMOVE_STARTED_BILLING_SETUP (3): + Cannot cancel an approved billing setup whose + start time has passed. + CANNOT_CHANGE_BILLING_TO_SAME_PAYMENTS_ACCOUNT (4): + Cannot perform a Change of Bill-To (CBT) to + the same payments account. + BILLING_SETUP_NOT_PERMITTED_FOR_CUSTOMER_STATUS (5): + Billing setups can only be used by customers + with ENABLED or DRAFT status. + INVALID_PAYMENTS_ACCOUNT (6): + Billing setups must either include a + correctly formatted existing payments account + id, or a non-empty new payments account name. + BILLING_SETUP_NOT_PERMITTED_FOR_CUSTOMER_CATEGORY (7): + Only billable and third-party customers can + create billing setups. + INVALID_START_TIME_TYPE (8): + Billing setup creations can only use NOW for + start time type. + THIRD_PARTY_ALREADY_HAS_BILLING (9): + Billing setups can only be created for a + third-party customer if they do not already have + a setup. + BILLING_SETUP_IN_PROGRESS (10): + Billing setups cannot be created if there is + already a pending billing in progress. + NO_SIGNUP_PERMISSION (11): + Billing setups can only be created by + customers who have permission to setup billings. + Users can contact a representative for help + setting up permissions. + CHANGE_OF_BILL_TO_IN_PROGRESS (12): + Billing setups cannot be created if there is + already a future-approved billing. + PAYMENTS_PROFILE_NOT_FOUND (13): + Requested payments profile not found. + PAYMENTS_ACCOUNT_NOT_FOUND (14): + Requested payments account not found. + PAYMENTS_PROFILE_INELIGIBLE (15): + Billing setup creation failed because the + payments profile is ineligible. + PAYMENTS_ACCOUNT_INELIGIBLE (16): + Billing setup creation failed because the + payments account is ineligible. + CUSTOMER_NEEDS_INTERNAL_APPROVAL (17): + Billing setup creation failed because the + payments profile needs internal approval. + PAYMENTS_PROFILE_NEEDS_SERVICE_AGREEMENT_ACCEPTANCE (18): + Billing setup creation failed because the + user needs to accept master service agreement on + the payments profile. + PAYMENTS_ACCOUNT_INELIGIBLE_CURRENCY_CODE_MISMATCH (19): + Payments account has different currency code + than the current customer and hence cannot be + used to setup billing. + FUTURE_START_TIME_PROHIBITED (20): + A start time in the future cannot be used + because there is currently no active billing + setup for this customer. + TOO_MANY_BILLING_SETUPS_FOR_PAYMENTS_ACCOUNT (21): + The payments account has maximum number of + billing setups. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CANNOT_USE_EXISTING_AND_NEW_ACCOUNT = 2 + CANNOT_REMOVE_STARTED_BILLING_SETUP = 3 + CANNOT_CHANGE_BILLING_TO_SAME_PAYMENTS_ACCOUNT = 4 + BILLING_SETUP_NOT_PERMITTED_FOR_CUSTOMER_STATUS = 5 + INVALID_PAYMENTS_ACCOUNT = 6 + BILLING_SETUP_NOT_PERMITTED_FOR_CUSTOMER_CATEGORY = 7 + INVALID_START_TIME_TYPE = 8 + THIRD_PARTY_ALREADY_HAS_BILLING = 9 + BILLING_SETUP_IN_PROGRESS = 10 + NO_SIGNUP_PERMISSION = 11 + CHANGE_OF_BILL_TO_IN_PROGRESS = 12 + PAYMENTS_PROFILE_NOT_FOUND = 13 + PAYMENTS_ACCOUNT_NOT_FOUND = 14 + PAYMENTS_PROFILE_INELIGIBLE = 15 + PAYMENTS_ACCOUNT_INELIGIBLE = 16 + CUSTOMER_NEEDS_INTERNAL_APPROVAL = 17 + PAYMENTS_PROFILE_NEEDS_SERVICE_AGREEMENT_ACCEPTANCE = 18 + PAYMENTS_ACCOUNT_INELIGIBLE_CURRENCY_CODE_MISMATCH = 19 + FUTURE_START_TIME_PROHIBITED = 20 + TOO_MANY_BILLING_SETUPS_FOR_PAYMENTS_ACCOUNT = 21 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/brand_guidelines_migration_error.py b/google/ads/googleads/v24/errors/types/brand_guidelines_migration_error.py new file mode 100644 index 000000000..4391ba490 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/brand_guidelines_migration_error.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "BrandGuidelinesMigrationErrorEnum", + }, +) + + +class BrandGuidelinesMigrationErrorEnum(proto.Message): + r"""Container for enum describing brand guidelines migration + errors. + + """ + + class BrandGuidelinesMigrationError(proto.Enum): + r"""Enum describing brand guidelines migration errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + BRAND_GUIDELINES_ALREADY_ENABLED (2): + This campaign is already enabled for Brand + Guidelines. + CANNOT_ENABLE_BRAND_GUIDELINES_FOR_REMOVED_CAMPAIGN (3): + Brand Guidelines can only be enabled for + active or suspended campaigns. + BRAND_GUIDELINES_LOGO_LIMIT_EXCEEDED (4): + Maximum of 5 square and landscape logos can + be specified for Brand Guidelines. + CANNOT_AUTO_POPULATE_BRAND_ASSETS_WHEN_BRAND_ASSETS_PROVIDED (5): + Either auto_populate_brand_assets must be true or + brand_assets must be provided, but not both. + AUTO_POPULATE_BRAND_ASSETS_REQUIRED_WHEN_BRAND_ASSETS_OMITTED (6): + Either auto_populate_brand_assets can be false or + brand_assets can be omitted, but not both. + TOO_MANY_ENABLE_OPERATIONS (7): + A maximum of 10 enable operations can be + executed in a request. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BRAND_GUIDELINES_ALREADY_ENABLED = 2 + CANNOT_ENABLE_BRAND_GUIDELINES_FOR_REMOVED_CAMPAIGN = 3 + BRAND_GUIDELINES_LOGO_LIMIT_EXCEEDED = 4 + CANNOT_AUTO_POPULATE_BRAND_ASSETS_WHEN_BRAND_ASSETS_PROVIDED = 5 + AUTO_POPULATE_BRAND_ASSETS_REQUIRED_WHEN_BRAND_ASSETS_OMITTED = 6 + TOO_MANY_ENABLE_OPERATIONS = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/campaign_budget_error.py b/google/ads/googleads/v24/errors/types/campaign_budget_error.py new file mode 100644 index 000000000..dcbfedbfb --- /dev/null +++ b/google/ads/googleads/v24/errors/types/campaign_budget_error.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignBudgetErrorEnum", + }, +) + + +class CampaignBudgetErrorEnum(proto.Message): + r"""Container for enum describing possible campaign budget + errors. + + """ + + class CampaignBudgetError(proto.Enum): + r"""Enum describing possible campaign budget errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CAMPAIGN_BUDGET_CANNOT_BE_SHARED (17): + The campaign budget cannot be shared. + CAMPAIGN_BUDGET_REMOVED (2): + The requested campaign budget no longer + exists. + CAMPAIGN_BUDGET_IN_USE (3): + The campaign budget is associated with at + least one campaign, and so the campaign budget + cannot be removed. + CAMPAIGN_BUDGET_PERIOD_NOT_AVAILABLE (4): + Customer is not on the allow-list for this + campaign budget period. + CANNOT_MODIFY_FIELD_OF_IMPLICITLY_SHARED_CAMPAIGN_BUDGET (6): + This field is not mutable on implicitly + shared campaign budgets + CANNOT_UPDATE_CAMPAIGN_BUDGET_TO_IMPLICITLY_SHARED (7): + Cannot change explicitly shared campaign + budgets back to implicitly shared ones. + CANNOT_UPDATE_CAMPAIGN_BUDGET_TO_EXPLICITLY_SHARED_WITHOUT_NAME (8): + An implicit campaign budget without a name + cannot be changed to explicitly shared campaign + budget. + CANNOT_UPDATE_CAMPAIGN_BUDGET_TO_EXPLICITLY_SHARED (9): + Cannot change an implicitly shared campaign + budget to an explicitly shared one. + CANNOT_USE_IMPLICITLY_SHARED_CAMPAIGN_BUDGET_WITH_MULTIPLE_CAMPAIGNS (10): + Only explicitly shared campaign budgets can + be used with multiple campaigns. + DUPLICATE_NAME (11): + A campaign budget with this name already + exists. + MONEY_AMOUNT_IN_WRONG_CURRENCY (12): + A money amount was not in the expected + currency. + MONEY_AMOUNT_LESS_THAN_CURRENCY_MINIMUM_CPC (13): + A money amount was less than the minimum CPC + for currency. + MONEY_AMOUNT_TOO_LARGE (14): + A money amount was greater than the maximum + allowed. + NEGATIVE_MONEY_AMOUNT (15): + A money amount was negative. + NON_MULTIPLE_OF_MINIMUM_CURRENCY_UNIT (16): + A money amount was not a multiple of a + minimum unit. + TOTAL_BUDGET_AMOUNT_MUST_BE_UNSET_FOR_BUDGET_PERIOD_DAILY (18): + Total budget amount must be unset when + BudgetPeriod is DAILY. + INVALID_PERIOD (19): + The period of the budget is not allowed. + CANNOT_USE_ACCELERATED_DELIVERY_MODE (20): + Cannot use accelerated delivery method on + this budget. + BUDGET_AMOUNT_MUST_BE_UNSET_FOR_CUSTOM_BUDGET_PERIOD (21): + Budget amount must be unset when BudgetPeriod + is CUSTOM. + BUDGET_BELOW_PER_DAY_MINIMUM (22): + Budget amount or total amount must be above this campaign's + per-day minimum. See the error's + details.budget_per_day_minimum_error_details field for more + information. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CAMPAIGN_BUDGET_CANNOT_BE_SHARED = 17 + CAMPAIGN_BUDGET_REMOVED = 2 + CAMPAIGN_BUDGET_IN_USE = 3 + CAMPAIGN_BUDGET_PERIOD_NOT_AVAILABLE = 4 + CANNOT_MODIFY_FIELD_OF_IMPLICITLY_SHARED_CAMPAIGN_BUDGET = 6 + CANNOT_UPDATE_CAMPAIGN_BUDGET_TO_IMPLICITLY_SHARED = 7 + CANNOT_UPDATE_CAMPAIGN_BUDGET_TO_EXPLICITLY_SHARED_WITHOUT_NAME = 8 + CANNOT_UPDATE_CAMPAIGN_BUDGET_TO_EXPLICITLY_SHARED = 9 + CANNOT_USE_IMPLICITLY_SHARED_CAMPAIGN_BUDGET_WITH_MULTIPLE_CAMPAIGNS = ( + 10 + ) + DUPLICATE_NAME = 11 + MONEY_AMOUNT_IN_WRONG_CURRENCY = 12 + MONEY_AMOUNT_LESS_THAN_CURRENCY_MINIMUM_CPC = 13 + MONEY_AMOUNT_TOO_LARGE = 14 + NEGATIVE_MONEY_AMOUNT = 15 + NON_MULTIPLE_OF_MINIMUM_CURRENCY_UNIT = 16 + TOTAL_BUDGET_AMOUNT_MUST_BE_UNSET_FOR_BUDGET_PERIOD_DAILY = 18 + INVALID_PERIOD = 19 + CANNOT_USE_ACCELERATED_DELIVERY_MODE = 20 + BUDGET_AMOUNT_MUST_BE_UNSET_FOR_CUSTOM_BUDGET_PERIOD = 21 + BUDGET_BELOW_PER_DAY_MINIMUM = 22 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/campaign_conversion_goal_error.py b/google/ads/googleads/v24/errors/types/campaign_conversion_goal_error.py new file mode 100644 index 000000000..154765974 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/campaign_conversion_goal_error.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignConversionGoalErrorEnum", + }, +) + + +class CampaignConversionGoalErrorEnum(proto.Message): + r"""Container for enum describing possible campaign conversion + goal errors. + + """ + + class CampaignConversionGoalError(proto.Enum): + r"""Enum describing possible campaign conversion goal errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CANNOT_USE_CAMPAIGN_GOAL_FOR_SEARCH_ADS_360_MANAGED_CAMPAIGN (2): + Campaign is managed by Search Ads 360 but + uses Unified Goal. + CANNOT_USE_STORE_SALE_GOAL_FOR_PERFORMANCE_MAX_CAMPAIGN (3): + Performance Max campaign cannot use an + included store sale campaign goal. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CANNOT_USE_CAMPAIGN_GOAL_FOR_SEARCH_ADS_360_MANAGED_CAMPAIGN = 2 + CANNOT_USE_STORE_SALE_GOAL_FOR_PERFORMANCE_MAX_CAMPAIGN = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/campaign_criterion_error.py b/google/ads/googleads/v24/errors/types/campaign_criterion_error.py new file mode 100644 index 000000000..7700de79f --- /dev/null +++ b/google/ads/googleads/v24/errors/types/campaign_criterion_error.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignCriterionErrorEnum", + }, +) + + +class CampaignCriterionErrorEnum(proto.Message): + r"""Container for enum describing possible campaign criterion + errors. + + """ + + class CampaignCriterionError(proto.Enum): + r"""Enum describing possible campaign criterion errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CONCRETE_TYPE_REQUIRED (2): + Concrete type of criterion (keyword v.s. + placement) is required for CREATE and UPDATE + operations. + INVALID_PLACEMENT_URL (3): + Invalid placement URL. + CANNOT_EXCLUDE_CRITERIA_TYPE (4): + Criteria type can not be excluded for the + campaign by the customer. like AOL account type + cannot target site type criteria + CANNOT_SET_STATUS_FOR_CRITERIA_TYPE (5): + Cannot set the campaign criterion status for + this criteria type. + CANNOT_SET_STATUS_FOR_EXCLUDED_CRITERIA (6): + Cannot set the campaign criterion status for + an excluded criteria. + CANNOT_TARGET_AND_EXCLUDE (7): + Cannot target and exclude the same criterion. + TOO_MANY_OPERATIONS (8): + The mutate contained too many operations. + OPERATOR_NOT_SUPPORTED_FOR_CRITERION_TYPE (9): + This operator cannot be applied to a + criterion of this type. + SHOPPING_CAMPAIGN_SALES_COUNTRY_NOT_SUPPORTED_FOR_SALES_CHANNEL (10): + The Shopping campaign sales country is not + supported for ProductSalesChannel targeting. + CANNOT_ADD_EXISTING_FIELD (11): + The existing field can't be updated with + CREATE operation. It can be updated with UPDATE + operation only. + CANNOT_UPDATE_NEGATIVE_CRITERION (12): + Negative criteria are immutable, so updates + are not allowed. + CANNOT_SET_NEGATIVE_KEYWORD_THEME_CONSTANT_CRITERION (13): + Only free form names are allowed for negative + Smart campaign keyword theme. + INVALID_KEYWORD_THEME_CONSTANT (14): + Invalid Smart campaign keyword theme constant + criterion. + MISSING_KEYWORD_THEME_CONSTANT_OR_FREE_FORM_KEYWORD_THEME (15): + A Smart campaign keyword theme constant or + free-form Smart campaign keyword theme is + required. + CANNOT_TARGET_BOTH_PROXIMITY_AND_LOCATION_CRITERIA_FOR_SMART_CAMPAIGN (16): + A Smart campaign may not target proximity and + location criteria simultaneously. + CANNOT_TARGET_MULTIPLE_PROXIMITY_CRITERIA_FOR_SMART_CAMPAIGN (17): + A Smart campaign may not target multiple + proximity criteria. + LOCATION_NOT_LAUNCHED_FOR_LOCAL_SERVICES_CAMPAIGN (18): + Location is not launched for Local Services + Campaigns. + LOCATION_INVALID_FOR_LOCAL_SERVICES_CAMPAIGN (19): + A Local Services campaign may not target + certain criteria types. + CANNOT_TARGET_COUNTRY_FOR_LOCAL_SERVICES_CAMPAIGN (20): + Country locations are not supported for Local + Services campaign. + LOCATION_NOT_IN_HOME_COUNTRY_FOR_LOCAL_SERVICES_CAMPAIGN (21): + Location is not within the home country of + Local Services campaign. + CANNOT_ADD_OR_REMOVE_LOCATION_FOR_LOCAL_SERVICES_CAMPAIGN (22): + Local Services profile does not exist for a + particular Local Services campaign. + AT_LEAST_ONE_POSITIVE_LOCATION_REQUIRED_FOR_LOCAL_SERVICES_CAMPAIGN (23): + Local Services campaign must have at least + one target location. + AT_LEAST_ONE_LOCAL_SERVICE_ID_CRITERION_REQUIRED_FOR_LOCAL_SERVICES_CAMPAIGN (24): + At least one positive local service ID + criterion is required for a Local Services + campaign. + LOCAL_SERVICE_ID_NOT_FOUND_FOR_CATEGORY (25): + Local service ID is not found under selected + categories in local services campaign setting. + CANNOT_ATTACH_BRAND_LIST_TO_NON_QUALIFIED_SEARCH_CAMPAIGN (26): + For search advertising channel, brand lists + can only be applied to exclusive targeting, + broad match campaigns for inclusive targeting or + PMax generated campaigns. + CANNOT_REMOVE_ALL_LOCATIONS_DUE_TO_TOO_MANY_COUNTRY_EXCLUSIONS (27): + Campaigns that target all countries and + territories are limited to a certain number of + top-level location exclusions. If removing a + criterion causes the campaign to target all + countries and territories and the campaign has + more top-level location exclusions than the + limit allows, then this error is returned. + INVALID_VIDEO_LINEUP_ID (28): + Video lineup ID does not exist. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CONCRETE_TYPE_REQUIRED = 2 + INVALID_PLACEMENT_URL = 3 + CANNOT_EXCLUDE_CRITERIA_TYPE = 4 + CANNOT_SET_STATUS_FOR_CRITERIA_TYPE = 5 + CANNOT_SET_STATUS_FOR_EXCLUDED_CRITERIA = 6 + CANNOT_TARGET_AND_EXCLUDE = 7 + TOO_MANY_OPERATIONS = 8 + OPERATOR_NOT_SUPPORTED_FOR_CRITERION_TYPE = 9 + SHOPPING_CAMPAIGN_SALES_COUNTRY_NOT_SUPPORTED_FOR_SALES_CHANNEL = 10 + CANNOT_ADD_EXISTING_FIELD = 11 + CANNOT_UPDATE_NEGATIVE_CRITERION = 12 + CANNOT_SET_NEGATIVE_KEYWORD_THEME_CONSTANT_CRITERION = 13 + INVALID_KEYWORD_THEME_CONSTANT = 14 + MISSING_KEYWORD_THEME_CONSTANT_OR_FREE_FORM_KEYWORD_THEME = 15 + CANNOT_TARGET_BOTH_PROXIMITY_AND_LOCATION_CRITERIA_FOR_SMART_CAMPAIGN = ( + 16 + ) + CANNOT_TARGET_MULTIPLE_PROXIMITY_CRITERIA_FOR_SMART_CAMPAIGN = 17 + LOCATION_NOT_LAUNCHED_FOR_LOCAL_SERVICES_CAMPAIGN = 18 + LOCATION_INVALID_FOR_LOCAL_SERVICES_CAMPAIGN = 19 + CANNOT_TARGET_COUNTRY_FOR_LOCAL_SERVICES_CAMPAIGN = 20 + LOCATION_NOT_IN_HOME_COUNTRY_FOR_LOCAL_SERVICES_CAMPAIGN = 21 + CANNOT_ADD_OR_REMOVE_LOCATION_FOR_LOCAL_SERVICES_CAMPAIGN = 22 + AT_LEAST_ONE_POSITIVE_LOCATION_REQUIRED_FOR_LOCAL_SERVICES_CAMPAIGN = 23 + AT_LEAST_ONE_LOCAL_SERVICE_ID_CRITERION_REQUIRED_FOR_LOCAL_SERVICES_CAMPAIGN = ( + 24 + ) + LOCAL_SERVICE_ID_NOT_FOUND_FOR_CATEGORY = 25 + CANNOT_ATTACH_BRAND_LIST_TO_NON_QUALIFIED_SEARCH_CAMPAIGN = 26 + CANNOT_REMOVE_ALL_LOCATIONS_DUE_TO_TOO_MANY_COUNTRY_EXCLUSIONS = 27 + INVALID_VIDEO_LINEUP_ID = 28 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/campaign_customizer_error.py b/google/ads/googleads/v24/errors/types/campaign_customizer_error.py new file mode 100644 index 000000000..8d39b1953 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/campaign_customizer_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignCustomizerErrorEnum", + }, +) + + +class CampaignCustomizerErrorEnum(proto.Message): + r"""Container for enum describing possible campaign customizer + errors. + + """ + + class CampaignCustomizerError(proto.Enum): + r"""Enum describing possible campaign customizer errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/campaign_draft_error.py b/google/ads/googleads/v24/errors/types/campaign_draft_error.py new file mode 100644 index 000000000..b5c4127eb --- /dev/null +++ b/google/ads/googleads/v24/errors/types/campaign_draft_error.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignDraftErrorEnum", + }, +) + + +class CampaignDraftErrorEnum(proto.Message): + r"""Container for enum describing possible campaign draft errors.""" + + class CampaignDraftError(proto.Enum): + r"""Enum describing possible campaign draft errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + DUPLICATE_DRAFT_NAME (2): + A draft with this name already exists for + this campaign. + INVALID_STATUS_TRANSITION_FROM_REMOVED (3): + The draft is removed and cannot be + transitioned to another status. + INVALID_STATUS_TRANSITION_FROM_PROMOTED (4): + The draft has been promoted and cannot be + transitioned to the specified status. + INVALID_STATUS_TRANSITION_FROM_PROMOTE_FAILED (5): + The draft has failed to be promoted and + cannot be transitioned to the specified status. + CUSTOMER_CANNOT_CREATE_DRAFT (6): + This customer is not allowed to create + drafts. + CAMPAIGN_CANNOT_CREATE_DRAFT (7): + This campaign is not allowed to create + drafts. + INVALID_DRAFT_CHANGE (8): + This modification cannot be made on a draft. + INVALID_STATUS_TRANSITION (9): + The draft cannot be transitioned to the + specified status from its current status. + MAX_NUMBER_OF_DRAFTS_PER_CAMPAIGN_REACHED (10): + The campaign has reached the maximum number + of drafts that can be created for a campaign + throughout its lifetime. No additional drafts + can be created for this campaign. Removed drafts + also count towards this limit. + LIST_ERRORS_FOR_PROMOTED_DRAFT_ONLY (11): + ListAsyncErrors was called without first + promoting the draft. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DUPLICATE_DRAFT_NAME = 2 + INVALID_STATUS_TRANSITION_FROM_REMOVED = 3 + INVALID_STATUS_TRANSITION_FROM_PROMOTED = 4 + INVALID_STATUS_TRANSITION_FROM_PROMOTE_FAILED = 5 + CUSTOMER_CANNOT_CREATE_DRAFT = 6 + CAMPAIGN_CANNOT_CREATE_DRAFT = 7 + INVALID_DRAFT_CHANGE = 8 + INVALID_STATUS_TRANSITION = 9 + MAX_NUMBER_OF_DRAFTS_PER_CAMPAIGN_REACHED = 10 + LIST_ERRORS_FOR_PROMOTED_DRAFT_ONLY = 11 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/campaign_error.py b/google/ads/googleads/v24/errors/types/campaign_error.py new file mode 100644 index 000000000..4dbc94303 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/campaign_error.py @@ -0,0 +1,481 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignErrorEnum", + }, +) + + +class CampaignErrorEnum(proto.Message): + r"""Container for enum describing possible campaign errors.""" + + class CampaignError(proto.Enum): + r"""Enum describing possible campaign errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CANNOT_TARGET_CONTENT_NETWORK (3): + Cannot target content network. + CANNOT_TARGET_SEARCH_NETWORK (4): + Cannot target search network. + CANNOT_TARGET_SEARCH_NETWORK_WITHOUT_GOOGLE_SEARCH (5): + Cannot cover search network without google + search network. + CANNOT_TARGET_GOOGLE_SEARCH_FOR_CPM_CAMPAIGN (6): + Cannot target Google Search network for a CPM + campaign. + CAMPAIGN_MUST_TARGET_AT_LEAST_ONE_NETWORK (7): + Must target at least one network. + CANNOT_TARGET_PARTNER_SEARCH_NETWORK (8): + Only some Google partners are allowed to + target partner search network. + CANNOT_TARGET_CONTENT_NETWORK_ONLY_WITH_CRITERIA_LEVEL_BIDDING_STRATEGY (9): + Cannot target content network only as + campaign has criteria-level bidding strategy. + CAMPAIGN_DURATION_MUST_CONTAIN_ALL_RUNNABLE_TRIALS (10): + Cannot modify the start or end date such that + the campaign duration would not contain the + durations of all runnable trials. + CANNOT_MODIFY_FOR_TRIAL_CAMPAIGN (11): + Cannot modify dates, budget or status of a + trial campaign. + DUPLICATE_CAMPAIGN_NAME (12): + Trying to modify the name of an active or + paused campaign, where the name is already + assigned to another active or paused campaign. + INCOMPATIBLE_CAMPAIGN_FIELD (13): + Two fields are in conflicting modes. + INVALID_CAMPAIGN_NAME (14): + Campaign name cannot be used. + INVALID_AD_SERVING_OPTIMIZATION_STATUS (15): + Given status is invalid. + INVALID_TRACKING_URL (16): + Error in the campaign level tracking URL. + CANNOT_SET_BOTH_TRACKING_URL_TEMPLATE_AND_TRACKING_SETTING (17): + Cannot set both tracking URL template and + tracking setting. A user has to clear legacy + tracking setting in order to add tracking URL + template. + MAX_IMPRESSIONS_NOT_IN_RANGE (18): + The maximum number of impressions for + Frequency Cap should be an integer greater than + 0. + TIME_UNIT_NOT_SUPPORTED (19): + Only the Day, Week and Month time units are + supported. + INVALID_OPERATION_IF_SERVING_STATUS_HAS_ENDED (20): + Operation not allowed on a campaign whose + serving status has ended + BUDGET_CANNOT_BE_SHARED (21): + This budget is exclusively linked to a + Campaign that is using experiments so it cannot + be shared. + CAMPAIGN_CANNOT_USE_SHARED_BUDGET (22): + Campaigns using experiments cannot use a + shared budget. + CANNOT_CHANGE_BUDGET_ON_CAMPAIGN_WITH_TRIALS (23): + A different budget cannot be assigned to a + campaign when there are running or scheduled + trials. + CAMPAIGN_LABEL_DOES_NOT_EXIST (24): + No link found between the campaign and the + label. + CAMPAIGN_LABEL_ALREADY_EXISTS (25): + The label has already been attached to the + campaign. + MISSING_SHOPPING_SETTING (26): + A ShoppingSetting was not found when creating + a shopping campaign. + INVALID_SHOPPING_SALES_COUNTRY (27): + The country in shopping setting is not an + allowed country. + ADVERTISING_CHANNEL_TYPE_NOT_AVAILABLE_FOR_ACCOUNT_TYPE (31): + The requested channel type is not available + according to the customer's account setting. + INVALID_ADVERTISING_CHANNEL_SUB_TYPE (32): + The AdvertisingChannelSubType is not a valid + subtype of the primary channel type. + AT_LEAST_ONE_CONVERSION_MUST_BE_SELECTED (33): + At least one conversion must be selected. + CANNOT_SET_AD_ROTATION_MODE (34): + Setting ad rotation mode for a campaign is + not allowed. Ad rotation mode at campaign is + deprecated. + CANNOT_MODIFY_START_DATE_IF_ALREADY_STARTED (35): + Trying to change start date on a campaign + that has started. + CANNOT_SET_DATE_TO_PAST (36): + Trying to modify a date into the past. + MISSING_HOTEL_CUSTOMER_LINK (37): + Hotel center id in the hotel setting does not + match any customer links. + INVALID_HOTEL_CUSTOMER_LINK (38): + Hotel center id in the hotel setting must + match an active customer link. + MISSING_HOTEL_SETTING (39): + Hotel setting was not found when creating a + hotel ads campaign. + CANNOT_USE_SHARED_CAMPAIGN_BUDGET_WHILE_PART_OF_CAMPAIGN_GROUP (40): + A Campaign cannot use shared campaign budgets + and be part of a campaign group. + APP_NOT_FOUND (41): + The app ID was not found. + SHOPPING_ENABLE_LOCAL_NOT_SUPPORTED_FOR_CAMPAIGN_TYPE (42): + Campaign.shopping_setting.enable_local is not supported for + the specified campaign type. + MERCHANT_NOT_ALLOWED_FOR_COMPARISON_LISTING_ADS (43): + The merchant does not support the creation of + campaigns for Shopping Comparison Listing Ads. + INSUFFICIENT_APP_INSTALLS_COUNT (44): + The App campaign for engagement cannot be + created because there aren't enough installs. + SENSITIVE_CATEGORY_APP (45): + The App campaign for engagement cannot be + created because the app is sensitive. + HEC_AGREEMENT_REQUIRED (46): + Customers with Housing, Employment, or Credit + ads must accept updated personalized ads policy + to continue creating campaigns. + NOT_COMPATIBLE_WITH_VIEW_THROUGH_CONVERSION_OPTIMIZATION (49): + The field is not compatible with view through + conversion optimization. + INVALID_EXCLUDED_PARENT_ASSET_FIELD_TYPE (48): + The field type cannot be excluded because an + active campaign-asset link of this type exists. + CANNOT_CREATE_APP_PRE_REGISTRATION_FOR_NON_ANDROID_APP (50): + The app pre-registration campaign cannot be + created for non-Android applications. + APP_NOT_AVAILABLE_TO_CREATE_APP_PRE_REGISTRATION_CAMPAIGN (51): + The campaign cannot be created since the app + is not available for pre-registration in any + country. + INCOMPATIBLE_BUDGET_TYPE (52): + The type of the Budget is not compatible with + this Campaign. + LOCAL_SERVICES_DUPLICATE_CATEGORY_BID (53): + Category bid list in the local services + campaign setting contains multiple bids for the + same category ID. + LOCAL_SERVICES_INVALID_CATEGORY_BID (54): + Category bid list in the local services + campaign setting contains a bid for an invalid + category ID. + LOCAL_SERVICES_MISSING_CATEGORY_BID (55): + Category bid list in the local services + campaign setting is missing a bid for a category + ID that must be present. + INVALID_STATUS_CHANGE (57): + The requested change in status is not + supported. + MISSING_TRAVEL_CUSTOMER_LINK (58): + Travel Campaign's travel_account_id does not match any + customer links. + INVALID_TRAVEL_CUSTOMER_LINK (59): + Travel Campaign's travel_account_id matches an existing + customer link but the customer link is not active. + INVALID_EXCLUDED_PARENT_ASSET_SET_TYPE (62): + The asset set type is invalid to be set in + excluded_parent_asset_set_types field. + ASSET_SET_NOT_A_HOTEL_PROPERTY_ASSET_SET (63): + Campaign.hotel_property_asset_set must point to an asset set + of type HOTEL_PROPERTY. + HOTEL_PROPERTY_ASSET_SET_ONLY_FOR_PERFORMANCE_MAX_FOR_TRAVEL_GOALS (64): + The hotel property asset set can only be set + on Performance Max for travel goals campaigns. + AVERAGE_DAILY_SPEND_TOO_HIGH (65): + Customer's average daily spend is too high to + enable this feature. + CANNOT_ATTACH_TO_REMOVED_CAMPAIGN_GROUP (66): + Cannot attach the campaign to a deleted + campaign group. + CANNOT_ATTACH_TO_BIDDING_STRATEGY (67): + Cannot attach the campaign to this bidding + strategy. + CANNOT_CHANGE_BUDGET_PERIOD (68): + A budget with a different period cannot be + assigned to the campaign. + NOT_ENOUGH_CONVERSIONS (71): + Customer does not have enough conversions to + enable this feature. + CANNOT_SET_MORE_THAN_ONE_CONVERSION_ACTION (72): + This campaign type can only have one + conversion action. + NOT_COMPATIBLE_WITH_BUDGET_TYPE (73): + The field is not compatible with the budget + type. + NOT_COMPATIBLE_WITH_UPLOAD_CLICKS_CONVERSION (74): + The feature is incompatible with + ConversionActionType.UPLOAD_CLICKS. + APP_ID_MUST_MATCH_CONVERSION_ACTION_APP_ID (76): + App campaign setting app ID must match + selective optimization conversion action app ID. + CONVERSION_ACTION_WITH_DOWNLOAD_CATEGORY_NOT_ALLOWED (77): + Selective optimization conversion action with + Download category is not allowed. + CONVERSION_ACTION_WITH_DOWNLOAD_CATEGORY_REQUIRED (78): + One software download for selective + optimization conversion action is required for + this campaign conversion action. + CONVERSION_TRACKING_NOT_ENABLED (79): + Conversion tracking is not enabled and is + required for this feature. + NOT_COMPATIBLE_WITH_BIDDING_STRATEGY_TYPE (80): + The field is not compatible with the bidding + strategy type. + NOT_COMPATIBLE_WITH_GOOGLE_ATTRIBUTION_CONVERSIONS (81): + Campaign is not compatible with a conversion + tracker that has Google attribution enabled. + CONVERSION_LAG_TOO_HIGH (82): + Customer level conversion lag is too high. + NOT_LINKED_ADVERTISING_PARTNER (83): + The advertiser set as an advertising partner + is not an actively linked advertiser to this + customer. + INVALID_NUMBER_OF_ADVERTISING_PARTNER_IDS (84): + Invalid number of advertising partner IDs. + CANNOT_TARGET_DISPLAY_NETWORK_WITHOUT_YOUTUBE (85): + Cannot target the display network without + also targeting YouTube. + CANNOT_LINK_TO_COMPARISON_SHOPPING_SERVICE_ACCOUNT (86): + This campaign type cannot be linked to a + Comparison Shopping Service account. + CANNOT_TARGET_NETWORK_FOR_COMPARISON_SHOPPING_SERVICE_LINKED_ACCOUNTS (87): + Standard Shopping campaigns that are linked + to a Comparison Shopping Service account cannot + target this network. + CANNOT_MODIFY_TEXT_ASSET_AUTOMATION_WITH_ENABLED_TRIAL (88): + Text asset automation settings can not be + modified when there is an active Performance Max + optimization automatically created assets + experiment. End the experiment to modify these + settings. + DYNAMIC_TEXT_ASSET_CANNOT_OPT_OUT_WITH_FINAL_URL_EXPANSION_OPT_IN (89): + Dynamic text asset cannot be opted out when + final URL expansion is opted in. + CANNOT_SET_CAMPAIGN_KEYWORD_MATCH_TYPE (90): + Can not set a campaign level match type. + CANNOT_DISABLE_BROAD_MATCH_WHEN_KEYWORD_CONVERSION_IN_PROCESS (91): + The campaign level keyword match type cannot + be switched to non-broad when keyword conversion + to broad match is in process. + CANNOT_DISABLE_BROAD_MATCH_WHEN_TARGETING_BRANDS (92): + The campaign level keyword match type cannot + be switched to non-broad when the campaign has + any attached brand list or when a brand hint + shared set is attached to the campaign. + CANNOT_ENABLE_BROAD_MATCH_FOR_BASE_CAMPAIGN_WITH_PROMOTING_TRIAL (93): + Cannot set campaign level keyword match type + to BROAD if the campaign is a base campaign with + an associated trial that is currently promoting. + CANNOT_ENABLE_BROAD_MATCH_FOR_PROMOTING_TRIAL_CAMPAIGN (94): + Cannot set campaign level keyword match type + to BROAD if the campaign is a trial currently + promoting. + REQUIRED_BUSINESS_NAME_ASSET_NOT_LINKED (95): + Performance Max campaigns with Brand + Guidelines enabled require at least one business + name to be linked as a CampaignAsset. + Performance Max campaigns for online sales with + a product feed must meet this requirement only + when there are assets that are linked to the + campaign's asset groups. + REQUIRED_LOGO_ASSET_NOT_LINKED (96): + Performance Max campaigns with Brand + Guidelines enabled require at least one square + logo to be linked as a CampaignAsset. + Performance Max campaigns for online sales with + a product feed must meet this requirement only + when there are assets that are linked to the + campaign's asset groups. + BRAND_TARGETING_OVERRIDES_NOT_SUPPORTED (97): + This campaign does not support brand + targeting overrides. Brand targeting overrides + are only supported for Performance Max campaigns + that have a product feed. + BRAND_GUIDELINES_NOT_ENABLED_FOR_CAMPAIGN (98): + Brand Guideline fields can only be set for + campaigns that have Brand Guidelines enabled. + BRAND_GUIDELINES_MAIN_AND_ACCENT_COLORS_REQUIRED (99): + When a Brand Guidelines color field is set, + both main color and accent color are required. + BRAND_GUIDELINES_COLOR_INVALID_FORMAT (100): + Brand Guidelines colors must be hex colors matching the + regular expression '#[0-9a-fA-F]{6}', for example '#abc123' + BRAND_GUIDELINES_UNSUPPORTED_FONT_FAMILY (101): + Brand Guidelines font family must be one of the supported + Google Fonts. See + Campaign.brand_guidelines.predefined_font_family for the + list of supported fonts. + BRAND_GUIDELINES_UNSUPPORTED_CHANNEL (102): + Brand Guidelines cannot be set for this + channel type. Brand Guidelines supports + Performance Max campaigns. + CANNOT_ENABLE_BRAND_GUIDELINES_FOR_TRAVEL_GOALS (103): + Brand Guidelines cannot be enabled for + Performance Max for travel goals campaigns. + CUSTOMER_NOT_ALLOWLISTED_FOR_BRAND_GUIDELINES (104): + This customer is not allowlisted for enabling + Brand Guidelines. + THIRD_PARTY_INTEGRATION_PARTNER_NOT_ALLOWED (105): + Using campaign third-party integration + partners that are not set at the customer level + is not allowed. + THIRD_PARTY_INTEGRATION_PARTNER_SHARE_COST_NOT_ALLOWED (106): + Campaign third-party integration partners are + not allowed to share cost if it is not enabled + at the customer level. + DUPLICATE_INTERACTION_TYPE (107): + Each ``previous_step_interaction_type`` can be used at most + once for the same ``previous_step_id`` + INVALID_INTERACTION_TYPE (108): + Previous step interaction type cannot happen for previous + step AdGroup type. For example, ``SKIP`` interaction type is + not valid for non-skippable formats. + VIDEO_SEQUENCE_ERROR_SEQUENCE_DEFINITION_REQUIRED (109): + Campaign video ads sequence is required for + ``VIDEO_SEQUENCE`` advertising channel sub type. + AI_MAX_MUST_BE_ENABLED (110): + This feature is only available for campaigns + with AI Max enabled. + DURATION_TOO_LONG_FOR_TOTAL_BUDGET (111): + Duration too long for total budget. + END_DATE_TIME_REQUIRED_FOR_TOTAL_BUDGET (112): + Campaigns with total budgets must have end + date/time specified. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CANNOT_TARGET_CONTENT_NETWORK = 3 + CANNOT_TARGET_SEARCH_NETWORK = 4 + CANNOT_TARGET_SEARCH_NETWORK_WITHOUT_GOOGLE_SEARCH = 5 + CANNOT_TARGET_GOOGLE_SEARCH_FOR_CPM_CAMPAIGN = 6 + CAMPAIGN_MUST_TARGET_AT_LEAST_ONE_NETWORK = 7 + CANNOT_TARGET_PARTNER_SEARCH_NETWORK = 8 + CANNOT_TARGET_CONTENT_NETWORK_ONLY_WITH_CRITERIA_LEVEL_BIDDING_STRATEGY = ( + 9 + ) + CAMPAIGN_DURATION_MUST_CONTAIN_ALL_RUNNABLE_TRIALS = 10 + CANNOT_MODIFY_FOR_TRIAL_CAMPAIGN = 11 + DUPLICATE_CAMPAIGN_NAME = 12 + INCOMPATIBLE_CAMPAIGN_FIELD = 13 + INVALID_CAMPAIGN_NAME = 14 + INVALID_AD_SERVING_OPTIMIZATION_STATUS = 15 + INVALID_TRACKING_URL = 16 + CANNOT_SET_BOTH_TRACKING_URL_TEMPLATE_AND_TRACKING_SETTING = 17 + MAX_IMPRESSIONS_NOT_IN_RANGE = 18 + TIME_UNIT_NOT_SUPPORTED = 19 + INVALID_OPERATION_IF_SERVING_STATUS_HAS_ENDED = 20 + BUDGET_CANNOT_BE_SHARED = 21 + CAMPAIGN_CANNOT_USE_SHARED_BUDGET = 22 + CANNOT_CHANGE_BUDGET_ON_CAMPAIGN_WITH_TRIALS = 23 + CAMPAIGN_LABEL_DOES_NOT_EXIST = 24 + CAMPAIGN_LABEL_ALREADY_EXISTS = 25 + MISSING_SHOPPING_SETTING = 26 + INVALID_SHOPPING_SALES_COUNTRY = 27 + ADVERTISING_CHANNEL_TYPE_NOT_AVAILABLE_FOR_ACCOUNT_TYPE = 31 + INVALID_ADVERTISING_CHANNEL_SUB_TYPE = 32 + AT_LEAST_ONE_CONVERSION_MUST_BE_SELECTED = 33 + CANNOT_SET_AD_ROTATION_MODE = 34 + CANNOT_MODIFY_START_DATE_IF_ALREADY_STARTED = 35 + CANNOT_SET_DATE_TO_PAST = 36 + MISSING_HOTEL_CUSTOMER_LINK = 37 + INVALID_HOTEL_CUSTOMER_LINK = 38 + MISSING_HOTEL_SETTING = 39 + CANNOT_USE_SHARED_CAMPAIGN_BUDGET_WHILE_PART_OF_CAMPAIGN_GROUP = 40 + APP_NOT_FOUND = 41 + SHOPPING_ENABLE_LOCAL_NOT_SUPPORTED_FOR_CAMPAIGN_TYPE = 42 + MERCHANT_NOT_ALLOWED_FOR_COMPARISON_LISTING_ADS = 43 + INSUFFICIENT_APP_INSTALLS_COUNT = 44 + SENSITIVE_CATEGORY_APP = 45 + HEC_AGREEMENT_REQUIRED = 46 + NOT_COMPATIBLE_WITH_VIEW_THROUGH_CONVERSION_OPTIMIZATION = 49 + INVALID_EXCLUDED_PARENT_ASSET_FIELD_TYPE = 48 + CANNOT_CREATE_APP_PRE_REGISTRATION_FOR_NON_ANDROID_APP = 50 + APP_NOT_AVAILABLE_TO_CREATE_APP_PRE_REGISTRATION_CAMPAIGN = 51 + INCOMPATIBLE_BUDGET_TYPE = 52 + LOCAL_SERVICES_DUPLICATE_CATEGORY_BID = 53 + LOCAL_SERVICES_INVALID_CATEGORY_BID = 54 + LOCAL_SERVICES_MISSING_CATEGORY_BID = 55 + INVALID_STATUS_CHANGE = 57 + MISSING_TRAVEL_CUSTOMER_LINK = 58 + INVALID_TRAVEL_CUSTOMER_LINK = 59 + INVALID_EXCLUDED_PARENT_ASSET_SET_TYPE = 62 + ASSET_SET_NOT_A_HOTEL_PROPERTY_ASSET_SET = 63 + HOTEL_PROPERTY_ASSET_SET_ONLY_FOR_PERFORMANCE_MAX_FOR_TRAVEL_GOALS = 64 + AVERAGE_DAILY_SPEND_TOO_HIGH = 65 + CANNOT_ATTACH_TO_REMOVED_CAMPAIGN_GROUP = 66 + CANNOT_ATTACH_TO_BIDDING_STRATEGY = 67 + CANNOT_CHANGE_BUDGET_PERIOD = 68 + NOT_ENOUGH_CONVERSIONS = 71 + CANNOT_SET_MORE_THAN_ONE_CONVERSION_ACTION = 72 + NOT_COMPATIBLE_WITH_BUDGET_TYPE = 73 + NOT_COMPATIBLE_WITH_UPLOAD_CLICKS_CONVERSION = 74 + APP_ID_MUST_MATCH_CONVERSION_ACTION_APP_ID = 76 + CONVERSION_ACTION_WITH_DOWNLOAD_CATEGORY_NOT_ALLOWED = 77 + CONVERSION_ACTION_WITH_DOWNLOAD_CATEGORY_REQUIRED = 78 + CONVERSION_TRACKING_NOT_ENABLED = 79 + NOT_COMPATIBLE_WITH_BIDDING_STRATEGY_TYPE = 80 + NOT_COMPATIBLE_WITH_GOOGLE_ATTRIBUTION_CONVERSIONS = 81 + CONVERSION_LAG_TOO_HIGH = 82 + NOT_LINKED_ADVERTISING_PARTNER = 83 + INVALID_NUMBER_OF_ADVERTISING_PARTNER_IDS = 84 + CANNOT_TARGET_DISPLAY_NETWORK_WITHOUT_YOUTUBE = 85 + CANNOT_LINK_TO_COMPARISON_SHOPPING_SERVICE_ACCOUNT = 86 + CANNOT_TARGET_NETWORK_FOR_COMPARISON_SHOPPING_SERVICE_LINKED_ACCOUNTS = ( + 87 + ) + CANNOT_MODIFY_TEXT_ASSET_AUTOMATION_WITH_ENABLED_TRIAL = 88 + DYNAMIC_TEXT_ASSET_CANNOT_OPT_OUT_WITH_FINAL_URL_EXPANSION_OPT_IN = 89 + CANNOT_SET_CAMPAIGN_KEYWORD_MATCH_TYPE = 90 + CANNOT_DISABLE_BROAD_MATCH_WHEN_KEYWORD_CONVERSION_IN_PROCESS = 91 + CANNOT_DISABLE_BROAD_MATCH_WHEN_TARGETING_BRANDS = 92 + CANNOT_ENABLE_BROAD_MATCH_FOR_BASE_CAMPAIGN_WITH_PROMOTING_TRIAL = 93 + CANNOT_ENABLE_BROAD_MATCH_FOR_PROMOTING_TRIAL_CAMPAIGN = 94 + REQUIRED_BUSINESS_NAME_ASSET_NOT_LINKED = 95 + REQUIRED_LOGO_ASSET_NOT_LINKED = 96 + BRAND_TARGETING_OVERRIDES_NOT_SUPPORTED = 97 + BRAND_GUIDELINES_NOT_ENABLED_FOR_CAMPAIGN = 98 + BRAND_GUIDELINES_MAIN_AND_ACCENT_COLORS_REQUIRED = 99 + BRAND_GUIDELINES_COLOR_INVALID_FORMAT = 100 + BRAND_GUIDELINES_UNSUPPORTED_FONT_FAMILY = 101 + BRAND_GUIDELINES_UNSUPPORTED_CHANNEL = 102 + CANNOT_ENABLE_BRAND_GUIDELINES_FOR_TRAVEL_GOALS = 103 + CUSTOMER_NOT_ALLOWLISTED_FOR_BRAND_GUIDELINES = 104 + THIRD_PARTY_INTEGRATION_PARTNER_NOT_ALLOWED = 105 + THIRD_PARTY_INTEGRATION_PARTNER_SHARE_COST_NOT_ALLOWED = 106 + DUPLICATE_INTERACTION_TYPE = 107 + INVALID_INTERACTION_TYPE = 108 + VIDEO_SEQUENCE_ERROR_SEQUENCE_DEFINITION_REQUIRED = 109 + AI_MAX_MUST_BE_ENABLED = 110 + DURATION_TOO_LONG_FOR_TOTAL_BUDGET = 111 + END_DATE_TIME_REQUIRED_FOR_TOTAL_BUDGET = 112 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/campaign_experiment_error.py b/google/ads/googleads/v24/errors/types/campaign_experiment_error.py new file mode 100644 index 000000000..16cf297e9 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/campaign_experiment_error.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignExperimentErrorEnum", + }, +) + + +class CampaignExperimentErrorEnum(proto.Message): + r"""Container for enum describing possible campaign experiment + errors. + + """ + + class CampaignExperimentError(proto.Enum): + r"""Enum describing possible campaign experiment errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + DUPLICATE_NAME (2): + An active campaign or experiment with this + name already exists. + INVALID_TRANSITION (3): + Experiment cannot be updated from the current + state to the requested target state. For + example, an experiment can only graduate if its + status is ENABLED. + CANNOT_CREATE_EXPERIMENT_WITH_SHARED_BUDGET (4): + Cannot create an experiment from a campaign + using an explicitly shared budget. + CANNOT_CREATE_EXPERIMENT_FOR_REMOVED_BASE_CAMPAIGN (5): + Cannot create an experiment for a removed + base campaign. + CANNOT_CREATE_EXPERIMENT_FOR_NON_PROPOSED_DRAFT (6): + Cannot create an experiment from a draft, + which has a status other than proposed. + CUSTOMER_CANNOT_CREATE_EXPERIMENT (7): + This customer is not allowed to create an + experiment. + CAMPAIGN_CANNOT_CREATE_EXPERIMENT (8): + This campaign is not allowed to create an + experiment. + EXPERIMENT_DURATIONS_MUST_NOT_OVERLAP (9): + Trying to set an experiment duration which + overlaps with another experiment. + EXPERIMENT_DURATION_MUST_BE_WITHIN_CAMPAIGN_DURATION (10): + All non-removed experiments must start and + end within their campaign's duration. + CANNOT_MUTATE_EXPERIMENT_DUE_TO_STATUS (11): + The experiment cannot be modified because its + status is in a terminal state, such as REMOVED. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DUPLICATE_NAME = 2 + INVALID_TRANSITION = 3 + CANNOT_CREATE_EXPERIMENT_WITH_SHARED_BUDGET = 4 + CANNOT_CREATE_EXPERIMENT_FOR_REMOVED_BASE_CAMPAIGN = 5 + CANNOT_CREATE_EXPERIMENT_FOR_NON_PROPOSED_DRAFT = 6 + CUSTOMER_CANNOT_CREATE_EXPERIMENT = 7 + CAMPAIGN_CANNOT_CREATE_EXPERIMENT = 8 + EXPERIMENT_DURATIONS_MUST_NOT_OVERLAP = 9 + EXPERIMENT_DURATION_MUST_BE_WITHIN_CAMPAIGN_DURATION = 10 + CANNOT_MUTATE_EXPERIMENT_DUE_TO_STATUS = 11 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/campaign_feed_error.py b/google/ads/googleads/v24/errors/types/campaign_feed_error.py new file mode 100644 index 000000000..737f12de2 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/campaign_feed_error.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignFeedErrorEnum", + }, +) + + +class CampaignFeedErrorEnum(proto.Message): + r"""Container for enum describing possible campaign feed errors.""" + + class CampaignFeedError(proto.Enum): + r"""Enum describing possible campaign feed errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + FEED_ALREADY_EXISTS_FOR_PLACEHOLDER_TYPE (2): + An active feed already exists for this + campaign and placeholder type. + CANNOT_CREATE_FOR_REMOVED_FEED (4): + The specified feed is removed. + CANNOT_CREATE_ALREADY_EXISTING_CAMPAIGN_FEED (5): + The CampaignFeed already exists. UPDATE + should be used to modify the existing + CampaignFeed. + CANNOT_MODIFY_REMOVED_CAMPAIGN_FEED (6): + Cannot update removed campaign feed. + INVALID_PLACEHOLDER_TYPE (7): + Invalid placeholder type. + MISSING_FEEDMAPPING_FOR_PLACEHOLDER_TYPE (8): + Feed mapping for this placeholder type does + not exist. + NO_EXISTING_LOCATION_CUSTOMER_FEED (9): + Location CampaignFeeds cannot be created + unless there is a location CustomerFeed for the + specified feed. + LEGACY_FEED_TYPE_READ_ONLY (10): + Feed is read only. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + FEED_ALREADY_EXISTS_FOR_PLACEHOLDER_TYPE = 2 + CANNOT_CREATE_FOR_REMOVED_FEED = 4 + CANNOT_CREATE_ALREADY_EXISTING_CAMPAIGN_FEED = 5 + CANNOT_MODIFY_REMOVED_CAMPAIGN_FEED = 6 + INVALID_PLACEHOLDER_TYPE = 7 + MISSING_FEEDMAPPING_FOR_PLACEHOLDER_TYPE = 8 + NO_EXISTING_LOCATION_CUSTOMER_FEED = 9 + LEGACY_FEED_TYPE_READ_ONLY = 10 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/campaign_goal_config_error.py b/google/ads/googleads/v24/errors/types/campaign_goal_config_error.py new file mode 100644 index 000000000..4f6f07c00 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/campaign_goal_config_error.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignGoalConfigErrorEnum", + }, +) + + +class CampaignGoalConfigErrorEnum(proto.Message): + r"""Container for enum describing possible campaign goal config + errors. + + """ + + class CampaignGoalConfigError(proto.Enum): + r"""Enum describing possible campaign goal config errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + GOAL_NOT_FOUND (3): + Goal is either removed or does not exist for + this account. + CAMPAIGN_NOT_FOUND (4): + Campaign is either removed or does not exist. + HIGH_LIFETIME_VALUE_PRESENT_BUT_VALUE_ABSENT (9): + If high lifetime value is present then value + should be present. + HIGH_LIFETIME_VALUE_LESS_THAN_OR_EQUAL_TO_VALUE (10): + High lifetime value should be greater than + value. + CUSTOMER_LIFECYCLE_OPTIMIZATION_CAMPAIGN_TYPE_NOT_SUPPORTED (11): + When using customer lifecycle optimization + goal, campaign type should be supported. + CUSTOMER_NOT_ALLOWLISTED_FOR_RETENTION_ONLY (12): + Customer must be allowlisted to use retention + only goal. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + GOAL_NOT_FOUND = 3 + CAMPAIGN_NOT_FOUND = 4 + HIGH_LIFETIME_VALUE_PRESENT_BUT_VALUE_ABSENT = 9 + HIGH_LIFETIME_VALUE_LESS_THAN_OR_EQUAL_TO_VALUE = 10 + CUSTOMER_LIFECYCLE_OPTIMIZATION_CAMPAIGN_TYPE_NOT_SUPPORTED = 11 + CUSTOMER_NOT_ALLOWLISTED_FOR_RETENTION_ONLY = 12 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/campaign_lifecycle_goal_error.py b/google/ads/googleads/v24/errors/types/campaign_lifecycle_goal_error.py new file mode 100644 index 000000000..b12323c1b --- /dev/null +++ b/google/ads/googleads/v24/errors/types/campaign_lifecycle_goal_error.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignLifecycleGoalErrorEnum", + }, +) + + +class CampaignLifecycleGoalErrorEnum(proto.Message): + r"""Container for enum describing possible campaign lifecycle + goal errors. + + """ + + class CampaignLifecycleGoalError(proto.Enum): + r"""Enum describing possible campaign lifecycle goal errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CAMPAIGN_MISSING (2): + Campaign is not specified. + INVALID_CAMPAIGN (3): + Cannot find the specified campaign. + CUSTOMER_ACQUISITION_INVALID_OPTIMIZATION_MODE (4): + Optimization mode is unspecified or invalid. + INCOMPATIBLE_BIDDING_STRATEGY (5): + The configured lifecycle goal setting is not compatible with + the bidding strategy the campaign is using. Specifically, + BID_HIGHER_FOR_NEW_CUSTOMER requires conversion-value based + bidding strategy type such as MAXIMIZE_CONVERSION_VALUE. + MISSING_PURCHASE_GOAL (6): + Lifecycle goals require the campaign to + optimize towards purchase conversion goal. + CUSTOMER_ACQUISITION_INVALID_HIGH_LIFETIME_VALUE (7): + CampaignLifecycleGoal.customer_acquisition_goal_settings.value_settings.high_lifetime_value + is invalid or not allowed, such as when the specified value + is smaller than 0.01, when the optimization mode is not + BID_HIGHER_FOR_NEW_CUSTOMER, or when + CampaignLifecycleGoal.customer_acquisition_goal_settings.value_settings.high_lifetime_value + is specified smaller than/without + CampaignLifecycleGoal.customer_acquisition_goal_settings.value_settings.value. + CUSTOMER_ACQUISITION_UNSUPPORTED_CAMPAIGN_TYPE (8): + Customer acquisition goal is not supported on + this campaign type. + CUSTOMER_ACQUISITION_INVALID_VALUE (9): + CampaignLifecycleGoal.customer_acquisition_goal_settings.value_settings.value + is invalid or not allowed, such as when the specified value + is smaller than 0.01, or when the optimization mode is not + BID_HIGHER_FOR_NEW_CUSTOMER. + CUSTOMER_ACQUISITION_VALUE_MISSING (10): + To use BID_HIGHER_FOR_NEW_CUSTOMER mode, either + CampaignLifecycleGoal.customer_acquisition_goal_settings.value_settings.value + or + CustomerLifecycleGoal.customer_acquisition_goal_value_settings.value + must have been specified. If a manager account is managing + your account's conversion tracking, then only the + CustomerLifecycleGoal of that manager account is used. + CUSTOMER_ACQUISITION_MISSING_EXISTING_CUSTOMER_DEFINITION (11): + In order for a campaign to adopt the customer acquisition + goal, + CustomerLifecycleGoal.lifecycle_goal_customer_definition_settings.existing_user_lists + must include active and accessible userlist with more than + 1000 members in the Search/Youtube network. If a manager + account is managing your account's conversion tracking, then + only the CustomerLifecycleGoal of that manager account is + used. Also make sure that the manager account shares + audience segments with sub-accounts with continuous audience + sharing. + CUSTOMER_ACQUISITION_MISSING_HIGH_VALUE_CUSTOMER_DEFINITION (12): + In order for a campaign to adopt the customer acquisition + goal with high lifetime value optimization, + CustomerLifecycleGoal.lifecycle_goal_customer_definition_settings.high_lifetime_value_user_lists + must include active and accessible userlist with more than + 1000 members in the Search/Youtube network. If a manager + account is managing your account's conversion tracking, then + only the CustomerLifecycleGoal of that manager account is + used. Also make sure that the manager account shares + audience segments with sub-accounts using continuous + audience sharing. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CAMPAIGN_MISSING = 2 + INVALID_CAMPAIGN = 3 + CUSTOMER_ACQUISITION_INVALID_OPTIMIZATION_MODE = 4 + INCOMPATIBLE_BIDDING_STRATEGY = 5 + MISSING_PURCHASE_GOAL = 6 + CUSTOMER_ACQUISITION_INVALID_HIGH_LIFETIME_VALUE = 7 + CUSTOMER_ACQUISITION_UNSUPPORTED_CAMPAIGN_TYPE = 8 + CUSTOMER_ACQUISITION_INVALID_VALUE = 9 + CUSTOMER_ACQUISITION_VALUE_MISSING = 10 + CUSTOMER_ACQUISITION_MISSING_EXISTING_CUSTOMER_DEFINITION = 11 + CUSTOMER_ACQUISITION_MISSING_HIGH_VALUE_CUSTOMER_DEFINITION = 12 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/campaign_shared_set_error.py b/google/ads/googleads/v24/errors/types/campaign_shared_set_error.py new file mode 100644 index 000000000..845b4d8bc --- /dev/null +++ b/google/ads/googleads/v24/errors/types/campaign_shared_set_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignSharedSetErrorEnum", + }, +) + + +class CampaignSharedSetErrorEnum(proto.Message): + r"""Container for enum describing possible campaign shared set + errors. + + """ + + class CampaignSharedSetError(proto.Enum): + r"""Enum describing possible campaign shared set errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + SHARED_SET_ACCESS_DENIED (2): + The shared set belongs to another customer + and permission isn't granted. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SHARED_SET_ACCESS_DENIED = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/change_event_error.py b/google/ads/googleads/v24/errors/types/change_event_error.py new file mode 100644 index 000000000..3b3dfbf1b --- /dev/null +++ b/google/ads/googleads/v24/errors/types/change_event_error.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ChangeEventErrorEnum", + }, +) + + +class ChangeEventErrorEnum(proto.Message): + r"""Container for enum describing possible change event errors.""" + + class ChangeEventError(proto.Enum): + r"""Enum describing possible change event errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + START_DATE_TOO_OLD (2): + The requested start date is too old. It + cannot be older than 30 days. + CHANGE_DATE_RANGE_INFINITE (3): + The change_event search request must specify a finite range + filter on change_date_time. + CHANGE_DATE_RANGE_NEGATIVE (4): + The change event search request has specified + invalid date time filters that can never + logically produce any valid results (for + example, start time after end time). + LIMIT_NOT_SPECIFIED (5): + The change_event search request must specify a LIMIT. + INVALID_LIMIT_CLAUSE (6): + The LIMIT specified by change_event request should be less + than or equal to 10K. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + START_DATE_TOO_OLD = 2 + CHANGE_DATE_RANGE_INFINITE = 3 + CHANGE_DATE_RANGE_NEGATIVE = 4 + LIMIT_NOT_SPECIFIED = 5 + INVALID_LIMIT_CLAUSE = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/change_status_error.py b/google/ads/googleads/v24/errors/types/change_status_error.py new file mode 100644 index 000000000..fa457ee55 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/change_status_error.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ChangeStatusErrorEnum", + }, +) + + +class ChangeStatusErrorEnum(proto.Message): + r"""Container for enum describing possible change status errors.""" + + class ChangeStatusError(proto.Enum): + r"""Enum describing possible change status errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + START_DATE_TOO_OLD (3): + The requested start date is too old. + CHANGE_DATE_RANGE_INFINITE (4): + The change_status search request must specify a finite range + filter on last_change_date_time. + CHANGE_DATE_RANGE_NEGATIVE (5): + The change status search request has + specified invalid date time filters that can + never logically produce any valid results (for + example, start time after end time). + LIMIT_NOT_SPECIFIED (6): + The change_status search request must specify a LIMIT. + INVALID_LIMIT_CLAUSE (7): + The LIMIT specified by change_status request should be less + than or equal to 10K. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + START_DATE_TOO_OLD = 3 + CHANGE_DATE_RANGE_INFINITE = 4 + CHANGE_DATE_RANGE_NEGATIVE = 5 + LIMIT_NOT_SPECIFIED = 6 + INVALID_LIMIT_CLAUSE = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/click_view_error.py b/google/ads/googleads/v24/errors/types/click_view_error.py new file mode 100644 index 000000000..4b559a582 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/click_view_error.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ClickViewErrorEnum", + }, +) + + +class ClickViewErrorEnum(proto.Message): + r"""Container for enum describing possible click view errors.""" + + class ClickViewError(proto.Enum): + r"""Enum describing possible click view errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + EXPECTED_FILTER_ON_A_SINGLE_DAY (2): + Missing filter on a single day. + DATE_TOO_OLD (3): + The requested date is too old. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EXPECTED_FILTER_ON_A_SINGLE_DAY = 2 + DATE_TOO_OLD = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/collection_size_error.py b/google/ads/googleads/v24/errors/types/collection_size_error.py new file mode 100644 index 000000000..581dbc3fa --- /dev/null +++ b/google/ads/googleads/v24/errors/types/collection_size_error.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CollectionSizeErrorEnum", + }, +) + + +class CollectionSizeErrorEnum(proto.Message): + r"""Container for enum describing possible collection size + errors. + + """ + + class CollectionSizeError(proto.Enum): + r"""Enum describing possible collection size errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + TOO_FEW (2): + Too few. + TOO_MANY (3): + Too many. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + TOO_FEW = 2 + TOO_MANY = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/content_creator_insights_error.py b/google/ads/googleads/v24/errors/types/content_creator_insights_error.py new file mode 100644 index 000000000..f8f36735b --- /dev/null +++ b/google/ads/googleads/v24/errors/types/content_creator_insights_error.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ContentCreatorInsightsErrorEnum", + }, +) + + +class ContentCreatorInsightsErrorEnum(proto.Message): + r"""Container for enum describing possible errors returned from + the ContentCreatorInsightsService. + + """ + + class ContentCreatorInsightsError(proto.Enum): + r"""Enum describing possible errors from + ContentCreatorInsightsService. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + DIMENSION_INCOMPATIBLE_WITH_AUDIENCE_COMBINATIONS (2): + The dimension cannot be used in audience + combinations. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DIMENSION_INCOMPATIBLE_WITH_AUDIENCE_COMBINATIONS = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/context_error.py b/google/ads/googleads/v24/errors/types/context_error.py new file mode 100644 index 000000000..94a15a8c7 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/context_error.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ContextErrorEnum", + }, +) + + +class ContextErrorEnum(proto.Message): + r"""Container for enum describing possible context errors.""" + + class ContextError(proto.Enum): + r"""Enum describing possible context errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + OPERATION_NOT_PERMITTED_FOR_CONTEXT (2): + The operation is not allowed for the given + context. + OPERATION_NOT_PERMITTED_FOR_REMOVED_RESOURCE (3): + The operation is not allowed for removed + resources. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + OPERATION_NOT_PERMITTED_FOR_CONTEXT = 2 + OPERATION_NOT_PERMITTED_FOR_REMOVED_RESOURCE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/conversion_action_error.py b/google/ads/googleads/v24/errors/types/conversion_action_error.py new file mode 100644 index 000000000..22cad77f9 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/conversion_action_error.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionActionErrorEnum", + }, +) + + +class ConversionActionErrorEnum(proto.Message): + r"""Container for enum describing possible conversion action + errors. + + """ + + class ConversionActionError(proto.Enum): + r"""Enum describing possible conversion action errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + DUPLICATE_NAME (2): + The specified conversion action name already + exists. + DUPLICATE_APP_ID (3): + Another conversion action with the specified + app id already exists. + TWO_CONVERSION_ACTIONS_BIDDING_ON_SAME_APP_DOWNLOAD (4): + Android first open action conflicts with + Google play codeless download action tracking + the same app. + BIDDING_ON_SAME_APP_DOWNLOAD_AS_GLOBAL_ACTION (5): + Android first open action conflicts with + Google play codeless download action tracking + the same app. + DATA_DRIVEN_MODEL_WAS_NEVER_GENERATED (6): + The attribution model cannot be set to DATA_DRIVEN because a + data-driven model has never been generated. + DATA_DRIVEN_MODEL_EXPIRED (7): + The attribution model cannot be set to DATA_DRIVEN because + the data-driven model is expired. + DATA_DRIVEN_MODEL_STALE (8): + The attribution model cannot be set to DATA_DRIVEN because + the data-driven model is stale. + DATA_DRIVEN_MODEL_UNKNOWN (9): + The attribution model cannot be set to DATA_DRIVEN because + the data-driven model is unavailable or the conversion + action was newly added. + CREATION_NOT_SUPPORTED (10): + Creation of this conversion action type isn't + supported by Google Ads API. + UPDATE_NOT_SUPPORTED (11): + Update of this conversion action isn't + supported by Google Ads API. + CANNOT_SET_RULE_BASED_ATTRIBUTION_MODELS (12): + Rule-based attribution models are deprecated + and not allowed to be set by conversion action. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DUPLICATE_NAME = 2 + DUPLICATE_APP_ID = 3 + TWO_CONVERSION_ACTIONS_BIDDING_ON_SAME_APP_DOWNLOAD = 4 + BIDDING_ON_SAME_APP_DOWNLOAD_AS_GLOBAL_ACTION = 5 + DATA_DRIVEN_MODEL_WAS_NEVER_GENERATED = 6 + DATA_DRIVEN_MODEL_EXPIRED = 7 + DATA_DRIVEN_MODEL_STALE = 8 + DATA_DRIVEN_MODEL_UNKNOWN = 9 + CREATION_NOT_SUPPORTED = 10 + UPDATE_NOT_SUPPORTED = 11 + CANNOT_SET_RULE_BASED_ATTRIBUTION_MODELS = 12 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/conversion_adjustment_upload_error.py b/google/ads/googleads/v24/errors/types/conversion_adjustment_upload_error.py new file mode 100644 index 000000000..fd1e05aaa --- /dev/null +++ b/google/ads/googleads/v24/errors/types/conversion_adjustment_upload_error.py @@ -0,0 +1,184 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionAdjustmentUploadErrorEnum", + }, +) + + +class ConversionAdjustmentUploadErrorEnum(proto.Message): + r"""Container for enum describing possible conversion adjustment + upload errors. + + """ + + class ConversionAdjustmentUploadError(proto.Enum): + r"""Enum describing possible conversion adjustment upload errors. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + TOO_RECENT_CONVERSION_ACTION (2): + Can't import events to a conversion action + that was just created. Try importing again in 6 + hours. + CONVERSION_ALREADY_RETRACTED (4): + The conversion was already retracted. This + adjustment was not processed. + CONVERSION_NOT_FOUND (5): + The conversion for this conversion action and + conversion identifier can't be found. Make sure + your conversion identifiers are associated with + the correct conversion action and try again. + CONVERSION_EXPIRED (6): + Adjustment can't be made to a conversion that + occurred more than 54 days ago. + ADJUSTMENT_PRECEDES_CONVERSION (7): + Adjustment has an ``adjustment_date_time`` that occurred + before the associated conversion. Make sure your + ``adjustment_date_time`` is correct and try again. + MORE_RECENT_RESTATEMENT_FOUND (8): + More recent adjustment ``adjustment_date_time`` has already + been reported for the associated conversion. Make sure your + adjustment ``adjustment_date_time`` is correct and try + again. + TOO_RECENT_CONVERSION (9): + Adjustment can't be recorded because the + conversion occurred too recently. Try adjusting + a conversion that occurred at least 24 hours + ago. + CANNOT_RESTATE_CONVERSION_ACTION_THAT_ALWAYS_USES_DEFAULT_CONVERSION_VALUE (10): + Can't make an adjustment to a conversion that + is set up to use the default value. Check your + conversion action value setting and try again. + TOO_MANY_ADJUSTMENTS_IN_REQUEST (11): + Try uploading fewer than 2001 adjustments in + a single API request. + TOO_MANY_ADJUSTMENTS (12): + The conversion has already been adjusted the + maximum number of times. Make sure you're only + making necessary adjustment to existing + conversion. + RESTATEMENT_ALREADY_EXISTS (13): + The conversion has prior a restatement with the same + ``adjustment_date_time``. Make sure your adjustment has the + correct and unique ``adjustment_date_time`` and try again. + DUPLICATE_ADJUSTMENT_IN_REQUEST (14): + Imported adjustment has a duplicate conversion adjustment + with same ``adjustment_date_time``. Make sure your + adjustment has the correct ``adjustment_date_time`` and try + again. + CUSTOMER_NOT_ACCEPTED_CUSTOMER_DATA_TERMS (15): + Make sure you agree to the customer data + processing terms in conversion settings and try + again. + CONVERSION_ACTION_NOT_ELIGIBLE_FOR_ENHANCEMENT (16): + Can't use enhanced conversions with the + specified conversion action. + INVALID_USER_IDENTIFIER (17): + Make sure you hash user provided data using + SHA-256 and ensure you are normalizing according + to the guidelines. + UNSUPPORTED_USER_IDENTIFIER (18): + Use user provided data such as emails or + phone numbers hashed using SHA-256 and try + again. + GCLID_DATE_TIME_PAIR_AND_ORDER_ID_BOTH_SET (20): + Cannot set both gclid_date_time_pair and order_id. Use only + 1 type and try again. + CONVERSION_ALREADY_ENHANCED (21): + Conversion already has enhancements with the + same Order ID and conversion action. Make sure + your data is correctly configured and try again. + DUPLICATE_ENHANCEMENT_IN_REQUEST (22): + Multiple enhancements have the same + conversion action and Order ID. Make sure your + data is correctly configured and try again. + CUSTOMER_DATA_POLICY_PROHIBITS_ENHANCEMENT (23): + Enhanced conversions can't be used for this + account because of Google customer data + policies. Contact your Google representative. + MISSING_ORDER_ID_FOR_WEBPAGE (24): + Adjustment for website conversion requires + Order ID (ie, transaction ID). Make sure your + website tags capture Order IDs and you send the + same Order IDs with your adjustment. + ORDER_ID_CONTAINS_PII (25): + Can't use adjustment with Order IDs + containing personally-identifiable information + (PII). + INVALID_JOB_ID (26): + The provided job id in the request is not within the allowed + range. A job ID must be a positive integer in the range [1, + 2^31). + NO_CONVERSION_ACTION_FOUND (27): + The conversion action specified in the + adjustment request cannot be found. Make sure + it's available in this account. + INVALID_CONVERSION_ACTION_TYPE (28): + The type of the conversion action specified in the + adjustment request isn't supported for uploading + adjustments. A conversion adjustment of type ``RETRACTION`` + or ``RESTATEMENT`` is only permitted for conversion actions + of type ``SALESFORCE``, ``UPLOAD_CLICK`` or ``WEBPAGE``. A + conversion adjustment of type ``ENHANCEMENT`` is only + permitted for conversion actions of type ``WEBPAGE``. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + TOO_RECENT_CONVERSION_ACTION = 2 + CONVERSION_ALREADY_RETRACTED = 4 + CONVERSION_NOT_FOUND = 5 + CONVERSION_EXPIRED = 6 + ADJUSTMENT_PRECEDES_CONVERSION = 7 + MORE_RECENT_RESTATEMENT_FOUND = 8 + TOO_RECENT_CONVERSION = 9 + CANNOT_RESTATE_CONVERSION_ACTION_THAT_ALWAYS_USES_DEFAULT_CONVERSION_VALUE = ( + 10 + ) + TOO_MANY_ADJUSTMENTS_IN_REQUEST = 11 + TOO_MANY_ADJUSTMENTS = 12 + RESTATEMENT_ALREADY_EXISTS = 13 + DUPLICATE_ADJUSTMENT_IN_REQUEST = 14 + CUSTOMER_NOT_ACCEPTED_CUSTOMER_DATA_TERMS = 15 + CONVERSION_ACTION_NOT_ELIGIBLE_FOR_ENHANCEMENT = 16 + INVALID_USER_IDENTIFIER = 17 + UNSUPPORTED_USER_IDENTIFIER = 18 + GCLID_DATE_TIME_PAIR_AND_ORDER_ID_BOTH_SET = 20 + CONVERSION_ALREADY_ENHANCED = 21 + DUPLICATE_ENHANCEMENT_IN_REQUEST = 22 + CUSTOMER_DATA_POLICY_PROHIBITS_ENHANCEMENT = 23 + MISSING_ORDER_ID_FOR_WEBPAGE = 24 + ORDER_ID_CONTAINS_PII = 25 + INVALID_JOB_ID = 26 + NO_CONVERSION_ACTION_FOUND = 27 + INVALID_CONVERSION_ACTION_TYPE = 28 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/conversion_custom_variable_error.py b/google/ads/googleads/v24/errors/types/conversion_custom_variable_error.py new file mode 100644 index 000000000..a444cf5e2 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/conversion_custom_variable_error.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionCustomVariableErrorEnum", + }, +) + + +class ConversionCustomVariableErrorEnum(proto.Message): + r"""Container for enum describing possible conversion custom + variable errors. + + """ + + class ConversionCustomVariableError(proto.Enum): + r"""Enum describing possible conversion custom variable errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + DUPLICATE_NAME (2): + A conversion custom variable with the + specified name already exists. + DUPLICATE_TAG (3): + A conversion custom variable with the + specified tag already exists. + RESERVED_TAG (4): + A conversion custom variable with the + specified tag is reserved for other uses. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DUPLICATE_NAME = 2 + DUPLICATE_TAG = 3 + RESERVED_TAG = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/conversion_goal_campaign_config_error.py b/google/ads/googleads/v24/errors/types/conversion_goal_campaign_config_error.py new file mode 100644 index 000000000..c490e318e --- /dev/null +++ b/google/ads/googleads/v24/errors/types/conversion_goal_campaign_config_error.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionGoalCampaignConfigErrorEnum", + }, +) + + +class ConversionGoalCampaignConfigErrorEnum(proto.Message): + r"""Container for enum describing possible conversion goal + campaign config errors. + + """ + + class ConversionGoalCampaignConfigError(proto.Enum): + r"""Enum describing possible conversion goal campaign config + errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CANNOT_USE_CAMPAIGN_GOAL_FOR_SEARCH_ADS_360_MANAGED_CAMPAIGN (2): + Campaign is managed by Search Ads 360 but + uses Unified Goal. + CUSTOM_GOAL_DOES_NOT_BELONG_TO_GOOGLE_ADS_CONVERSION_CUSTOMER (3): + The campaign is using a custom goal that does + not belong to its Google Ads conversion customer + (conversion tracking customer). + CAMPAIGN_CANNOT_USE_UNIFIED_GOALS (4): + The campaign is not allowed to use unified + goals. + EMPTY_CONVERSION_GOALS (5): + The campaign is using campaign override goals + but has no goals configured. + STORE_SALE_STORE_VISIT_CANNOT_BE_BOTH_INCLUDED (6): + STORE_SALE and STORE_VISIT conversion types cannot be both + included in campaign level goal. + PERFORMANCE_MAX_CAMPAIGN_CANNOT_USE_CUSTOM_GOAL_WITH_STORE_SALES (7): + Performance Max campaign is not allowed to + use custom goal with store sales conversion + type. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CANNOT_USE_CAMPAIGN_GOAL_FOR_SEARCH_ADS_360_MANAGED_CAMPAIGN = 2 + CUSTOM_GOAL_DOES_NOT_BELONG_TO_GOOGLE_ADS_CONVERSION_CUSTOMER = 3 + CAMPAIGN_CANNOT_USE_UNIFIED_GOALS = 4 + EMPTY_CONVERSION_GOALS = 5 + STORE_SALE_STORE_VISIT_CANNOT_BE_BOTH_INCLUDED = 6 + PERFORMANCE_MAX_CAMPAIGN_CANNOT_USE_CUSTOM_GOAL_WITH_STORE_SALES = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/conversion_upload_error.py b/google/ads/googleads/v24/errors/types/conversion_upload_error.py new file mode 100644 index 000000000..68b79213c --- /dev/null +++ b/google/ads/googleads/v24/errors/types/conversion_upload_error.py @@ -0,0 +1,295 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionUploadErrorEnum", + }, +) + + +class ConversionUploadErrorEnum(proto.Message): + r"""Container for enum describing possible conversion upload + errors. + + """ + + class ConversionUploadError(proto.Enum): + r"""Enum describing possible conversion upload errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + TOO_MANY_CONVERSIONS_IN_REQUEST (2): + Upload fewer than 2001 events in a single + request. + UNPARSEABLE_GCLID (3): + The imported gclid could not be decoded. + CONVERSION_PRECEDES_EVENT (42): + The imported event has a ``conversion_date_time`` that + precedes the click. Make sure your ``conversion_date_time`` + is correct and try again. + EXPIRED_EVENT (43): + The imported event can't be recorded because + its click occurred before this conversion's + click-through window. Make sure you import the + most recent data. + TOO_RECENT_EVENT (44): + The click associated with the given + identifier or iOS URL parameter occurred less + than 6 hours ago. Retry after 6 hours have + passed. + EVENT_NOT_FOUND (45): + The imported event could not be attributed to + a click. This may be because the event did not + come from a Google Ads campaign. + UNAUTHORIZED_CUSTOMER (8): + The click ID or call is associated with an + Ads account you don't have access to. Make sure + you import conversions for accounts managed by + your manager account. + TOO_RECENT_CONVERSION_ACTION (10): + Can't import events to a conversion action + that was just created. Try importing again in 6 + hours. + CONVERSION_TRACKING_NOT_ENABLED_AT_IMPRESSION_TIME (11): + At the time of the click, conversion tracking + was not enabled in the effective conversion + account of the click's Google Ads account. + EXTERNAL_ATTRIBUTION_DATA_SET_FOR_NON_EXTERNALLY_ATTRIBUTED_CONVERSION_ACTION (12): + The imported event includes external + attribution data, but the conversion action + isn't set up to use an external attribution + model. Make sure the conversion action is + correctly configured and try again. + EXTERNAL_ATTRIBUTION_DATA_NOT_SET_FOR_EXTERNALLY_ATTRIBUTED_CONVERSION_ACTION (13): + The conversion action is set up to use an + external attribution model, but the imported + event is missing data. Make sure imported events + include the external attribution credit and all + necessary fields. + ORDER_ID_NOT_PERMITTED_FOR_EXTERNALLY_ATTRIBUTED_CONVERSION_ACTION (14): + Order IDs can't be used for a conversion + measured with an external attribution model. + Make sure the conversion is correctly configured + and imported events include only necessary data + and try again. + ORDER_ID_ALREADY_IN_USE (15): + The imported event includes an order ID that + was previously recorded, so the event was not + processed. + DUPLICATE_ORDER_ID (16): + Imported events include multiple conversions + with the same order ID and were not processed. + Make sure order IDs are unique and try again. + TOO_RECENT_CALL (17): + Can't import calls that occurred less than 6 + hours ago. Try uploading again in 6 hours. + EXPIRED_CALL (18): + The call can't be recorded because it + occurred before this conversion action's + lookback window. Make sure your import is + configured to get the most recent data. + CALL_NOT_FOUND (19): + The call or click leading to the imported + event can't be found. Make sure your data source + is set up to include correct identifiers. + CONVERSION_PRECEDES_CALL (20): + The call has a ``conversion_date_time`` that precedes the + associated click. Make sure your ``conversion_date_time`` is + correct. + CONVERSION_TRACKING_NOT_ENABLED_AT_CALL_TIME (21): + At the time of the imported call, conversion + tracking was not enabled in the effective + conversion account of the click's Google Ads + account. + UNPARSEABLE_CALLERS_PHONE_NUMBER (22): + Make sure phone numbers are formatted as + E.164 (+16502531234), International (+64 3-331 + 6005), or US national number (6502531234). + CLICK_CONVERSION_ALREADY_EXISTS (23): + The imported event has the same click and + ``conversion_date_time`` as an existing conversion. Use a + unique ``conversion_date_time`` or order ID for each unique + event and try again. + CALL_CONVERSION_ALREADY_EXISTS (24): + The imported call has the same ``conversion_date_time`` as + an existing conversion. Make sure your + ``conversion_date_time`` correctly configured and try again. + DUPLICATE_CLICK_CONVERSION_IN_REQUEST (25): + Multiple events have the same click and + ``conversion_date_time``. Make sure your + ``conversion_date_time`` is correctly configured and try + again. + DUPLICATE_CALL_CONVERSION_IN_REQUEST (26): + Multiple events have the same call and + ``conversion_date_time``. Make sure your + ``conversion_date_time`` is correctly configured and try + again. + CUSTOM_VARIABLE_NOT_ENABLED (28): + Enable the custom variable in your conversion + settings and try again. + CUSTOM_VARIABLE_VALUE_CONTAINS_PII (29): + Can't import events with custom variables + containing personally-identifiable information + (PII). Remove these variables and try again. + INVALID_CUSTOMER_FOR_CLICK (30): + The click from the imported event is + associated with a different Google Ads account. + Make sure you're importing to the correct + account. + INVALID_CUSTOMER_FOR_CALL (31): + The click from the call is associated with a different + Google Ads account. Make sure you're importing to the + correct account. Query + conversion_tracking_setting.google_ads_conversion_customer + on Customer to identify the correct account. + CONVERSION_NOT_COMPLIANT_WITH_ATT_POLICY (32): + The connversion can't be imported because the + conversion source didn't comply with Apple App + Transparency Tracking (ATT) policies or because + the customer didn't consent to tracking. + CLICK_NOT_FOUND (33): + The email address or phone number for this + event can't be matched to a click. This may be + because it didn't come from a Google Ads + campaign, and you can safely ignore this + warning. If this includes more imported events + than is expected, you may need to check your + setup. + INVALID_USER_IDENTIFIER (34): + Make sure you hash user provided data using + SHA-256 and ensure you are normalizing according + to the guidelines. + EXTERNALLY_ATTRIBUTED_CONVERSION_ACTION_NOT_PERMITTED_WITH_USER_IDENTIFIER (35): + User provided data can't be used with + external attribution models. Use a different + attribution model or omit user identifiers and + try again. + UNSUPPORTED_USER_IDENTIFIER (36): + The provided user identifiers are not + supported. Use only hashed email or phone number + and try again. + GBRAID_WBRAID_BOTH_SET (38): + Can't use both gbraid and wbraid parameters. + Use only 1 and try again. + UNPARSEABLE_WBRAID (39): + Can't parse event import data. Check if your + wbraid parameter was not modified and try again. + UNPARSEABLE_GBRAID (40): + Can't parse event import data. Check if your + gbraid parameter was not modified and try again. + ONE_PER_CLICK_CONVERSION_ACTION_NOT_PERMITTED_WITH_BRAID (46): + Conversion actions that use one-per-click + counting can't be used with gbraid or wbraid + parameters. + CUSTOMER_DATA_POLICY_PROHIBITS_ENHANCED_CONVERSIONS (47): + Enhanced conversions can't be used for this + account because of Google customer data + policies. Contact your Google representative. + CUSTOMER_NOT_ACCEPTED_CUSTOMER_DATA_TERMS (48): + Make sure you agree to the customer data processing terms in + conversion settings and try again. You can check your + setting by querying + conversion_tracking_setting.accepted_customer_data_terms on + Customer. + ORDER_ID_CONTAINS_PII (49): + Can't import events with order IDs containing + personally-identifiable information (PII). + CUSTOMER_NOT_ENABLED_ENHANCED_CONVERSIONS_FOR_LEADS (50): + Make sure you've turned on enhanced conversions for leads in + conversion settings and try again. You can check your + setting by querying + conversion_tracking_setting.enhanced_conversions_for_leads_enabled + on Customer. + INVALID_JOB_ID (52): + The provided job id in the request is not within the allowed + range. A job ID must be a positive integer in the range [1, + 2^31). + NO_CONVERSION_ACTION_FOUND (53): + The conversion action specified in the upload + request cannot be found. Make sure it's + available in this account. + INVALID_CONVERSION_ACTION_TYPE (54): + The conversion action specified in the upload + request isn't set up for uploading conversions. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + TOO_MANY_CONVERSIONS_IN_REQUEST = 2 + UNPARSEABLE_GCLID = 3 + CONVERSION_PRECEDES_EVENT = 42 + EXPIRED_EVENT = 43 + TOO_RECENT_EVENT = 44 + EVENT_NOT_FOUND = 45 + UNAUTHORIZED_CUSTOMER = 8 + TOO_RECENT_CONVERSION_ACTION = 10 + CONVERSION_TRACKING_NOT_ENABLED_AT_IMPRESSION_TIME = 11 + EXTERNAL_ATTRIBUTION_DATA_SET_FOR_NON_EXTERNALLY_ATTRIBUTED_CONVERSION_ACTION = ( + 12 + ) + EXTERNAL_ATTRIBUTION_DATA_NOT_SET_FOR_EXTERNALLY_ATTRIBUTED_CONVERSION_ACTION = ( + 13 + ) + ORDER_ID_NOT_PERMITTED_FOR_EXTERNALLY_ATTRIBUTED_CONVERSION_ACTION = 14 + ORDER_ID_ALREADY_IN_USE = 15 + DUPLICATE_ORDER_ID = 16 + TOO_RECENT_CALL = 17 + EXPIRED_CALL = 18 + CALL_NOT_FOUND = 19 + CONVERSION_PRECEDES_CALL = 20 + CONVERSION_TRACKING_NOT_ENABLED_AT_CALL_TIME = 21 + UNPARSEABLE_CALLERS_PHONE_NUMBER = 22 + CLICK_CONVERSION_ALREADY_EXISTS = 23 + CALL_CONVERSION_ALREADY_EXISTS = 24 + DUPLICATE_CLICK_CONVERSION_IN_REQUEST = 25 + DUPLICATE_CALL_CONVERSION_IN_REQUEST = 26 + CUSTOM_VARIABLE_NOT_ENABLED = 28 + CUSTOM_VARIABLE_VALUE_CONTAINS_PII = 29 + INVALID_CUSTOMER_FOR_CLICK = 30 + INVALID_CUSTOMER_FOR_CALL = 31 + CONVERSION_NOT_COMPLIANT_WITH_ATT_POLICY = 32 + CLICK_NOT_FOUND = 33 + INVALID_USER_IDENTIFIER = 34 + EXTERNALLY_ATTRIBUTED_CONVERSION_ACTION_NOT_PERMITTED_WITH_USER_IDENTIFIER = ( + 35 + ) + UNSUPPORTED_USER_IDENTIFIER = 36 + GBRAID_WBRAID_BOTH_SET = 38 + UNPARSEABLE_WBRAID = 39 + UNPARSEABLE_GBRAID = 40 + ONE_PER_CLICK_CONVERSION_ACTION_NOT_PERMITTED_WITH_BRAID = 46 + CUSTOMER_DATA_POLICY_PROHIBITS_ENHANCED_CONVERSIONS = 47 + CUSTOMER_NOT_ACCEPTED_CUSTOMER_DATA_TERMS = 48 + ORDER_ID_CONTAINS_PII = 49 + CUSTOMER_NOT_ENABLED_ENHANCED_CONVERSIONS_FOR_LEADS = 50 + INVALID_JOB_ID = 52 + NO_CONVERSION_ACTION_FOUND = 53 + INVALID_CONVERSION_ACTION_TYPE = 54 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/conversion_value_rule_error.py b/google/ads/googleads/v24/errors/types/conversion_value_rule_error.py new file mode 100644 index 000000000..52c70431b --- /dev/null +++ b/google/ads/googleads/v24/errors/types/conversion_value_rule_error.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionValueRuleErrorEnum", + }, +) + + +class ConversionValueRuleErrorEnum(proto.Message): + r"""Container for enum describing possible conversion value rule + errors. + + """ + + class ConversionValueRuleError(proto.Enum): + r"""Enum describing possible conversion value rule errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_GEO_TARGET_CONSTANT (2): + The value rule's geo location condition + contains invalid geo target constant(s), for + example, there's no matching geo target. + CONFLICTING_INCLUDED_AND_EXCLUDED_GEO_TARGET (3): + The value rule's geo location condition + contains conflicting included and excluded geo + targets. Specifically, some of the excluded geo + target(s) are the same as or contain some of the + included geo target(s). For example, the geo + location condition includes California but + excludes U.S. + CONFLICTING_CONDITIONS (4): + User specified conflicting conditions for two + value rules in the same value rule set. + CANNOT_REMOVE_IF_INCLUDED_IN_VALUE_RULE_SET (5): + The value rule cannot be removed because it's + still included in some value rule set. + CONDITION_NOT_ALLOWED (6): + The value rule contains a condition that's + not allowed by the value rule set including this + value rule. + FIELD_MUST_BE_UNSET (7): + The value rule contains a field that should + be unset. + CANNOT_PAUSE_UNLESS_VALUE_RULE_SET_IS_PAUSED (8): + Pausing the value rule requires pausing the + value rule set because the value rule is (one + of) the last enabled in the value rule set. + UNTARGETABLE_GEO_TARGET (9): + The value rule's geo location condition + contains untargetable geo target constant(s). + INVALID_AUDIENCE_USER_LIST (10): + The value rule's audience condition contains + invalid user list(s). In another word, there's + no matching user list. + INACCESSIBLE_USER_LIST (11): + The value rule's audience condition contains + inaccessible user list(s). + INVALID_AUDIENCE_USER_INTEREST (12): + The value rule's audience condition contains invalid + user_interest(s). This might be because there is no matching + user interest, or the user interest is not visible. + CANNOT_ADD_RULE_WITH_STATUS_REMOVED (13): + When a value rule is created, it shouldn't + have REMOVED status. + NO_DAY_OF_WEEK_SELECTED (14): + The value rule's itinerary condition contains + invalid travel start day, it contains no day of + week. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_GEO_TARGET_CONSTANT = 2 + CONFLICTING_INCLUDED_AND_EXCLUDED_GEO_TARGET = 3 + CONFLICTING_CONDITIONS = 4 + CANNOT_REMOVE_IF_INCLUDED_IN_VALUE_RULE_SET = 5 + CONDITION_NOT_ALLOWED = 6 + FIELD_MUST_BE_UNSET = 7 + CANNOT_PAUSE_UNLESS_VALUE_RULE_SET_IS_PAUSED = 8 + UNTARGETABLE_GEO_TARGET = 9 + INVALID_AUDIENCE_USER_LIST = 10 + INACCESSIBLE_USER_LIST = 11 + INVALID_AUDIENCE_USER_INTEREST = 12 + CANNOT_ADD_RULE_WITH_STATUS_REMOVED = 13 + NO_DAY_OF_WEEK_SELECTED = 14 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/conversion_value_rule_set_error.py b/google/ads/googleads/v24/errors/types/conversion_value_rule_set_error.py new file mode 100644 index 000000000..41f321f9a --- /dev/null +++ b/google/ads/googleads/v24/errors/types/conversion_value_rule_set_error.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionValueRuleSetErrorEnum", + }, +) + + +class ConversionValueRuleSetErrorEnum(proto.Message): + r"""Container for enum describing possible conversion value rule + set errors. + + """ + + class ConversionValueRuleSetError(proto.Enum): + r"""Enum describing possible conversion value rule set errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CONFLICTING_VALUE_RULE_CONDITIONS (2): + Two value rules in this value rule set + contain conflicting conditions. + INVALID_VALUE_RULE (3): + This value rule set includes a value rule + that cannot be found, has been permanently + removed or belongs to a different customer. + DIMENSIONS_UPDATE_ONLY_ALLOW_APPEND (4): + An error that's thrown when a mutate + operation is trying to replace/remove some + existing elements in the dimensions field. In + other words, ADD op is always fine and UPDATE op + is fine if it's only appending new elements into + dimensions list. + CONDITION_TYPE_NOT_ALLOWED (5): + An error that's thrown when a mutate is + adding new value rule(s) into a value rule set + and the added value rule(s) include conditions + that are not specified in the dimensions of the + value rule set. + DUPLICATE_DIMENSIONS (6): + The dimensions field contains duplicate + elements. + INVALID_CAMPAIGN_ID (7): + This value rule set is attached to an invalid + campaign id. Either a campaign with this + campaign id doesn't exist or it belongs to a + different customer. + CANNOT_PAUSE_UNLESS_ALL_VALUE_RULES_ARE_PAUSED (8): + When a mutate request tries to pause a value + rule set, the enabled value rules in this set + must be paused in the same command, or this + error will be thrown. + SHOULD_PAUSE_WHEN_ALL_VALUE_RULES_ARE_PAUSED (9): + When a mutate request tries to pause all the + value rules in a value rule set, the value rule + set must be paused, or this error will be + thrown. + VALUE_RULES_NOT_SUPPORTED_FOR_CAMPAIGN_TYPE (10): + This value rule set is attached to a campaign + that does not support value rules. Currently, + campaign level value rule sets can only be + created on Search, or Display campaigns. + INELIGIBLE_CONVERSION_ACTION_CATEGORIES (11): + To add a value rule set that applies on Store + Visits/Store Sales conversion action categories, + the customer must have valid Store Visits/ Store + Sales conversion actions. + DIMENSION_NO_CONDITION_USED_WITH_OTHER_DIMENSIONS (12): + If NO_CONDITION is used as a dimension of a value rule set, + it must be the only dimension. + DIMENSION_NO_CONDITION_NOT_ALLOWED (13): + Dimension NO_CONDITION can only be used by Store + Visits/Store Sales value rule set. + UNSUPPORTED_CONVERSION_ACTION_CATEGORIES (14): + Value rule sets defined on the specified conversion action + categories are not supported. The list of conversion action + categories must be an empty list, only STORE_VISIT, or only + STORE_SALE. + DIMENSION_NOT_SUPPORTED_FOR_CAMPAIGN_TYPE (15): + Dimension ITINERARY can only be used on campaigns with an + advertising channel type of PERFORMANCE_MAX or HOTEL. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CONFLICTING_VALUE_RULE_CONDITIONS = 2 + INVALID_VALUE_RULE = 3 + DIMENSIONS_UPDATE_ONLY_ALLOW_APPEND = 4 + CONDITION_TYPE_NOT_ALLOWED = 5 + DUPLICATE_DIMENSIONS = 6 + INVALID_CAMPAIGN_ID = 7 + CANNOT_PAUSE_UNLESS_ALL_VALUE_RULES_ARE_PAUSED = 8 + SHOULD_PAUSE_WHEN_ALL_VALUE_RULES_ARE_PAUSED = 9 + VALUE_RULES_NOT_SUPPORTED_FOR_CAMPAIGN_TYPE = 10 + INELIGIBLE_CONVERSION_ACTION_CATEGORIES = 11 + DIMENSION_NO_CONDITION_USED_WITH_OTHER_DIMENSIONS = 12 + DIMENSION_NO_CONDITION_NOT_ALLOWED = 13 + UNSUPPORTED_CONVERSION_ACTION_CATEGORIES = 14 + DIMENSION_NOT_SUPPORTED_FOR_CAMPAIGN_TYPE = 15 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/country_code_error.py b/google/ads/googleads/v24/errors/types/country_code_error.py new file mode 100644 index 000000000..bd70cd246 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/country_code_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CountryCodeErrorEnum", + }, +) + + +class CountryCodeErrorEnum(proto.Message): + r"""Container for enum describing country code errors.""" + + class CountryCodeError(proto.Enum): + r"""Enum describing country code errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_COUNTRY_CODE (2): + The country code is invalid. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_COUNTRY_CODE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/criterion_error.py b/google/ads/googleads/v24/errors/types/criterion_error.py new file mode 100644 index 000000000..7ae04f730 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/criterion_error.py @@ -0,0 +1,707 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CriterionErrorEnum", + }, +) + + +class CriterionErrorEnum(proto.Message): + r"""Container for enum describing possible criterion errors.""" + + class CriterionError(proto.Enum): + r"""Enum describing possible criterion errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CONCRETE_TYPE_REQUIRED (2): + Concrete type of criterion is required for + CREATE and UPDATE operations. + INVALID_EXCLUDED_CATEGORY (3): + The category requested for exclusion is + invalid. + INVALID_KEYWORD_TEXT (4): + Invalid keyword criteria text. + KEYWORD_TEXT_TOO_LONG (5): + Keyword text should be less than 80 chars. + KEYWORD_HAS_TOO_MANY_WORDS (6): + Keyword text has too many words. + KEYWORD_HAS_INVALID_CHARS (7): + Keyword text has invalid characters or + symbols. + INVALID_PLACEMENT_URL (8): + Invalid placement URL. + INVALID_USER_LIST (9): + Invalid user list criterion. + INVALID_USER_INTEREST (10): + Invalid user interest criterion. + INVALID_FORMAT_FOR_PLACEMENT_URL (11): + Placement URL has wrong format. + PLACEMENT_URL_IS_TOO_LONG (12): + Placement URL is too long. + PLACEMENT_URL_HAS_ILLEGAL_CHAR (13): + Indicates the URL contains an illegal + character. + PLACEMENT_URL_HAS_MULTIPLE_SITES_IN_LINE (14): + Indicates the URL contains multiple comma + separated URLs. + PLACEMENT_IS_NOT_AVAILABLE_FOR_TARGETING_OR_EXCLUSION (15): + Indicates the domain is blocked. + INVALID_TOPIC_PATH (16): + Invalid topic path. + INVALID_YOUTUBE_CHANNEL_ID (17): + The YouTube Channel Id is invalid. + INVALID_YOUTUBE_VIDEO_ID (18): + The YouTube Video Id is invalid. + YOUTUBE_VERTICAL_CHANNEL_DEPRECATED (19): + Indicates the placement is a YouTube vertical + channel, which is no longer supported. + YOUTUBE_DEMOGRAPHIC_CHANNEL_DEPRECATED (20): + Indicates the placement is a YouTube + demographic channel, which is no longer + supported. + YOUTUBE_URL_UNSUPPORTED (21): + YouTube urls are not supported in Placement + criterion. Use YouTubeChannel and YouTubeVideo + criterion instead. + CANNOT_EXCLUDE_CRITERIA_TYPE (22): + Criteria type can not be excluded by the + customer, like AOL account type cannot target + site type criteria. + CANNOT_ADD_CRITERIA_TYPE (23): + Criteria type can not be targeted. + CANNOT_EXCLUDE_SIMILAR_USER_LIST (26): + Not allowed to exclude similar user list. + CANNOT_ADD_CLOSED_USER_LIST (27): + Not allowed to target a closed user list. + CANNOT_ADD_DISPLAY_ONLY_LISTS_TO_SEARCH_ONLY_CAMPAIGNS (28): + Not allowed to add display only UserLists to + search only campaigns. + CANNOT_ADD_DISPLAY_ONLY_LISTS_TO_SEARCH_CAMPAIGNS (29): + Not allowed to add display only UserLists to + search plus campaigns. + CANNOT_ADD_DISPLAY_ONLY_LISTS_TO_SHOPPING_CAMPAIGNS (30): + Not allowed to add display only UserLists to + shopping campaigns. + CANNOT_ADD_USER_INTERESTS_TO_SEARCH_CAMPAIGNS (31): + Not allowed to add User interests to search + only campaigns. + CANNOT_SET_BIDS_ON_CRITERION_TYPE_IN_SEARCH_CAMPAIGNS (32): + Not allowed to set bids for this criterion + type in search campaigns + CANNOT_ADD_URLS_TO_CRITERION_TYPE_FOR_CAMPAIGN_TYPE (33): + Final URLs, URL Templates and + CustomParameters cannot be set for the criterion + types of Gender, AgeRange, UserList, Placement, + MobileApp, and MobileAppCategory in search + campaigns and shopping campaigns. + INVALID_COMBINED_AUDIENCE (122): + Invalid combined audience criterion. + INVALID_CUSTOM_AFFINITY (96): + Invalid custom affinity criterion. + INVALID_CUSTOM_INTENT (97): + Invalid custom intent criterion. + INVALID_CUSTOM_AUDIENCE (121): + Invalid custom audience criterion. + INVALID_IP_ADDRESS (34): + IP address is not valid. + INVALID_IP_FORMAT (35): + IP format is not valid. + INVALID_MOBILE_APP (36): + Mobile application is not valid. + INVALID_MOBILE_APP_CATEGORY (37): + Mobile application category is not valid. + INVALID_CRITERION_ID (38): + The CriterionId does not exist or is of the + incorrect type. + CANNOT_TARGET_CRITERION (39): + The Criterion is not allowed to be targeted. + CANNOT_TARGET_OBSOLETE_CRITERION (40): + The criterion is not allowed to be targeted + as it is deprecated. + CRITERION_ID_AND_TYPE_MISMATCH (41): + The CriterionId is not valid for the type. + INVALID_PROXIMITY_RADIUS (42): + Distance for the radius for the proximity + criterion is invalid. + INVALID_PROXIMITY_RADIUS_UNITS (43): + Units for the distance for the radius for the + proximity criterion is invalid. + INVALID_STREETADDRESS_LENGTH (44): + Street address in the address is not valid. + INVALID_CITYNAME_LENGTH (45): + City name in the address is not valid. + INVALID_REGIONCODE_LENGTH (46): + Region code in the address is not valid. + INVALID_REGIONNAME_LENGTH (47): + Region name in the address is not valid. + INVALID_POSTALCODE_LENGTH (48): + Postal code in the address is not valid. + INVALID_COUNTRY_CODE (49): + Country code in the address is not valid. + INVALID_LATITUDE (50): + Latitude for the GeoPoint is not valid. + INVALID_LONGITUDE (51): + Longitude for the GeoPoint is not valid. + PROXIMITY_GEOPOINT_AND_ADDRESS_BOTH_CANNOT_BE_NULL (52): + The Proximity input is not valid. Both + address and geoPoint cannot be null. + INVALID_PROXIMITY_ADDRESS (53): + The Proximity address cannot be geocoded to a + valid lat/long. + INVALID_USER_DOMAIN_NAME (54): + User domain name is not valid. + CRITERION_PARAMETER_TOO_LONG (55): + Length of serialized criterion parameter + exceeded size limit. + AD_SCHEDULE_TIME_INTERVALS_OVERLAP (56): + Time interval in the AdSchedule overlaps with + another AdSchedule. + AD_SCHEDULE_INTERVAL_CANNOT_SPAN_MULTIPLE_DAYS (57): + AdSchedule time interval cannot span multiple + days. + AD_SCHEDULE_INVALID_TIME_INTERVAL (58): + AdSchedule time interval specified is + invalid, endTime cannot be earlier than + startTime. + AD_SCHEDULE_EXCEEDED_INTERVALS_PER_DAY_LIMIT (59): + The number of AdSchedule entries in a day + exceeds the limit. + AD_SCHEDULE_CRITERION_ID_MISMATCHING_FIELDS (60): + CriteriaId does not match the interval of the + AdSchedule specified. + CANNOT_BID_MODIFY_CRITERION_TYPE (61): + Cannot set bid modifier for this criterion + type. + CANNOT_BID_MODIFY_CRITERION_CAMPAIGN_OPTED_OUT (62): + Cannot bid modify criterion, since it is + opted out of the campaign. + CANNOT_BID_MODIFY_NEGATIVE_CRITERION (63): + Cannot set bid modifier for a negative + criterion. + BID_MODIFIER_ALREADY_EXISTS (64): + Bid Modifier already exists. Use SET + operation to update. + FEED_ID_NOT_ALLOWED (65): + Feed Id is not allowed in these Location + Groups. + ACCOUNT_INELIGIBLE_FOR_CRITERIA_TYPE (66): + The account may not use the requested + criteria type. For example, some accounts are + restricted to keywords only. + CRITERIA_TYPE_INVALID_FOR_BIDDING_STRATEGY (67): + The requested criteria type cannot be used + with campaign or ad group bidding strategy. + CANNOT_EXCLUDE_CRITERION (68): + The Criterion is not allowed to be excluded. + CANNOT_REMOVE_CRITERION (69): + The criterion is not allowed to be removed. + For example, we cannot remove any of the device + criterion. + INVALID_PRODUCT_BIDDING_CATEGORY (76): + Bidding categories do not form a valid path + in the Shopping bidding category taxonomy. + MISSING_SHOPPING_SETTING (77): + ShoppingSetting must be added to the campaign + before ProductScope criteria can be added. + INVALID_MATCHING_FUNCTION (78): + Matching function is invalid. + LOCATION_FILTER_NOT_ALLOWED (79): + Filter parameters not allowed for location + groups targeting. + INVALID_FEED_FOR_LOCATION_FILTER (98): + Feed not found, or the feed is not an enabled + location feed. + LOCATION_FILTER_INVALID (80): + Given location filter parameter is invalid + for location groups targeting. + CANNOT_SET_GEO_TARGET_CONSTANTS_WITH_FEED_ITEM_SETS (123): + Cannot set geo target constants and feed item + sets at the same time. + CANNOT_SET_BOTH_ASSET_SET_AND_FEED (140): + Cannot set both assetset and feed at the same + time. + CANNOT_SET_FEED_OR_FEED_ITEM_SETS_FOR_CUSTOMER (142): + Cannot set feed or feed item sets for + Customer. + CANNOT_SET_ASSET_SET_FIELD_FOR_CUSTOMER (150): + Cannot set AssetSet criteria for customer. + CANNOT_SET_GEO_TARGET_CONSTANTS_WITH_ASSET_SETS (143): + Cannot set geo target constants and asset + sets at the same time. + CANNOT_SET_ASSET_SETS_WITH_FEED_ITEM_SETS (144): + Cannot set asset sets and feed item sets at + the same time. + INVALID_LOCATION_GROUP_ASSET_SET (141): + The location group asset set id is invalid + INVALID_LOCATION_GROUP_RADIUS (124): + The location group radius is in the range but + not at the valid increment. + INVALID_LOCATION_GROUP_RADIUS_UNIT (125): + The location group radius unit is invalid. + CANNOT_ATTACH_CRITERIA_AT_CAMPAIGN_AND_ADGROUP (81): + Criteria type cannot be associated with a + campaign and its ad group(s) simultaneously. + HOTEL_LENGTH_OF_STAY_OVERLAPS_WITH_EXISTING_CRITERION (82): + Range represented by hotel length of stay's + min nights and max nights overlaps with an + existing criterion. + HOTEL_ADVANCE_BOOKING_WINDOW_OVERLAPS_WITH_EXISTING_CRITERION (83): + Range represented by hotel advance booking + window's min days and max days overlaps with an + existing criterion. + FIELD_INCOMPATIBLE_WITH_NEGATIVE_TARGETING (84): + The field is not allowed to be set when the + negative field is set to true, for example, we + don't allow bids in negative ad group or + campaign criteria. + INVALID_WEBPAGE_CONDITION (85): + The combination of operand and operator in + webpage condition is invalid. + INVALID_WEBPAGE_CONDITION_URL (86): + The URL of webpage condition is invalid. + WEBPAGE_CONDITION_URL_CANNOT_BE_EMPTY (87): + The URL of webpage condition cannot be empty + or contain white space. + WEBPAGE_CONDITION_URL_UNSUPPORTED_PROTOCOL (88): + The URL of webpage condition contains an + unsupported protocol. + WEBPAGE_CONDITION_URL_CANNOT_BE_IP_ADDRESS (89): + The URL of webpage condition cannot be an IP + address. + WEBPAGE_CONDITION_URL_DOMAIN_NOT_CONSISTENT_WITH_CAMPAIGN_SETTING (90): + The domain of the URL is not consistent with + the domain in campaign setting. + WEBPAGE_CONDITION_URL_CANNOT_BE_PUBLIC_SUFFIX (91): + The URL of webpage condition cannot be a + public suffix itself. + WEBPAGE_CONDITION_URL_INVALID_PUBLIC_SUFFIX (92): + The URL of webpage condition has an invalid + public suffix. + WEBPAGE_CONDITION_URL_VALUE_TRACK_VALUE_NOT_SUPPORTED (93): + Value track parameter is not supported in + webpage condition URL. + WEBPAGE_CRITERION_URL_EQUALS_CAN_HAVE_ONLY_ONE_CONDITION (94): + Only one URL-EQUALS webpage condition is + allowed in a webpage criterion and it cannot be + combined with other conditions. + WEBPAGE_CRITERION_NOT_SUPPORTED_ON_NON_DSA_AD_GROUP (95): + A webpage criterion cannot be added to a + non-DSA ad group. + CANNOT_TARGET_USER_LIST_FOR_SMART_DISPLAY_CAMPAIGNS (99): + Cannot add positive user list criteria in + Smart Display campaigns. + CANNOT_TARGET_PLACEMENTS_FOR_SEARCH_CAMPAIGNS (126): + Cannot add positive placement criterion types + in search campaigns. + LISTING_SCOPE_TOO_MANY_DIMENSION_TYPES (100): + Listing scope contains too many dimension + types. + LISTING_SCOPE_TOO_MANY_IN_OPERATORS (101): + Listing scope has too many IN operators. + LISTING_SCOPE_IN_OPERATOR_NOT_SUPPORTED (102): + Listing scope contains IN operator on an + unsupported dimension type. + DUPLICATE_LISTING_DIMENSION_TYPE (103): + There are dimensions with duplicate dimension + type. + DUPLICATE_LISTING_DIMENSION_VALUE (104): + There are dimensions with duplicate dimension + value. + CANNOT_SET_BIDS_ON_LISTING_GROUP_SUBDIVISION (105): + Listing group SUBDIVISION nodes cannot have + bids. + LISTING_GROUP_ERROR_IN_ANOTHER_OPERATION (169): + Product group operation is invalid because + another operation targeting the same AdGroupId + is failing. + INVALID_LISTING_GROUP_HIERARCHY (106): + Ad group is invalid due to the listing groups + it contains. + LISTING_GROUP_TREE_WAS_INVALID_BEFORE_MUTATION (170): + Tree was invalid before the mutation. + LISTING_GROUP_UNIT_CANNOT_HAVE_CHILDREN (107): + Listing group unit cannot have children. + LISTING_GROUP_SUBDIVISION_REQUIRES_OTHERS_CASE (108): + Subdivided listing groups must have an + "others" case. + LISTING_GROUP_REQUIRES_SAME_DIMENSION_TYPE_AS_SIBLINGS (109): + Dimension type of listing group must be the + same as that of its siblings. + LISTING_GROUP_ALREADY_EXISTS (110): + Listing group cannot be added to the ad group + because it already exists. + LISTING_GROUP_DOES_NOT_EXIST (111): + Listing group referenced in the operation was + not found in the ad group. + LISTING_GROUP_CANNOT_BE_REMOVED (112): + Recursive removal failed because listing + group subdivision is being created or modified + in this request. + INVALID_LISTING_GROUP_TYPE (113): + Listing group type is not allowed for + specified ad group criterion type. + LISTING_GROUP_ADD_MAY_ONLY_USE_TEMP_ID (114): + Listing group in an ADD operation specifies a + non temporary criterion id. + LISTING_SCOPE_TOO_LONG (115): + The combined length of dimension values of + the Listing scope criterion is too long. + LISTING_SCOPE_TOO_MANY_DIMENSIONS (116): + Listing scope contains too many dimensions. + LISTING_GROUP_TOO_LONG (117): + The combined length of dimension values of + the Listing group criterion is too long. + LISTING_GROUP_TREE_TOO_DEEP (118): + Listing group tree is too deep. + INVALID_LISTING_DIMENSION (119): + Listing dimension is invalid (for example, + dimension contains illegal value, dimension type + is represented with wrong class, etc). Listing + dimension value can not contain "==" or "&+". + INVALID_LISTING_DIMENSION_TYPE (120): + Listing dimension type is either invalid for campaigns of + this type or cannot be used in the current context. + BIDDING_CATEGORY_Lx and PRODUCT_TYPE_Lx dimensions must be + used in ascending order of their levels: L1, L2, L3, L4, + L5... The levels must be specified sequentially and start + from L1. Furthermore, an "others" Listing group cannot be + subdivided with a dimension of the same type but of a higher + level ("others" BIDDING_CATEGORY_L3 can be subdivided with + BRAND but not with BIDDING_CATEGORY_L4). + ADVERTISER_NOT_ON_ALLOWLIST_FOR_COMBINED_AUDIENCE_ON_DISPLAY (127): + Customer is not on allowlist for composite + audience in display campaigns. + CANNOT_TARGET_REMOVED_COMBINED_AUDIENCE (128): + Cannot target on a removed combined audience. + INVALID_COMBINED_AUDIENCE_ID (129): + Combined audience ID is invalid. + CANNOT_TARGET_REMOVED_CUSTOM_AUDIENCE (130): + Can not target removed combined audience. + HOTEL_CHECK_IN_DATE_RANGE_OVERLAPS_WITH_EXISTING_CRITERION (131): + Range represented by hotel check-in date's + start date and end date overlaps with an + existing criterion. + HOTEL_CHECK_IN_DATE_RANGE_START_DATE_TOO_EARLY (132): + Start date is earlier than earliest allowed + value of yesterday UTC. + HOTEL_CHECK_IN_DATE_RANGE_END_DATE_TOO_LATE (133): + End date later is than latest allowed day of + 330 days in the future UTC. + HOTEL_CHECK_IN_DATE_RANGE_REVERSED (134): + Start date is after end date. + BROAD_MATCH_MODIFIER_KEYWORD_NOT_ALLOWED (135): + Broad match modifier (BMM) keywords can no + longer be created. See + https://ads-developers.googleblog.com/2021/06/broad-match-modifier-upcoming-changes.html. + ONE_AUDIENCE_ALLOWED_PER_ASSET_GROUP (136): + Only one audience is allowed in an asset + group. + AUDIENCE_NOT_ELIGIBLE_FOR_CAMPAIGN_TYPE (137): + Audience is not supported for the specified + campaign type. + AUDIENCE_NOT_ALLOWED_TO_ATTACH_WHEN_AUDIENCE_GROUPED_SET_TO_FALSE (138): + Audience is not allowed to attach when use_audience_grouped + bit is set to false. + CANNOT_TARGET_CUSTOMER_MATCH_USER_LIST (139): + Targeting is not allowed for Customer Match + lists as per Customer Match policy. See + https://support.google.com/google-ads/answer/6299717. + NEGATIVE_KEYWORD_SHARED_SET_DOES_NOT_EXIST (145): + Cannot create a negative keyword list + criterion with a shared set that does not exist. + CANNOT_ADD_REMOVED_NEGATIVE_KEYWORD_SHARED_SET (146): + Cannot create a negative keyword list with + deleted shared set. + CANNOT_HAVE_MULTIPLE_NEGATIVE_KEYWORD_LIST_PER_ACCOUNT (147): + Can only have one Negative Keyword List per + account. + CUSTOMER_CANNOT_ADD_CRITERION_OF_THIS_TYPE (149): + Only allowlisted customers can add criteria + of this type. + CANNOT_TARGET_SIMILAR_USER_LIST (151): + Targeting for Similar audiences is not + supported, since this feature has been + deprecated. See + https://support.google.com/google-ads/answer/12463119 + to learn more. + CANNOT_ADD_AUDIENCE_SEGMENT_CRITERION_WHEN_AUDIENCE_GROUPED_IS_SET (152): + Audience segment criteria cannot be added when + use_audience_grouped bit is set. + ONE_AUDIENCE_ALLOWED_PER_AD_GROUP (153): + Only one audience is allowed in an ad group. + INVALID_DETAILED_DEMOGRAPHIC (154): + Invalid detailed demographics criterion. + CANNOT_RECOGNIZE_BRAND (155): + The brand criteria has a brand input that is + not recognized as a valid brand. + BRAND_SHARED_SET_DOES_NOT_EXIST (156): + The brand_list.shared_set_id references a shared set that + does not exist. + CANNOT_ADD_REMOVED_BRAND_SHARED_SET (157): + Cannot create a brand list with deleted + shared set. + ONLY_EXCLUSION_BRAND_LIST_ALLOWED_FOR_CAMPAIGN_TYPE (158): + Brand list can only be negatively targeted + for the campaign type. + CANNOT_TARGET_ONLY_UNDETERMINED (165): + The combination of demographic criteria would + result in only targeting the "undetermined" + segment, which is prohibited. + LOCATION_TARGETING_NOT_ELIGIBLE_FOR_RESTRICTED_CAMPAIGN (166): + Cannot positively target locations outside of + restricted area for campaign. + ONLY_INCLUSION_BRAND_LIST_ALLOWED_FOR_AD_GROUPS (171): + Ad group level brand list criteria only + support inclusionary targeting. Negative + targeting at this level is not supported. + CANNOT_ADD_REMOVED_PLACEMENT_LIST_SHARED_SET (172): + Cannot create a placement list with deleted + shared set. + PLACEMENT_LIST_SHARED_SET_DOES_NOT_EXIST (173): + The placement_list.shared_set_id references a shared set + that does not exist. + AI_MAX_MUST_BE_ENABLED (174): + This feature is only available for AI Max + campaigns. + NOT_AVAILABLE_FOR_AI_MAX_CAMPAIGNS (175): + This feature is not available for AI Max + campaigns. + MISSING_EU_POLITICAL_ADVERTISING_SELF_DECLARATION (176): + The operation failed because the campaign is + missing the self-declaration on political + advertising status in the EU. + INVALID_CAMPAIGN_TYPE_FOR_THIRD_PARTY_PARTNER_DATA_LIST (177): + Targeting this UserList is not allowed for + this campaign type. + CANNOT_ADD_USER_LIST_PENDING_PRIVACY_REVIEW (178): + The user list cannot be used while it is + pending privacy review. + VERTICAL_ADS_ITEM_GROUP_RULE_LIST_DOES_NOT_EXIST (179): + The referenced Vertical Ads item group rule + list shared set does not exist. + CANNOT_ADD_REMOVED_VERTICAL_ADS_ITEM_GROUP_RULE_LIST_SHARED_SET (180): + Cannot add Vertical Ads Item Group Rule List + with deleted shared set. + VERTICAL_ADS_ITEM_GROUP_RULE_LIST_NOT_SUPPORTED_FOR_CAMPAIGNS_WITHOUT_ENABLED_TRAVEL_FEED (181): + Vertical Ads Item Group Rule List is not + supported for campaigns that do not have an + active travel feed. + VERTICAL_ADS_ITEM_GROUP_RULE_LIST_NOT_SUPPORTED_FOR_CAMPAIGNS_WITHOUT_AI_MAX (182): + Vertical Ads Item Group Rule List is not + supported for campaigns that do not have AI max + enabled. + VERTICAL_ADS_ITEM_GROUP_RULE_NOT_SUPPORTED_FOR_THE_VERTICAL_TYPE (183): + The dimension of the Vertical Ads Item Group + Rule criterion is not supported for the shared + set vertical type. + RETAIL_FILTER_EXPRESSION_DOES_NOT_EXIST (184): + A RetailTag references a + RetailFilterExpression name that does not exist. + RETAIL_FILTER_TAGS_REFERRING_TO_EXPRESSION (185): + A RetailFilterExpression cannot be removed as + it is still referenced by Tags. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CONCRETE_TYPE_REQUIRED = 2 + INVALID_EXCLUDED_CATEGORY = 3 + INVALID_KEYWORD_TEXT = 4 + KEYWORD_TEXT_TOO_LONG = 5 + KEYWORD_HAS_TOO_MANY_WORDS = 6 + KEYWORD_HAS_INVALID_CHARS = 7 + INVALID_PLACEMENT_URL = 8 + INVALID_USER_LIST = 9 + INVALID_USER_INTEREST = 10 + INVALID_FORMAT_FOR_PLACEMENT_URL = 11 + PLACEMENT_URL_IS_TOO_LONG = 12 + PLACEMENT_URL_HAS_ILLEGAL_CHAR = 13 + PLACEMENT_URL_HAS_MULTIPLE_SITES_IN_LINE = 14 + PLACEMENT_IS_NOT_AVAILABLE_FOR_TARGETING_OR_EXCLUSION = 15 + INVALID_TOPIC_PATH = 16 + INVALID_YOUTUBE_CHANNEL_ID = 17 + INVALID_YOUTUBE_VIDEO_ID = 18 + YOUTUBE_VERTICAL_CHANNEL_DEPRECATED = 19 + YOUTUBE_DEMOGRAPHIC_CHANNEL_DEPRECATED = 20 + YOUTUBE_URL_UNSUPPORTED = 21 + CANNOT_EXCLUDE_CRITERIA_TYPE = 22 + CANNOT_ADD_CRITERIA_TYPE = 23 + CANNOT_EXCLUDE_SIMILAR_USER_LIST = 26 + CANNOT_ADD_CLOSED_USER_LIST = 27 + CANNOT_ADD_DISPLAY_ONLY_LISTS_TO_SEARCH_ONLY_CAMPAIGNS = 28 + CANNOT_ADD_DISPLAY_ONLY_LISTS_TO_SEARCH_CAMPAIGNS = 29 + CANNOT_ADD_DISPLAY_ONLY_LISTS_TO_SHOPPING_CAMPAIGNS = 30 + CANNOT_ADD_USER_INTERESTS_TO_SEARCH_CAMPAIGNS = 31 + CANNOT_SET_BIDS_ON_CRITERION_TYPE_IN_SEARCH_CAMPAIGNS = 32 + CANNOT_ADD_URLS_TO_CRITERION_TYPE_FOR_CAMPAIGN_TYPE = 33 + INVALID_COMBINED_AUDIENCE = 122 + INVALID_CUSTOM_AFFINITY = 96 + INVALID_CUSTOM_INTENT = 97 + INVALID_CUSTOM_AUDIENCE = 121 + INVALID_IP_ADDRESS = 34 + INVALID_IP_FORMAT = 35 + INVALID_MOBILE_APP = 36 + INVALID_MOBILE_APP_CATEGORY = 37 + INVALID_CRITERION_ID = 38 + CANNOT_TARGET_CRITERION = 39 + CANNOT_TARGET_OBSOLETE_CRITERION = 40 + CRITERION_ID_AND_TYPE_MISMATCH = 41 + INVALID_PROXIMITY_RADIUS = 42 + INVALID_PROXIMITY_RADIUS_UNITS = 43 + INVALID_STREETADDRESS_LENGTH = 44 + INVALID_CITYNAME_LENGTH = 45 + INVALID_REGIONCODE_LENGTH = 46 + INVALID_REGIONNAME_LENGTH = 47 + INVALID_POSTALCODE_LENGTH = 48 + INVALID_COUNTRY_CODE = 49 + INVALID_LATITUDE = 50 + INVALID_LONGITUDE = 51 + PROXIMITY_GEOPOINT_AND_ADDRESS_BOTH_CANNOT_BE_NULL = 52 + INVALID_PROXIMITY_ADDRESS = 53 + INVALID_USER_DOMAIN_NAME = 54 + CRITERION_PARAMETER_TOO_LONG = 55 + AD_SCHEDULE_TIME_INTERVALS_OVERLAP = 56 + AD_SCHEDULE_INTERVAL_CANNOT_SPAN_MULTIPLE_DAYS = 57 + AD_SCHEDULE_INVALID_TIME_INTERVAL = 58 + AD_SCHEDULE_EXCEEDED_INTERVALS_PER_DAY_LIMIT = 59 + AD_SCHEDULE_CRITERION_ID_MISMATCHING_FIELDS = 60 + CANNOT_BID_MODIFY_CRITERION_TYPE = 61 + CANNOT_BID_MODIFY_CRITERION_CAMPAIGN_OPTED_OUT = 62 + CANNOT_BID_MODIFY_NEGATIVE_CRITERION = 63 + BID_MODIFIER_ALREADY_EXISTS = 64 + FEED_ID_NOT_ALLOWED = 65 + ACCOUNT_INELIGIBLE_FOR_CRITERIA_TYPE = 66 + CRITERIA_TYPE_INVALID_FOR_BIDDING_STRATEGY = 67 + CANNOT_EXCLUDE_CRITERION = 68 + CANNOT_REMOVE_CRITERION = 69 + INVALID_PRODUCT_BIDDING_CATEGORY = 76 + MISSING_SHOPPING_SETTING = 77 + INVALID_MATCHING_FUNCTION = 78 + LOCATION_FILTER_NOT_ALLOWED = 79 + INVALID_FEED_FOR_LOCATION_FILTER = 98 + LOCATION_FILTER_INVALID = 80 + CANNOT_SET_GEO_TARGET_CONSTANTS_WITH_FEED_ITEM_SETS = 123 + CANNOT_SET_BOTH_ASSET_SET_AND_FEED = 140 + CANNOT_SET_FEED_OR_FEED_ITEM_SETS_FOR_CUSTOMER = 142 + CANNOT_SET_ASSET_SET_FIELD_FOR_CUSTOMER = 150 + CANNOT_SET_GEO_TARGET_CONSTANTS_WITH_ASSET_SETS = 143 + CANNOT_SET_ASSET_SETS_WITH_FEED_ITEM_SETS = 144 + INVALID_LOCATION_GROUP_ASSET_SET = 141 + INVALID_LOCATION_GROUP_RADIUS = 124 + INVALID_LOCATION_GROUP_RADIUS_UNIT = 125 + CANNOT_ATTACH_CRITERIA_AT_CAMPAIGN_AND_ADGROUP = 81 + HOTEL_LENGTH_OF_STAY_OVERLAPS_WITH_EXISTING_CRITERION = 82 + HOTEL_ADVANCE_BOOKING_WINDOW_OVERLAPS_WITH_EXISTING_CRITERION = 83 + FIELD_INCOMPATIBLE_WITH_NEGATIVE_TARGETING = 84 + INVALID_WEBPAGE_CONDITION = 85 + INVALID_WEBPAGE_CONDITION_URL = 86 + WEBPAGE_CONDITION_URL_CANNOT_BE_EMPTY = 87 + WEBPAGE_CONDITION_URL_UNSUPPORTED_PROTOCOL = 88 + WEBPAGE_CONDITION_URL_CANNOT_BE_IP_ADDRESS = 89 + WEBPAGE_CONDITION_URL_DOMAIN_NOT_CONSISTENT_WITH_CAMPAIGN_SETTING = 90 + WEBPAGE_CONDITION_URL_CANNOT_BE_PUBLIC_SUFFIX = 91 + WEBPAGE_CONDITION_URL_INVALID_PUBLIC_SUFFIX = 92 + WEBPAGE_CONDITION_URL_VALUE_TRACK_VALUE_NOT_SUPPORTED = 93 + WEBPAGE_CRITERION_URL_EQUALS_CAN_HAVE_ONLY_ONE_CONDITION = 94 + WEBPAGE_CRITERION_NOT_SUPPORTED_ON_NON_DSA_AD_GROUP = 95 + CANNOT_TARGET_USER_LIST_FOR_SMART_DISPLAY_CAMPAIGNS = 99 + CANNOT_TARGET_PLACEMENTS_FOR_SEARCH_CAMPAIGNS = 126 + LISTING_SCOPE_TOO_MANY_DIMENSION_TYPES = 100 + LISTING_SCOPE_TOO_MANY_IN_OPERATORS = 101 + LISTING_SCOPE_IN_OPERATOR_NOT_SUPPORTED = 102 + DUPLICATE_LISTING_DIMENSION_TYPE = 103 + DUPLICATE_LISTING_DIMENSION_VALUE = 104 + CANNOT_SET_BIDS_ON_LISTING_GROUP_SUBDIVISION = 105 + LISTING_GROUP_ERROR_IN_ANOTHER_OPERATION = 169 + INVALID_LISTING_GROUP_HIERARCHY = 106 + LISTING_GROUP_TREE_WAS_INVALID_BEFORE_MUTATION = 170 + LISTING_GROUP_UNIT_CANNOT_HAVE_CHILDREN = 107 + LISTING_GROUP_SUBDIVISION_REQUIRES_OTHERS_CASE = 108 + LISTING_GROUP_REQUIRES_SAME_DIMENSION_TYPE_AS_SIBLINGS = 109 + LISTING_GROUP_ALREADY_EXISTS = 110 + LISTING_GROUP_DOES_NOT_EXIST = 111 + LISTING_GROUP_CANNOT_BE_REMOVED = 112 + INVALID_LISTING_GROUP_TYPE = 113 + LISTING_GROUP_ADD_MAY_ONLY_USE_TEMP_ID = 114 + LISTING_SCOPE_TOO_LONG = 115 + LISTING_SCOPE_TOO_MANY_DIMENSIONS = 116 + LISTING_GROUP_TOO_LONG = 117 + LISTING_GROUP_TREE_TOO_DEEP = 118 + INVALID_LISTING_DIMENSION = 119 + INVALID_LISTING_DIMENSION_TYPE = 120 + ADVERTISER_NOT_ON_ALLOWLIST_FOR_COMBINED_AUDIENCE_ON_DISPLAY = 127 + CANNOT_TARGET_REMOVED_COMBINED_AUDIENCE = 128 + INVALID_COMBINED_AUDIENCE_ID = 129 + CANNOT_TARGET_REMOVED_CUSTOM_AUDIENCE = 130 + HOTEL_CHECK_IN_DATE_RANGE_OVERLAPS_WITH_EXISTING_CRITERION = 131 + HOTEL_CHECK_IN_DATE_RANGE_START_DATE_TOO_EARLY = 132 + HOTEL_CHECK_IN_DATE_RANGE_END_DATE_TOO_LATE = 133 + HOTEL_CHECK_IN_DATE_RANGE_REVERSED = 134 + BROAD_MATCH_MODIFIER_KEYWORD_NOT_ALLOWED = 135 + ONE_AUDIENCE_ALLOWED_PER_ASSET_GROUP = 136 + AUDIENCE_NOT_ELIGIBLE_FOR_CAMPAIGN_TYPE = 137 + AUDIENCE_NOT_ALLOWED_TO_ATTACH_WHEN_AUDIENCE_GROUPED_SET_TO_FALSE = 138 + CANNOT_TARGET_CUSTOMER_MATCH_USER_LIST = 139 + NEGATIVE_KEYWORD_SHARED_SET_DOES_NOT_EXIST = 145 + CANNOT_ADD_REMOVED_NEGATIVE_KEYWORD_SHARED_SET = 146 + CANNOT_HAVE_MULTIPLE_NEGATIVE_KEYWORD_LIST_PER_ACCOUNT = 147 + CUSTOMER_CANNOT_ADD_CRITERION_OF_THIS_TYPE = 149 + CANNOT_TARGET_SIMILAR_USER_LIST = 151 + CANNOT_ADD_AUDIENCE_SEGMENT_CRITERION_WHEN_AUDIENCE_GROUPED_IS_SET = 152 + ONE_AUDIENCE_ALLOWED_PER_AD_GROUP = 153 + INVALID_DETAILED_DEMOGRAPHIC = 154 + CANNOT_RECOGNIZE_BRAND = 155 + BRAND_SHARED_SET_DOES_NOT_EXIST = 156 + CANNOT_ADD_REMOVED_BRAND_SHARED_SET = 157 + ONLY_EXCLUSION_BRAND_LIST_ALLOWED_FOR_CAMPAIGN_TYPE = 158 + CANNOT_TARGET_ONLY_UNDETERMINED = 165 + LOCATION_TARGETING_NOT_ELIGIBLE_FOR_RESTRICTED_CAMPAIGN = 166 + ONLY_INCLUSION_BRAND_LIST_ALLOWED_FOR_AD_GROUPS = 171 + CANNOT_ADD_REMOVED_PLACEMENT_LIST_SHARED_SET = 172 + PLACEMENT_LIST_SHARED_SET_DOES_NOT_EXIST = 173 + AI_MAX_MUST_BE_ENABLED = 174 + NOT_AVAILABLE_FOR_AI_MAX_CAMPAIGNS = 175 + MISSING_EU_POLITICAL_ADVERTISING_SELF_DECLARATION = 176 + INVALID_CAMPAIGN_TYPE_FOR_THIRD_PARTY_PARTNER_DATA_LIST = 177 + CANNOT_ADD_USER_LIST_PENDING_PRIVACY_REVIEW = 178 + VERTICAL_ADS_ITEM_GROUP_RULE_LIST_DOES_NOT_EXIST = 179 + CANNOT_ADD_REMOVED_VERTICAL_ADS_ITEM_GROUP_RULE_LIST_SHARED_SET = 180 + VERTICAL_ADS_ITEM_GROUP_RULE_LIST_NOT_SUPPORTED_FOR_CAMPAIGNS_WITHOUT_ENABLED_TRAVEL_FEED = ( + 181 + ) + VERTICAL_ADS_ITEM_GROUP_RULE_LIST_NOT_SUPPORTED_FOR_CAMPAIGNS_WITHOUT_AI_MAX = ( + 182 + ) + VERTICAL_ADS_ITEM_GROUP_RULE_NOT_SUPPORTED_FOR_THE_VERTICAL_TYPE = 183 + RETAIL_FILTER_EXPRESSION_DOES_NOT_EXIST = 184 + RETAIL_FILTER_TAGS_REFERRING_TO_EXPRESSION = 185 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/currency_code_error.py b/google/ads/googleads/v24/errors/types/currency_code_error.py new file mode 100644 index 000000000..5bdeaede0 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/currency_code_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CurrencyCodeErrorEnum", + }, +) + + +class CurrencyCodeErrorEnum(proto.Message): + r"""Container for enum describing possible currency code errors.""" + + class CurrencyCodeError(proto.Enum): + r"""Enum describing possible currency code errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + UNSUPPORTED (2): + The currency code is not supported. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UNSUPPORTED = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/currency_error.py b/google/ads/googleads/v24/errors/types/currency_error.py new file mode 100644 index 000000000..bdc657b08 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/currency_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CurrencyErrorEnum", + }, +) + + +class CurrencyErrorEnum(proto.Message): + r"""Container for enum describing possible currency errors.""" + + class CurrencyError(proto.Enum): + r"""Enum describing possible currency errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + VALUE_NOT_MULTIPLE_OF_BILLABLE_UNIT (2): + Bid must be a multiple of billable unit. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + VALUE_NOT_MULTIPLE_OF_BILLABLE_UNIT = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/custom_audience_error.py b/google/ads/googleads/v24/errors/types/custom_audience_error.py new file mode 100644 index 000000000..372d07bbd --- /dev/null +++ b/google/ads/googleads/v24/errors/types/custom_audience_error.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CustomAudienceErrorEnum", + }, +) + + +class CustomAudienceErrorEnum(proto.Message): + r"""Container for enum describing possible custom audience + errors. + + """ + + class CustomAudienceError(proto.Enum): + r"""Enum describing possible custom audience errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + NAME_ALREADY_USED (2): + New name in the custom audience is duplicated + ignoring cases. + CANNOT_REMOVE_WHILE_IN_USE (3): + Cannot remove a custom audience while it's + still being used as targeting. + RESOURCE_ALREADY_REMOVED (4): + Cannot update or remove a custom audience + that is already removed. + MEMBER_TYPE_AND_PARAMETER_ALREADY_EXISTED (5): + The pair of [type, value] already exists in members. + INVALID_MEMBER_TYPE (6): + Member type is invalid. + MEMBER_TYPE_AND_VALUE_DOES_NOT_MATCH (7): + Member type does not have associated value. + POLICY_VIOLATION (8): + Custom audience contains a member that + violates policy. + INVALID_TYPE_CHANGE (9): + Change in custom audience type is not + allowed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NAME_ALREADY_USED = 2 + CANNOT_REMOVE_WHILE_IN_USE = 3 + RESOURCE_ALREADY_REMOVED = 4 + MEMBER_TYPE_AND_PARAMETER_ALREADY_EXISTED = 5 + INVALID_MEMBER_TYPE = 6 + MEMBER_TYPE_AND_VALUE_DOES_NOT_MATCH = 7 + POLICY_VIOLATION = 8 + INVALID_TYPE_CHANGE = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/custom_conversion_goal_error.py b/google/ads/googleads/v24/errors/types/custom_conversion_goal_error.py new file mode 100644 index 000000000..857e3c0f4 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/custom_conversion_goal_error.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CustomConversionGoalErrorEnum", + }, +) + + +class CustomConversionGoalErrorEnum(proto.Message): + r"""Container for enum describing possible custom conversion goal + errors. + + """ + + class CustomConversionGoalError(proto.Enum): + r"""Enum describing possible custom conversion goal errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_CONVERSION_ACTION (2): + Cannot find a conversion action with the + specified id. + CONVERSION_ACTION_NOT_ENABLED (3): + The conversion action is not enabled so it + cannot be included in a custom conversion goal. + CANNOT_REMOVE_LINKED_CUSTOM_CONVERSION_GOAL (4): + The custom conversion goal cannot be removed + because it's linked to a campaign. + CUSTOM_GOAL_DUPLICATE_NAME (5): + Custom goal with the same name already + exists. + DUPLICATE_CONVERSION_ACTION_LIST (6): + Custom goal with the same conversion action + list already exists. + NON_BIDDABLE_CONVERSION_ACTION_NOT_ELIGIBLE_FOR_CUSTOM_GOAL (7): + Conversion types that cannot be biddable + should not be included in custom goal. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_CONVERSION_ACTION = 2 + CONVERSION_ACTION_NOT_ENABLED = 3 + CANNOT_REMOVE_LINKED_CUSTOM_CONVERSION_GOAL = 4 + CUSTOM_GOAL_DUPLICATE_NAME = 5 + DUPLICATE_CONVERSION_ACTION_LIST = 6 + NON_BIDDABLE_CONVERSION_ACTION_NOT_ELIGIBLE_FOR_CUSTOM_GOAL = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/custom_interest_error.py b/google/ads/googleads/v24/errors/types/custom_interest_error.py new file mode 100644 index 000000000..a8be6a25c --- /dev/null +++ b/google/ads/googleads/v24/errors/types/custom_interest_error.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CustomInterestErrorEnum", + }, +) + + +class CustomInterestErrorEnum(proto.Message): + r"""Container for enum describing possible custom interest + errors. + + """ + + class CustomInterestError(proto.Enum): + r"""Enum describing possible custom interest errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + NAME_ALREADY_USED (2): + Duplicate custom interest name ignoring case. + CUSTOM_INTEREST_MEMBER_ID_AND_TYPE_PARAMETER_NOT_PRESENT_IN_REMOVE (3): + In the remove custom interest member operation, both member + ID and pair [type, parameter] are not present. + TYPE_AND_PARAMETER_NOT_FOUND (4): + The pair of [type, parameter] does not exist. + TYPE_AND_PARAMETER_ALREADY_EXISTED (5): + The pair of [type, parameter] already exists. + INVALID_CUSTOM_INTEREST_MEMBER_TYPE (6): + Unsupported custom interest member type. + CANNOT_REMOVE_WHILE_IN_USE (7): + Cannot remove a custom interest while it's + still being targeted. + CANNOT_CHANGE_TYPE (8): + Cannot mutate custom interest type. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NAME_ALREADY_USED = 2 + CUSTOM_INTEREST_MEMBER_ID_AND_TYPE_PARAMETER_NOT_PRESENT_IN_REMOVE = 3 + TYPE_AND_PARAMETER_NOT_FOUND = 4 + TYPE_AND_PARAMETER_ALREADY_EXISTED = 5 + INVALID_CUSTOM_INTEREST_MEMBER_TYPE = 6 + CANNOT_REMOVE_WHILE_IN_USE = 7 + CANNOT_CHANGE_TYPE = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/customer_client_link_error.py b/google/ads/googleads/v24/errors/types/customer_client_link_error.py new file mode 100644 index 000000000..d1aa18714 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/customer_client_link_error.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerClientLinkErrorEnum", + }, +) + + +class CustomerClientLinkErrorEnum(proto.Message): + r"""Container for enum describing possible CustomerClientLink + errors. + + """ + + class CustomerClientLinkError(proto.Enum): + r"""Enum describing possible CustomerClientLink errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CLIENT_ALREADY_INVITED_BY_THIS_MANAGER (2): + Trying to manage a client that already in + being managed by customer. + CLIENT_ALREADY_MANAGED_IN_HIERARCHY (3): + Already managed by some other manager in the + hierarchy. + CYCLIC_LINK_NOT_ALLOWED (4): + Attempt to create a cycle in the hierarchy. + CUSTOMER_HAS_TOO_MANY_ACCOUNTS (5): + Managed accounts has the maximum number of + linked accounts. + CLIENT_HAS_TOO_MANY_INVITATIONS (6): + Invitor has the maximum pending invitations. + CANNOT_HIDE_OR_UNHIDE_MANAGER_ACCOUNTS (7): + Attempt to change hidden status of a link + that is not active. + CUSTOMER_HAS_TOO_MANY_ACCOUNTS_AT_MANAGER (8): + Parent manager account has the maximum number + of linked accounts. + CLIENT_HAS_TOO_MANY_MANAGERS (9): + Client has too many managers. + MAX_CUSTOMER_LIMIT_REACHED (10): + You have reached the maximum limit of + accounts that can be created for this account. + ACCOUNT_CREATION_POLICY_VIOLATION (11): + This account cannot create new client + accounts due to a Google Ads policy violation. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CLIENT_ALREADY_INVITED_BY_THIS_MANAGER = 2 + CLIENT_ALREADY_MANAGED_IN_HIERARCHY = 3 + CYCLIC_LINK_NOT_ALLOWED = 4 + CUSTOMER_HAS_TOO_MANY_ACCOUNTS = 5 + CLIENT_HAS_TOO_MANY_INVITATIONS = 6 + CANNOT_HIDE_OR_UNHIDE_MANAGER_ACCOUNTS = 7 + CUSTOMER_HAS_TOO_MANY_ACCOUNTS_AT_MANAGER = 8 + CLIENT_HAS_TOO_MANY_MANAGERS = 9 + MAX_CUSTOMER_LIMIT_REACHED = 10 + ACCOUNT_CREATION_POLICY_VIOLATION = 11 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/customer_customizer_error.py b/google/ads/googleads/v24/errors/types/customer_customizer_error.py new file mode 100644 index 000000000..84af2c29e --- /dev/null +++ b/google/ads/googleads/v24/errors/types/customer_customizer_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerCustomizerErrorEnum", + }, +) + + +class CustomerCustomizerErrorEnum(proto.Message): + r"""Container for enum describing possible customer customizer + errors. + + """ + + class CustomerCustomizerError(proto.Enum): + r"""Enum describing possible customer customizer errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/customer_error.py b/google/ads/googleads/v24/errors/types/customer_error.py new file mode 100644 index 000000000..e567c84cd --- /dev/null +++ b/google/ads/googleads/v24/errors/types/customer_error.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerErrorEnum", + }, +) + + +class CustomerErrorEnum(proto.Message): + r"""Container for enum describing possible customer errors.""" + + class CustomerError(proto.Enum): + r"""Set of errors that are related to requests dealing with + Customer. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + STATUS_CHANGE_DISALLOWED (2): + Customer status is not allowed to be changed + from DRAFT and CLOSED. Currency code and at + least one of country code and time zone needs to + be set when status is changed to ENABLED. + ACCOUNT_NOT_SET_UP (3): + CustomerService cannot get a customer that + has not been fully set up. + CREATION_DENIED_FOR_POLICY_VIOLATION (4): + Customer creation is denied for policy + violation. + CREATION_DENIED_INELIGIBLE_MCC (5): + Manager account is ineligible to create new + accounts. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + STATUS_CHANGE_DISALLOWED = 2 + ACCOUNT_NOT_SET_UP = 3 + CREATION_DENIED_FOR_POLICY_VIOLATION = 4 + CREATION_DENIED_INELIGIBLE_MCC = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/customer_feed_error.py b/google/ads/googleads/v24/errors/types/customer_feed_error.py new file mode 100644 index 000000000..2ff53b587 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/customer_feed_error.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerFeedErrorEnum", + }, +) + + +class CustomerFeedErrorEnum(proto.Message): + r"""Container for enum describing possible customer feed errors.""" + + class CustomerFeedError(proto.Enum): + r"""Enum describing possible customer feed errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + FEED_ALREADY_EXISTS_FOR_PLACEHOLDER_TYPE (2): + An active feed already exists for this + customer and place holder type. + CANNOT_CREATE_FOR_REMOVED_FEED (3): + The specified feed is removed. + CANNOT_CREATE_ALREADY_EXISTING_CUSTOMER_FEED (4): + The CustomerFeed already exists. Update + should be used to modify the existing + CustomerFeed. + CANNOT_MODIFY_REMOVED_CUSTOMER_FEED (5): + Cannot update removed customer feed. + INVALID_PLACEHOLDER_TYPE (6): + Invalid placeholder type. + MISSING_FEEDMAPPING_FOR_PLACEHOLDER_TYPE (7): + Feed mapping for this placeholder type does + not exist. + PLACEHOLDER_TYPE_NOT_ALLOWED_ON_CUSTOMER_FEED (8): + Placeholder not allowed at the account level. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + FEED_ALREADY_EXISTS_FOR_PLACEHOLDER_TYPE = 2 + CANNOT_CREATE_FOR_REMOVED_FEED = 3 + CANNOT_CREATE_ALREADY_EXISTING_CUSTOMER_FEED = 4 + CANNOT_MODIFY_REMOVED_CUSTOMER_FEED = 5 + INVALID_PLACEHOLDER_TYPE = 6 + MISSING_FEEDMAPPING_FOR_PLACEHOLDER_TYPE = 7 + PLACEHOLDER_TYPE_NOT_ALLOWED_ON_CUSTOMER_FEED = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/customer_lifecycle_goal_error.py b/google/ads/googleads/v24/errors/types/customer_lifecycle_goal_error.py new file mode 100644 index 000000000..9ce3a9d9b --- /dev/null +++ b/google/ads/googleads/v24/errors/types/customer_lifecycle_goal_error.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerLifecycleGoalErrorEnum", + }, +) + + +class CustomerLifecycleGoalErrorEnum(proto.Message): + r"""Container for enum describing possible customer lifecycle + goal errors. + + """ + + class CustomerLifecycleGoalError(proto.Enum): + r"""Enum describing possible customer lifecycle goal errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CUSTOMER_ACQUISITION_VALUE_MISSING (2): + CustomerLifecycleGoal.customer_acquisition_goal_value_settings.value + must be set. + CUSTOMER_ACQUISITION_INVALID_VALUE (3): + CustomerLifecycleGoal.customer_acquisition_goal_value_settings.value + must be no less than 0.01. + CUSTOMER_ACQUISITION_INVALID_HIGH_LIFETIME_VALUE (4): + CustomerLifecycleGoal.customer_acquisition_goal_value_settings.high_lifetime_value + must be no less than 0.01. Also, to set this field, + CustomerLifecycleGoal.customer_acquisition_goal_value_settings.value + must also be present, and high_lifetime_value must be + greater than value. + CUSTOMER_ACQUISITION_VALUE_CANNOT_BE_CLEARED (5): + CustomerLifecycleGoal.customer_acquisition_goal_value_settings.value + cannot be cleared. This value would have no effect as long + as none of your campaigns adopt the customer acquisitiong + goal. + CUSTOMER_ACQUISITION_HIGH_LIFETIME_VALUE_CANNOT_BE_CLEARED (6): + CustomerLifecycleGoal.customer_acquisition_goal_value_settings.high_lifetime_value + cannot be cleared. This value would have no effect as long + as none of your campaigns adopt the high value optimization + of customer acquisitiong goal. + INVALID_EXISTING_USER_LIST (7): + Found invalid value in + CustomerLifecycleGoal.lifecycle_goal_customer_definition_settings.existing_user_lists. + The userlist must be accessible, active and belong to one of + the following types: CRM_BASED, RULE_BASED, REMARKETING. + INVALID_HIGH_LIFETIME_VALUE_USER_LIST (8): + Found invalid value in + CustomerLifecycleGoal.lifecycle_goal_customer_definition_settings.high_lifetime_value_user_lists. + The userlist must be accessible, active and belong to one of + the following types: CRM_BASED, RULE_BASED, REMARKETING. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER_ACQUISITION_VALUE_MISSING = 2 + CUSTOMER_ACQUISITION_INVALID_VALUE = 3 + CUSTOMER_ACQUISITION_INVALID_HIGH_LIFETIME_VALUE = 4 + CUSTOMER_ACQUISITION_VALUE_CANNOT_BE_CLEARED = 5 + CUSTOMER_ACQUISITION_HIGH_LIFETIME_VALUE_CANNOT_BE_CLEARED = 6 + INVALID_EXISTING_USER_LIST = 7 + INVALID_HIGH_LIFETIME_VALUE_USER_LIST = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/customer_manager_link_error.py b/google/ads/googleads/v24/errors/types/customer_manager_link_error.py new file mode 100644 index 000000000..fbb0f5795 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/customer_manager_link_error.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerManagerLinkErrorEnum", + }, +) + + +class CustomerManagerLinkErrorEnum(proto.Message): + r"""Container for enum describing possible CustomerManagerLink + errors. + + """ + + class CustomerManagerLinkError(proto.Enum): + r"""Enum describing possible CustomerManagerLink errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + NO_PENDING_INVITE (2): + No pending invitation. + SAME_CLIENT_MORE_THAN_ONCE_PER_CALL (3): + Attempt to operate on the same client more + than once in the same call. + MANAGER_HAS_MAX_NUMBER_OF_LINKED_ACCOUNTS (4): + Manager account has the maximum number of + linked accounts. + CANNOT_UNLINK_ACCOUNT_WITHOUT_ACTIVE_USER (5): + If no active user on account it cannot be + unlinked from its manager. + CANNOT_REMOVE_LAST_CLIENT_ACCOUNT_OWNER (6): + Account should have at least one active owner + on it before being unlinked. + CANNOT_CHANGE_ROLE_BY_NON_ACCOUNT_OWNER (7): + Only account owners may change their + permission role. + CANNOT_CHANGE_ROLE_FOR_NON_ACTIVE_LINK_ACCOUNT (8): + When a client's link to its manager is not + active, the link role cannot be changed. + DUPLICATE_CHILD_FOUND (9): + Attempt to link a child to a parent that + contains or will contain duplicate children. + TEST_ACCOUNT_LINKS_TOO_MANY_CHILD_ACCOUNTS (10): + The authorized customer is a test account. It + can add no more than the allowed number of + accounts + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NO_PENDING_INVITE = 2 + SAME_CLIENT_MORE_THAN_ONCE_PER_CALL = 3 + MANAGER_HAS_MAX_NUMBER_OF_LINKED_ACCOUNTS = 4 + CANNOT_UNLINK_ACCOUNT_WITHOUT_ACTIVE_USER = 5 + CANNOT_REMOVE_LAST_CLIENT_ACCOUNT_OWNER = 6 + CANNOT_CHANGE_ROLE_BY_NON_ACCOUNT_OWNER = 7 + CANNOT_CHANGE_ROLE_FOR_NON_ACTIVE_LINK_ACCOUNT = 8 + DUPLICATE_CHILD_FOUND = 9 + TEST_ACCOUNT_LINKS_TOO_MANY_CHILD_ACCOUNTS = 10 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/customer_sk_ad_network_conversion_value_schema_error.py b/google/ads/googleads/v24/errors/types/customer_sk_ad_network_conversion_value_schema_error.py new file mode 100644 index 000000000..d4f8c0da7 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/customer_sk_ad_network_conversion_value_schema_error.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerSkAdNetworkConversionValueSchemaErrorEnum", + }, +) + + +class CustomerSkAdNetworkConversionValueSchemaErrorEnum(proto.Message): + r"""Container for enum describing possible + CustomerSkAdNetworkConversionValueSchema errors. + + """ + + class CustomerSkAdNetworkConversionValueSchemaError(proto.Enum): + r"""Enum describing possible + CustomerSkAdNetworkConversionValueSchema errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_LINK_ID (2): + The customer link ID provided is invalid. + INVALID_APP_ID (3): + The app ID provided is invalid. + INVALID_SCHEMA (4): + The conversion value schema provided is + invalid. + LINK_CODE_NOT_FOUND (5): + The customer link id provided could not be + found. + INVALID_EVENT_COUNTER (7): + The SkAdNetwork event counter provided is + invalid. + INVALID_EVENT_NAME (8): + The SkAdNetwork event name provided is + invalid. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_LINK_ID = 2 + INVALID_APP_ID = 3 + INVALID_SCHEMA = 4 + LINK_CODE_NOT_FOUND = 5 + INVALID_EVENT_COUNTER = 7 + INVALID_EVENT_NAME = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/customer_user_access_error.py b/google/ads/googleads/v24/errors/types/customer_user_access_error.py new file mode 100644 index 000000000..a02f9577a --- /dev/null +++ b/google/ads/googleads/v24/errors/types/customer_user_access_error.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerUserAccessErrorEnum", + }, +) + + +class CustomerUserAccessErrorEnum(proto.Message): + r"""Container for enum describing possible CustomerUserAccess + errors. + + """ + + class CustomerUserAccessError(proto.Enum): + r"""Enum describing possible customer user access errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_USER_ID (2): + There is no user associated with the user id + specified. + REMOVAL_DISALLOWED (3): + Unable to remove the access between the user + and customer. + DISALLOWED_ACCESS_ROLE (4): + Unable to add or update the access role as + specified. + LAST_ADMIN_USER_OF_SERVING_CUSTOMER (5): + The user can't remove itself from an active + serving customer if it's the last admin user and + the customer doesn't have any owner manager + LAST_ADMIN_USER_OF_MANAGER (6): + Last admin user cannot be removed from a + manager. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_USER_ID = 2 + REMOVAL_DISALLOWED = 3 + DISALLOWED_ACCESS_ROLE = 4 + LAST_ADMIN_USER_OF_SERVING_CUSTOMER = 5 + LAST_ADMIN_USER_OF_MANAGER = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/customizer_attribute_error.py b/google/ads/googleads/v24/errors/types/customizer_attribute_error.py new file mode 100644 index 000000000..8022e0dcd --- /dev/null +++ b/google/ads/googleads/v24/errors/types/customizer_attribute_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "CustomizerAttributeErrorEnum", + }, +) + + +class CustomizerAttributeErrorEnum(proto.Message): + r"""Container for enum describing possible customizer attribute + errors. + + """ + + class CustomizerAttributeError(proto.Enum): + r"""Enum describing possible customizer attribute errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + DUPLICATE_CUSTOMIZER_ATTRIBUTE_NAME (2): + CustomizerAttribute name matches that of + another active CustomizerAttribute. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DUPLICATE_CUSTOMIZER_ATTRIBUTE_NAME = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/data_link_error.py b/google/ads/googleads/v24/errors/types/data_link_error.py new file mode 100644 index 000000000..3779901b9 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/data_link_error.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "DataLinkErrorEnum", + }, +) + + +class DataLinkErrorEnum(proto.Message): + r"""Container for enum describing possible DataLink errors.""" + + class DataLinkError(proto.Enum): + r"""Enum describing possible DataLink errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + YOUTUBE_CHANNEL_ID_INVALID (2): + The requested YouTube Channel ID is invalid. + YOUTUBE_VIDEO_ID_INVALID (3): + The requested YouTube Video ID is invalid. + YOUTUBE_VIDEO_FROM_DIFFERENT_CHANNEL (4): + The requested YouTube Video ID doesn't belong + to the requested YouTube Channel ID. + PERMISSION_DENIED (5): + A link cannot be created because the customer + doesn't have the permission. + INVALID_STATUS (6): + A link can not be removed or updated because + the status is invalid. + INVALID_UPDATE_STATUS (7): + The input status in the update request is + invalid. + INVALID_RESOURCE_NAME (8): + The input resource name is invalid. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + YOUTUBE_CHANNEL_ID_INVALID = 2 + YOUTUBE_VIDEO_ID_INVALID = 3 + YOUTUBE_VIDEO_FROM_DIFFERENT_CHANNEL = 4 + PERMISSION_DENIED = 5 + INVALID_STATUS = 6 + INVALID_UPDATE_STATUS = 7 + INVALID_RESOURCE_NAME = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/database_error.py b/google/ads/googleads/v24/errors/types/database_error.py new file mode 100644 index 000000000..0ba9bbd94 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/database_error.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "DatabaseErrorEnum", + }, +) + + +class DatabaseErrorEnum(proto.Message): + r"""Container for enum describing possible database errors.""" + + class DatabaseError(proto.Enum): + r"""Enum describing possible database errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CONCURRENT_MODIFICATION (2): + Multiple requests were attempting to modify + the same resource at once. Retry the request. + DATA_CONSTRAINT_VIOLATION (3): + The request conflicted with existing data. + This error will usually be replaced with a more + specific error if the request is retried. + REQUEST_TOO_LARGE (4): + The data written is too large. Split the + request into smaller requests. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CONCURRENT_MODIFICATION = 2 + DATA_CONSTRAINT_VIOLATION = 3 + REQUEST_TOO_LARGE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/date_error.py b/google/ads/googleads/v24/errors/types/date_error.py new file mode 100644 index 000000000..e6652dd70 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/date_error.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "DateErrorEnum", + }, +) + + +class DateErrorEnum(proto.Message): + r"""Container for enum describing possible date errors.""" + + class DateError(proto.Enum): + r"""Enum describing possible date errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_FIELD_VALUES_IN_DATE (2): + Given field values do not correspond to a + valid date. + INVALID_FIELD_VALUES_IN_DATE_TIME (3): + Given field values do not correspond to a + valid date time. + INVALID_STRING_DATE (4): + The string date's format should be + yyyy-mm-dd. + INVALID_STRING_DATE_TIME_MICROS (6): + The string date time's format should be + yyyy-mm-dd hh:mm:ss.ssssss. + INVALID_STRING_DATE_TIME_SECONDS (11): + The string date time's format should be + yyyy-mm-dd hh:mm:ss. + INVALID_STRING_DATE_TIME_SECONDS_WITH_OFFSET (12): + The string date time's format should be yyyy-mm-dd + hh:mm:ss+\|-hh:mm. + EARLIER_THAN_MINIMUM_DATE (7): + Date is before allowed minimum. + LATER_THAN_MAXIMUM_DATE (8): + Date is after allowed maximum. + DATE_RANGE_MINIMUM_DATE_LATER_THAN_MAXIMUM_DATE (9): + Date range bounds are not in order. + DATE_RANGE_MINIMUM_AND_MAXIMUM_DATES_BOTH_NULL (10): + Both dates in range are null. + DATE_RANGE_ERROR_START_TIME_MUST_BE_THE_START_OF_A_DAY (13): + This campaign type doesn't support a start + date time that isn't the start of the day. + DATE_RANGE_ERROR_END_TIME_MUST_BE_THE_END_OF_A_DAY (14): + This campaign type doesn't support an end + date time that isn't the end of the day. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_FIELD_VALUES_IN_DATE = 2 + INVALID_FIELD_VALUES_IN_DATE_TIME = 3 + INVALID_STRING_DATE = 4 + INVALID_STRING_DATE_TIME_MICROS = 6 + INVALID_STRING_DATE_TIME_SECONDS = 11 + INVALID_STRING_DATE_TIME_SECONDS_WITH_OFFSET = 12 + EARLIER_THAN_MINIMUM_DATE = 7 + LATER_THAN_MAXIMUM_DATE = 8 + DATE_RANGE_MINIMUM_DATE_LATER_THAN_MAXIMUM_DATE = 9 + DATE_RANGE_MINIMUM_AND_MAXIMUM_DATES_BOTH_NULL = 10 + DATE_RANGE_ERROR_START_TIME_MUST_BE_THE_START_OF_A_DAY = 13 + DATE_RANGE_ERROR_END_TIME_MUST_BE_THE_END_OF_A_DAY = 14 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/date_range_error.py b/google/ads/googleads/v24/errors/types/date_range_error.py new file mode 100644 index 000000000..9bf7133f1 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/date_range_error.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "DateRangeErrorEnum", + }, +) + + +class DateRangeErrorEnum(proto.Message): + r"""Container for enum describing possible date range errors.""" + + class DateRangeError(proto.Enum): + r"""Enum describing possible date range errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_DATE (2): + Invalid date. + START_DATE_AFTER_END_DATE (3): + The start date was after the end date. + CANNOT_SET_DATE_TO_PAST (4): + Cannot set date to past time + AFTER_MAXIMUM_ALLOWABLE_DATE (5): + A date was used that is past the system + "last" date. + CANNOT_MODIFY_START_DATE_IF_ALREADY_STARTED (6): + Trying to change start date on a resource + that has started. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_DATE = 2 + START_DATE_AFTER_END_DATE = 3 + CANNOT_SET_DATE_TO_PAST = 4 + AFTER_MAXIMUM_ALLOWABLE_DATE = 5 + CANNOT_MODIFY_START_DATE_IF_ALREADY_STARTED = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/distinct_error.py b/google/ads/googleads/v24/errors/types/distinct_error.py new file mode 100644 index 000000000..6004d4455 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/distinct_error.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "DistinctErrorEnum", + }, +) + + +class DistinctErrorEnum(proto.Message): + r"""Container for enum describing possible distinct errors.""" + + class DistinctError(proto.Enum): + r"""Enum describing possible distinct errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + DUPLICATE_ELEMENT (2): + Duplicate element. + DUPLICATE_TYPE (3): + Duplicate type. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DUPLICATE_ELEMENT = 2 + DUPLICATE_TYPE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/enum_error.py b/google/ads/googleads/v24/errors/types/enum_error.py new file mode 100644 index 000000000..8be4069f7 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/enum_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "EnumErrorEnum", + }, +) + + +class EnumErrorEnum(proto.Message): + r"""Container for enum describing possible enum errors.""" + + class EnumError(proto.Enum): + r"""Enum describing possible enum errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + ENUM_VALUE_NOT_PERMITTED (3): + The enum value is not permitted. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ENUM_VALUE_NOT_PERMITTED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/errors.py b/google/ads/googleads/v24/errors/types/errors.py new file mode 100644 index 000000000..731080ff3 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/errors.py @@ -0,0 +1,3014 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import campaign_reservation_quote +from google.ads.googleads.v24.common.types import policy +from google.ads.googleads.v24.common.types import value +from google.ads.googleads.v24.enums.types import resource_limit_type +from google.ads.googleads.v24.errors.types import ( + access_invitation_error as gage_access_invitation_error, +) +from google.ads.googleads.v24.errors.types import ( + account_budget_proposal_error as gage_account_budget_proposal_error, +) +from google.ads.googleads.v24.errors.types import ( + account_link_error as gage_account_link_error, +) +from google.ads.googleads.v24.errors.types import ( + action_error as gage_action_error, +) +from google.ads.googleads.v24.errors.types import ( + ad_customizer_error as gage_ad_customizer_error, +) +from google.ads.googleads.v24.errors.types import ad_error as gage_ad_error +from google.ads.googleads.v24.errors.types import ( + ad_group_ad_error as gage_ad_group_ad_error, +) +from google.ads.googleads.v24.errors.types import ( + ad_group_bid_modifier_error as gage_ad_group_bid_modifier_error, +) +from google.ads.googleads.v24.errors.types import ( + ad_group_criterion_customizer_error as gage_ad_group_criterion_customizer_error, +) +from google.ads.googleads.v24.errors.types import ( + ad_group_criterion_error as gage_ad_group_criterion_error, +) +from google.ads.googleads.v24.errors.types import ( + ad_group_customizer_error as gage_ad_group_customizer_error, +) +from google.ads.googleads.v24.errors.types import ( + ad_group_error as gage_ad_group_error, +) +from google.ads.googleads.v24.errors.types import ( + ad_group_feed_error as gage_ad_group_feed_error, +) +from google.ads.googleads.v24.errors.types import ( + ad_parameter_error as gage_ad_parameter_error, +) +from google.ads.googleads.v24.errors.types import ( + ad_sharing_error as gage_ad_sharing_error, +) +from google.ads.googleads.v24.errors.types import adx_error as gage_adx_error +from google.ads.googleads.v24.errors.types import ( + asset_error as gage_asset_error, +) +from google.ads.googleads.v24.errors.types import ( + asset_generation_error as gage_asset_generation_error, +) +from google.ads.googleads.v24.errors.types import ( + asset_group_asset_error as gage_asset_group_asset_error, +) +from google.ads.googleads.v24.errors.types import ( + asset_group_error as gage_asset_group_error, +) +from google.ads.googleads.v24.errors.types import ( + asset_group_listing_group_filter_error as gage_asset_group_listing_group_filter_error, +) +from google.ads.googleads.v24.errors.types import ( + asset_group_signal_error as gage_asset_group_signal_error, +) +from google.ads.googleads.v24.errors.types import ( + asset_link_error as gage_asset_link_error, +) +from google.ads.googleads.v24.errors.types import ( + asset_set_asset_error as gage_asset_set_asset_error, +) +from google.ads.googleads.v24.errors.types import ( + asset_set_error as gage_asset_set_error, +) +from google.ads.googleads.v24.errors.types import ( + asset_set_link_error as gage_asset_set_link_error, +) +from google.ads.googleads.v24.errors.types import ( + audience_error as gage_audience_error, +) +from google.ads.googleads.v24.errors.types import ( + audience_insights_error as gage_audience_insights_error, +) +from google.ads.googleads.v24.errors.types import ( + authentication_error as gage_authentication_error, +) +from google.ads.googleads.v24.errors.types import ( + authorization_error as gage_authorization_error, +) +from google.ads.googleads.v24.errors.types import ( + automatically_created_asset_removal_error as gage_automatically_created_asset_removal_error, +) +from google.ads.googleads.v24.errors.types import ( + batch_job_error as gage_batch_job_error, +) +from google.ads.googleads.v24.errors.types import ( + benchmarks_error as gage_benchmarks_error, +) +from google.ads.googleads.v24.errors.types import ( + bidding_error as gage_bidding_error, +) +from google.ads.googleads.v24.errors.types import ( + bidding_strategy_error as gage_bidding_strategy_error, +) +from google.ads.googleads.v24.errors.types import ( + billing_setup_error as gage_billing_setup_error, +) +from google.ads.googleads.v24.errors.types import ( + brand_guidelines_migration_error as gage_brand_guidelines_migration_error, +) +from google.ads.googleads.v24.errors.types import ( + campaign_budget_error as gage_campaign_budget_error, +) +from google.ads.googleads.v24.errors.types import ( + campaign_conversion_goal_error as gage_campaign_conversion_goal_error, +) +from google.ads.googleads.v24.errors.types import ( + campaign_criterion_error as gage_campaign_criterion_error, +) +from google.ads.googleads.v24.errors.types import ( + campaign_customizer_error as gage_campaign_customizer_error, +) +from google.ads.googleads.v24.errors.types import ( + campaign_draft_error as gage_campaign_draft_error, +) +from google.ads.googleads.v24.errors.types import ( + campaign_error as gage_campaign_error, +) +from google.ads.googleads.v24.errors.types import ( + campaign_experiment_error as gage_campaign_experiment_error, +) +from google.ads.googleads.v24.errors.types import ( + campaign_feed_error as gage_campaign_feed_error, +) +from google.ads.googleads.v24.errors.types import ( + campaign_goal_config_error as gage_campaign_goal_config_error, +) +from google.ads.googleads.v24.errors.types import ( + campaign_lifecycle_goal_error as gage_campaign_lifecycle_goal_error, +) +from google.ads.googleads.v24.errors.types import ( + campaign_shared_set_error as gage_campaign_shared_set_error, +) +from google.ads.googleads.v24.errors.types import ( + change_event_error as gage_change_event_error, +) +from google.ads.googleads.v24.errors.types import ( + change_status_error as gage_change_status_error, +) +from google.ads.googleads.v24.errors.types import ( + click_view_error as gage_click_view_error, +) +from google.ads.googleads.v24.errors.types import ( + collection_size_error as gage_collection_size_error, +) +from google.ads.googleads.v24.errors.types import ( + content_creator_insights_error as gage_content_creator_insights_error, +) +from google.ads.googleads.v24.errors.types import ( + context_error as gage_context_error, +) +from google.ads.googleads.v24.errors.types import ( + conversion_action_error as gage_conversion_action_error, +) +from google.ads.googleads.v24.errors.types import ( + conversion_adjustment_upload_error as gage_conversion_adjustment_upload_error, +) +from google.ads.googleads.v24.errors.types import ( + conversion_custom_variable_error as gage_conversion_custom_variable_error, +) +from google.ads.googleads.v24.errors.types import ( + conversion_goal_campaign_config_error as gage_conversion_goal_campaign_config_error, +) +from google.ads.googleads.v24.errors.types import ( + conversion_upload_error as gage_conversion_upload_error, +) +from google.ads.googleads.v24.errors.types import ( + conversion_value_rule_error as gage_conversion_value_rule_error, +) +from google.ads.googleads.v24.errors.types import ( + conversion_value_rule_set_error as gage_conversion_value_rule_set_error, +) +from google.ads.googleads.v24.errors.types import ( + country_code_error as gage_country_code_error, +) +from google.ads.googleads.v24.errors.types import ( + criterion_error as gage_criterion_error, +) +from google.ads.googleads.v24.errors.types import ( + currency_code_error as gage_currency_code_error, +) +from google.ads.googleads.v24.errors.types import ( + currency_error as gage_currency_error, +) +from google.ads.googleads.v24.errors.types import ( + custom_audience_error as gage_custom_audience_error, +) +from google.ads.googleads.v24.errors.types import ( + custom_conversion_goal_error as gage_custom_conversion_goal_error, +) +from google.ads.googleads.v24.errors.types import ( + custom_interest_error as gage_custom_interest_error, +) +from google.ads.googleads.v24.errors.types import ( + customer_client_link_error as gage_customer_client_link_error, +) +from google.ads.googleads.v24.errors.types import ( + customer_customizer_error as gage_customer_customizer_error, +) +from google.ads.googleads.v24.errors.types import ( + customer_error as gage_customer_error, +) +from google.ads.googleads.v24.errors.types import ( + customer_feed_error as gage_customer_feed_error, +) +from google.ads.googleads.v24.errors.types import ( + customer_lifecycle_goal_error as gage_customer_lifecycle_goal_error, +) +from google.ads.googleads.v24.errors.types import ( + customer_manager_link_error as gage_customer_manager_link_error, +) +from google.ads.googleads.v24.errors.types import ( + customer_sk_ad_network_conversion_value_schema_error as gage_customer_sk_ad_network_conversion_value_schema_error, +) +from google.ads.googleads.v24.errors.types import ( + customer_user_access_error as gage_customer_user_access_error, +) +from google.ads.googleads.v24.errors.types import ( + customizer_attribute_error as gage_customizer_attribute_error, +) +from google.ads.googleads.v24.errors.types import ( + data_link_error as gage_data_link_error, +) +from google.ads.googleads.v24.errors.types import ( + database_error as gage_database_error, +) +from google.ads.googleads.v24.errors.types import date_error as gage_date_error +from google.ads.googleads.v24.errors.types import ( + date_range_error as gage_date_range_error, +) +from google.ads.googleads.v24.errors.types import ( + distinct_error as gage_distinct_error, +) +from google.ads.googleads.v24.errors.types import enum_error as gage_enum_error +from google.ads.googleads.v24.errors.types import ( + experiment_arm_error as gage_experiment_arm_error, +) +from google.ads.googleads.v24.errors.types import ( + experiment_error as gage_experiment_error, +) +from google.ads.googleads.v24.errors.types import ( + extension_feed_item_error as gage_extension_feed_item_error, +) +from google.ads.googleads.v24.errors.types import ( + extension_setting_error as gage_extension_setting_error, +) +from google.ads.googleads.v24.errors.types import ( + feed_attribute_reference_error as gage_feed_attribute_reference_error, +) +from google.ads.googleads.v24.errors.types import feed_error as gage_feed_error +from google.ads.googleads.v24.errors.types import ( + feed_item_error as gage_feed_item_error, +) +from google.ads.googleads.v24.errors.types import ( + feed_item_set_error as gage_feed_item_set_error, +) +from google.ads.googleads.v24.errors.types import ( + feed_item_set_link_error as gage_feed_item_set_link_error, +) +from google.ads.googleads.v24.errors.types import ( + feed_item_target_error as gage_feed_item_target_error, +) +from google.ads.googleads.v24.errors.types import ( + feed_item_validation_error as gage_feed_item_validation_error, +) +from google.ads.googleads.v24.errors.types import ( + feed_mapping_error as gage_feed_mapping_error, +) +from google.ads.googleads.v24.errors.types import ( + field_error as gage_field_error, +) +from google.ads.googleads.v24.errors.types import ( + field_mask_error as gage_field_mask_error, +) +from google.ads.googleads.v24.errors.types import ( + final_url_expansion_asset_view_error as gage_final_url_expansion_asset_view_error, +) +from google.ads.googleads.v24.errors.types import ( + function_error as gage_function_error, +) +from google.ads.googleads.v24.errors.types import ( + function_parsing_error as gage_function_parsing_error, +) +from google.ads.googleads.v24.errors.types import ( + geo_target_constant_suggestion_error as gage_geo_target_constant_suggestion_error, +) +from google.ads.googleads.v24.errors.types import goal_error as gage_goal_error +from google.ads.googleads.v24.errors.types import ( + header_error as gage_header_error, +) +from google.ads.googleads.v24.errors.types import id_error as gage_id_error +from google.ads.googleads.v24.errors.types import ( + identity_verification_error as gage_identity_verification_error, +) +from google.ads.googleads.v24.errors.types import ( + image_error as gage_image_error, +) +from google.ads.googleads.v24.errors.types import ( + incentive_error as gage_incentive_error, +) +from google.ads.googleads.v24.errors.types import ( + internal_error as gage_internal_error, +) +from google.ads.googleads.v24.errors.types import ( + invoice_error as gage_invoice_error, +) +from google.ads.googleads.v24.errors.types import ( + keyword_plan_ad_group_error as gage_keyword_plan_ad_group_error, +) +from google.ads.googleads.v24.errors.types import ( + keyword_plan_ad_group_keyword_error as gage_keyword_plan_ad_group_keyword_error, +) +from google.ads.googleads.v24.errors.types import ( + keyword_plan_campaign_error as gage_keyword_plan_campaign_error, +) +from google.ads.googleads.v24.errors.types import ( + keyword_plan_campaign_keyword_error as gage_keyword_plan_campaign_keyword_error, +) +from google.ads.googleads.v24.errors.types import ( + keyword_plan_error as gage_keyword_plan_error, +) +from google.ads.googleads.v24.errors.types import ( + keyword_plan_idea_error as gage_keyword_plan_idea_error, +) +from google.ads.googleads.v24.errors.types import ( + label_error as gage_label_error, +) +from google.ads.googleads.v24.errors.types import ( + language_code_error as gage_language_code_error, +) +from google.ads.googleads.v24.errors.types import ( + list_operation_error as gage_list_operation_error, +) +from google.ads.googleads.v24.errors.types import ( + manager_link_error as gage_manager_link_error, +) +from google.ads.googleads.v24.errors.types import ( + media_bundle_error as gage_media_bundle_error, +) +from google.ads.googleads.v24.errors.types import ( + media_file_error as gage_media_file_error, +) +from google.ads.googleads.v24.errors.types import ( + media_upload_error as gage_media_upload_error, +) +from google.ads.googleads.v24.errors.types import ( + merchant_center_error as gage_merchant_center_error, +) +from google.ads.googleads.v24.errors.types import ( + multiplier_error as gage_multiplier_error, +) +from google.ads.googleads.v24.errors.types import ( + mutate_error as gage_mutate_error, +) +from google.ads.googleads.v24.errors.types import ( + new_resource_creation_error as gage_new_resource_creation_error, +) +from google.ads.googleads.v24.errors.types import ( + not_allowlisted_error as gage_not_allowlisted_error, +) +from google.ads.googleads.v24.errors.types import ( + not_empty_error as gage_not_empty_error, +) +from google.ads.googleads.v24.errors.types import null_error as gage_null_error +from google.ads.googleads.v24.errors.types import ( + offline_user_data_job_error as gage_offline_user_data_job_error, +) +from google.ads.googleads.v24.errors.types import ( + operation_access_denied_error as gage_operation_access_denied_error, +) +from google.ads.googleads.v24.errors.types import ( + operator_error as gage_operator_error, +) +from google.ads.googleads.v24.errors.types import ( + partial_failure_error as gage_partial_failure_error, +) +from google.ads.googleads.v24.errors.types import ( + payments_account_error as gage_payments_account_error, +) +from google.ads.googleads.v24.errors.types import ( + policy_finding_error as gage_policy_finding_error, +) +from google.ads.googleads.v24.errors.types import ( + policy_validation_parameter_error as gage_policy_validation_parameter_error, +) +from google.ads.googleads.v24.errors.types import ( + policy_violation_error as gage_policy_violation_error, +) +from google.ads.googleads.v24.errors.types import ( + product_link_error as gage_product_link_error, +) +from google.ads.googleads.v24.errors.types import ( + product_link_invitation_error as gage_product_link_invitation_error, +) +from google.ads.googleads.v24.errors.types import ( + query_error as gage_query_error, +) +from google.ads.googleads.v24.errors.types import ( + quota_error as gage_quota_error, +) +from google.ads.googleads.v24.errors.types import ( + range_error as gage_range_error, +) +from google.ads.googleads.v24.errors.types import ( + reach_plan_error as gage_reach_plan_error, +) +from google.ads.googleads.v24.errors.types import ( + recommendation_error as gage_recommendation_error, +) +from google.ads.googleads.v24.errors.types import ( + recommendation_subscription_error as gage_recommendation_subscription_error, +) +from google.ads.googleads.v24.errors.types import ( + region_code_error as gage_region_code_error, +) +from google.ads.googleads.v24.errors.types import ( + request_error as gage_request_error, +) +from google.ads.googleads.v24.errors.types import ( + resource_access_denied_error as gage_resource_access_denied_error, +) +from google.ads.googleads.v24.errors.types import ( + resource_count_limit_exceeded_error as gage_resource_count_limit_exceeded_error, +) +from google.ads.googleads.v24.errors.types import ( + search_term_insight_error as gage_search_term_insight_error, +) +from google.ads.googleads.v24.errors.types import ( + setting_error as gage_setting_error, +) +from google.ads.googleads.v24.errors.types import ( + shareable_preview_error as gage_shareable_preview_error, +) +from google.ads.googleads.v24.errors.types import ( + shared_criterion_error as gage_shared_criterion_error, +) +from google.ads.googleads.v24.errors.types import ( + shared_set_error as gage_shared_set_error, +) +from google.ads.googleads.v24.errors.types import ( + shopping_product_error as gage_shopping_product_error, +) +from google.ads.googleads.v24.errors.types import ( + size_limit_error as gage_size_limit_error, +) +from google.ads.googleads.v24.errors.types import ( + smart_campaign_error as gage_smart_campaign_error, +) +from google.ads.googleads.v24.errors.types import ( + string_format_error as gage_string_format_error, +) +from google.ads.googleads.v24.errors.types import ( + string_length_error as gage_string_length_error, +) +from google.ads.googleads.v24.errors.types import ( + third_party_app_analytics_link_error as gage_third_party_app_analytics_link_error, +) +from google.ads.googleads.v24.errors.types import ( + time_zone_error as gage_time_zone_error, +) +from google.ads.googleads.v24.errors.types import ( + url_field_error as gage_url_field_error, +) +from google.ads.googleads.v24.errors.types import ( + user_data_error as gage_user_data_error, +) +from google.ads.googleads.v24.errors.types import ( + user_list_customer_type_error as gage_user_list_customer_type_error, +) +from google.ads.googleads.v24.errors.types import ( + user_list_error as gage_user_list_error, +) +from google.ads.googleads.v24.errors.types import ( + video_campaign_error as gage_video_campaign_error, +) +from google.ads.googleads.v24.errors.types import ( + video_reservation_error as gage_video_reservation_error, +) +from google.ads.googleads.v24.errors.types import ( + youtube_video_registration_error as gage_youtube_video_registration_error, +) +from google.protobuf import duration_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "GoogleAdsFailure", + "GoogleAdsError", + "ErrorCode", + "ErrorLocation", + "ErrorDetails", + "PolicyViolationDetails", + "PolicyFindingDetails", + "QuotaErrorDetails", + "ResourceCountDetails", + "BudgetPerDayMinimumErrorDetails", + "ReservationErrorDetails", + }, +) + + +class GoogleAdsFailure(proto.Message): + r"""Describes how a GoogleAds API call failed. It's returned + inside google.rpc.Status.details when a call fails. + + Attributes: + errors (MutableSequence[google.ads.googleads.v24.errors.types.GoogleAdsError]): + The list of errors that occurred. + request_id (str): + The unique ID of the request that is used for + debugging purposes. + """ + + errors: MutableSequence["GoogleAdsError"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="GoogleAdsError", + ) + request_id: str = proto.Field( + proto.STRING, + number=2, + ) + + +class GoogleAdsError(proto.Message): + r"""GoogleAds-specific error. + + Attributes: + error_code (google.ads.googleads.v24.errors.types.ErrorCode): + An enum value that indicates which error + occurred. + message (str): + A human-readable description of the error. + trigger (google.ads.googleads.v24.common.types.Value): + The value that triggered the error. + location (google.ads.googleads.v24.errors.types.ErrorLocation): + Describes the part of the request proto that + caused the error. + details (google.ads.googleads.v24.errors.types.ErrorDetails): + Additional error details, which are returned + by certain error codes. Most error codes do not + include details. + """ + + error_code: "ErrorCode" = proto.Field( + proto.MESSAGE, + number=1, + message="ErrorCode", + ) + message: str = proto.Field( + proto.STRING, + number=2, + ) + trigger: value.Value = proto.Field( + proto.MESSAGE, + number=3, + message=value.Value, + ) + location: "ErrorLocation" = proto.Field( + proto.MESSAGE, + number=4, + message="ErrorLocation", + ) + details: "ErrorDetails" = proto.Field( + proto.MESSAGE, + number=5, + message="ErrorDetails", + ) + + +class ErrorCode(proto.Message): + r"""The error reason represented by type and enum. + + 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: + request_error (google.ads.googleads.v24.errors.types.RequestErrorEnum.RequestError): + An error caused by the request + + This field is a member of `oneof`_ ``error_code``. + bidding_strategy_error (google.ads.googleads.v24.errors.types.BiddingStrategyErrorEnum.BiddingStrategyError): + An error with a Bidding Strategy mutate. + + This field is a member of `oneof`_ ``error_code``. + url_field_error (google.ads.googleads.v24.errors.types.UrlFieldErrorEnum.UrlFieldError): + An error with a URL field mutate. + + This field is a member of `oneof`_ ``error_code``. + list_operation_error (google.ads.googleads.v24.errors.types.ListOperationErrorEnum.ListOperationError): + An error with a list operation. + + This field is a member of `oneof`_ ``error_code``. + query_error (google.ads.googleads.v24.errors.types.QueryErrorEnum.QueryError): + An error with an AWQL query + + This field is a member of `oneof`_ ``error_code``. + mutate_error (google.ads.googleads.v24.errors.types.MutateErrorEnum.MutateError): + An error with a mutate + + This field is a member of `oneof`_ ``error_code``. + field_mask_error (google.ads.googleads.v24.errors.types.FieldMaskErrorEnum.FieldMaskError): + An error with a field mask + + This field is a member of `oneof`_ ``error_code``. + authorization_error (google.ads.googleads.v24.errors.types.AuthorizationErrorEnum.AuthorizationError): + An error encountered when trying to authorize + a user. + + This field is a member of `oneof`_ ``error_code``. + internal_error (google.ads.googleads.v24.errors.types.InternalErrorEnum.InternalError): + An unexpected server-side error. + + This field is a member of `oneof`_ ``error_code``. + quota_error (google.ads.googleads.v24.errors.types.QuotaErrorEnum.QuotaError): + An error with the amount of quota remaining. + + This field is a member of `oneof`_ ``error_code``. + ad_error (google.ads.googleads.v24.errors.types.AdErrorEnum.AdError): + An error with an Ad Group Ad mutate. + + This field is a member of `oneof`_ ``error_code``. + ad_group_error (google.ads.googleads.v24.errors.types.AdGroupErrorEnum.AdGroupError): + An error with an Ad Group mutate. + + This field is a member of `oneof`_ ``error_code``. + campaign_budget_error (google.ads.googleads.v24.errors.types.CampaignBudgetErrorEnum.CampaignBudgetError): + An error with a Campaign Budget mutate. + + This field is a member of `oneof`_ ``error_code``. + campaign_error (google.ads.googleads.v24.errors.types.CampaignErrorEnum.CampaignError): + An error with a Campaign mutate. + + This field is a member of `oneof`_ ``error_code``. + video_campaign_error (google.ads.googleads.v24.errors.types.VideoCampaignErrorEnum.VideoCampaignError): + An error with a Video Campaign mutate. + + This field is a member of `oneof`_ ``error_code``. + authentication_error (google.ads.googleads.v24.errors.types.AuthenticationErrorEnum.AuthenticationError): + Indicates failure to properly authenticate + user. + + This field is a member of `oneof`_ ``error_code``. + action_error (google.ads.googleads.v24.errors.types.ActionErrorEnum.ActionError): + An error with a Tangle Action. + + This field is a member of `oneof`_ ``error_code``. + ad_group_criterion_customizer_error (google.ads.googleads.v24.errors.types.AdGroupCriterionCustomizerErrorEnum.AdGroupCriterionCustomizerError): + The reasons for the ad group criterion + customizer error. + + This field is a member of `oneof`_ ``error_code``. + ad_group_criterion_error (google.ads.googleads.v24.errors.types.AdGroupCriterionErrorEnum.AdGroupCriterionError): + Indicates failure to properly authenticate + user. + + This field is a member of `oneof`_ ``error_code``. + ad_group_customizer_error (google.ads.googleads.v24.errors.types.AdGroupCustomizerErrorEnum.AdGroupCustomizerError): + The reasons for the ad group customizer + error. + + This field is a member of `oneof`_ ``error_code``. + ad_customizer_error (google.ads.googleads.v24.errors.types.AdCustomizerErrorEnum.AdCustomizerError): + The reasons for the ad customizer error + + This field is a member of `oneof`_ ``error_code``. + ad_group_ad_error (google.ads.googleads.v24.errors.types.AdGroupAdErrorEnum.AdGroupAdError): + The reasons for the ad group ad error + + This field is a member of `oneof`_ ``error_code``. + ad_sharing_error (google.ads.googleads.v24.errors.types.AdSharingErrorEnum.AdSharingError): + The reasons for the ad sharing error + + This field is a member of `oneof`_ ``error_code``. + adx_error (google.ads.googleads.v24.errors.types.AdxErrorEnum.AdxError): + The reasons for the adx error + + This field is a member of `oneof`_ ``error_code``. + asset_error (google.ads.googleads.v24.errors.types.AssetErrorEnum.AssetError): + The reasons for the asset error + + This field is a member of `oneof`_ ``error_code``. + asset_group_asset_error (google.ads.googleads.v24.errors.types.AssetGroupAssetErrorEnum.AssetGroupAssetError): + The reasons for the asset group asset error + + This field is a member of `oneof`_ ``error_code``. + asset_group_listing_group_filter_error (google.ads.googleads.v24.errors.types.AssetGroupListingGroupFilterErrorEnum.AssetGroupListingGroupFilterError): + The reasons for the asset group listing group + filter error + + This field is a member of `oneof`_ ``error_code``. + asset_group_error (google.ads.googleads.v24.errors.types.AssetGroupErrorEnum.AssetGroupError): + The reasons for the asset group error + + This field is a member of `oneof`_ ``error_code``. + asset_set_asset_error (google.ads.googleads.v24.errors.types.AssetSetAssetErrorEnum.AssetSetAssetError): + The reasons for the asset set asset error + + This field is a member of `oneof`_ ``error_code``. + asset_set_link_error (google.ads.googleads.v24.errors.types.AssetSetLinkErrorEnum.AssetSetLinkError): + The reasons for the asset set link error + + This field is a member of `oneof`_ ``error_code``. + asset_set_error (google.ads.googleads.v24.errors.types.AssetSetErrorEnum.AssetSetError): + The reasons for the asset set error + + This field is a member of `oneof`_ ``error_code``. + bidding_error (google.ads.googleads.v24.errors.types.BiddingErrorEnum.BiddingError): + The reasons for the bidding errors + + This field is a member of `oneof`_ ``error_code``. + campaign_criterion_error (google.ads.googleads.v24.errors.types.CampaignCriterionErrorEnum.CampaignCriterionError): + The reasons for the campaign criterion error + + This field is a member of `oneof`_ ``error_code``. + campaign_conversion_goal_error (google.ads.googleads.v24.errors.types.CampaignConversionGoalErrorEnum.CampaignConversionGoalError): + The reasons for the campaign conversion goal + error + + This field is a member of `oneof`_ ``error_code``. + campaign_customizer_error (google.ads.googleads.v24.errors.types.CampaignCustomizerErrorEnum.CampaignCustomizerError): + The reasons for the campaign customizer + error. + + This field is a member of `oneof`_ ``error_code``. + collection_size_error (google.ads.googleads.v24.errors.types.CollectionSizeErrorEnum.CollectionSizeError): + The reasons for the collection size error + + This field is a member of `oneof`_ ``error_code``. + conversion_goal_campaign_config_error (google.ads.googleads.v24.errors.types.ConversionGoalCampaignConfigErrorEnum.ConversionGoalCampaignConfigError): + The reasons for the conversion goal campaign + config error + + This field is a member of `oneof`_ ``error_code``. + country_code_error (google.ads.googleads.v24.errors.types.CountryCodeErrorEnum.CountryCodeError): + The reasons for the country code error + + This field is a member of `oneof`_ ``error_code``. + criterion_error (google.ads.googleads.v24.errors.types.CriterionErrorEnum.CriterionError): + The reasons for the criterion error + + This field is a member of `oneof`_ ``error_code``. + custom_conversion_goal_error (google.ads.googleads.v24.errors.types.CustomConversionGoalErrorEnum.CustomConversionGoalError): + The reasons for the custom conversion goal + error + + This field is a member of `oneof`_ ``error_code``. + customer_customizer_error (google.ads.googleads.v24.errors.types.CustomerCustomizerErrorEnum.CustomerCustomizerError): + The reasons for the customer customizer + error. + + This field is a member of `oneof`_ ``error_code``. + customer_error (google.ads.googleads.v24.errors.types.CustomerErrorEnum.CustomerError): + The reasons for the customer error + + This field is a member of `oneof`_ ``error_code``. + customizer_attribute_error (google.ads.googleads.v24.errors.types.CustomizerAttributeErrorEnum.CustomizerAttributeError): + The reasons for the customizer attribute + error. + + This field is a member of `oneof`_ ``error_code``. + date_error (google.ads.googleads.v24.errors.types.DateErrorEnum.DateError): + The reasons for the date error + + This field is a member of `oneof`_ ``error_code``. + date_range_error (google.ads.googleads.v24.errors.types.DateRangeErrorEnum.DateRangeError): + The reasons for the date range error + + This field is a member of `oneof`_ ``error_code``. + distinct_error (google.ads.googleads.v24.errors.types.DistinctErrorEnum.DistinctError): + The reasons for the distinct error + + This field is a member of `oneof`_ ``error_code``. + feed_attribute_reference_error (google.ads.googleads.v24.errors.types.FeedAttributeReferenceErrorEnum.FeedAttributeReferenceError): + The reasons for the feed attribute reference + error + + This field is a member of `oneof`_ ``error_code``. + final_url_expansion_asset_view_error (google.ads.googleads.v24.errors.types.FinalUrlExpansionAssetViewErrorEnum.FinalUrlExpansionAssetViewError): + The reasons for the final url expansion asset + view error + + This field is a member of `oneof`_ ``error_code``. + function_error (google.ads.googleads.v24.errors.types.FunctionErrorEnum.FunctionError): + The reasons for the function error + + This field is a member of `oneof`_ ``error_code``. + function_parsing_error (google.ads.googleads.v24.errors.types.FunctionParsingErrorEnum.FunctionParsingError): + The reasons for the function parsing error + + This field is a member of `oneof`_ ``error_code``. + id_error (google.ads.googleads.v24.errors.types.IdErrorEnum.IdError): + The reasons for the id error + + This field is a member of `oneof`_ ``error_code``. + image_error (google.ads.googleads.v24.errors.types.ImageErrorEnum.ImageError): + The reasons for the image error + + This field is a member of `oneof`_ ``error_code``. + language_code_error (google.ads.googleads.v24.errors.types.LanguageCodeErrorEnum.LanguageCodeError): + The reasons for the language code error + + This field is a member of `oneof`_ ``error_code``. + media_bundle_error (google.ads.googleads.v24.errors.types.MediaBundleErrorEnum.MediaBundleError): + The reasons for the media bundle error + + This field is a member of `oneof`_ ``error_code``. + media_upload_error (google.ads.googleads.v24.errors.types.MediaUploadErrorEnum.MediaUploadError): + The reasons for media uploading errors. + + This field is a member of `oneof`_ ``error_code``. + media_file_error (google.ads.googleads.v24.errors.types.MediaFileErrorEnum.MediaFileError): + The reasons for the media file error + + This field is a member of `oneof`_ ``error_code``. + merchant_center_error (google.ads.googleads.v24.errors.types.MerchantCenterErrorEnum.MerchantCenterError): + Container for enum describing possible + merchant center errors. + + This field is a member of `oneof`_ ``error_code``. + multiplier_error (google.ads.googleads.v24.errors.types.MultiplierErrorEnum.MultiplierError): + The reasons for the multiplier error + + This field is a member of `oneof`_ ``error_code``. + new_resource_creation_error (google.ads.googleads.v24.errors.types.NewResourceCreationErrorEnum.NewResourceCreationError): + The reasons for the new resource creation + error + + This field is a member of `oneof`_ ``error_code``. + not_empty_error (google.ads.googleads.v24.errors.types.NotEmptyErrorEnum.NotEmptyError): + The reasons for the not empty error + + This field is a member of `oneof`_ ``error_code``. + null_error (google.ads.googleads.v24.errors.types.NullErrorEnum.NullError): + The reasons for the null error + + This field is a member of `oneof`_ ``error_code``. + operator_error (google.ads.googleads.v24.errors.types.OperatorErrorEnum.OperatorError): + The reasons for the operator error + + This field is a member of `oneof`_ ``error_code``. + range_error (google.ads.googleads.v24.errors.types.RangeErrorEnum.RangeError): + The reasons for the range error + + This field is a member of `oneof`_ ``error_code``. + recommendation_error (google.ads.googleads.v24.errors.types.RecommendationErrorEnum.RecommendationError): + The reasons for error in applying a + recommendation + + This field is a member of `oneof`_ ``error_code``. + recommendation_subscription_error (google.ads.googleads.v24.errors.types.RecommendationSubscriptionErrorEnum.RecommendationSubscriptionError): + The reasons for the recommendation + subscription error. + + This field is a member of `oneof`_ ``error_code``. + region_code_error (google.ads.googleads.v24.errors.types.RegionCodeErrorEnum.RegionCodeError): + The reasons for the region code error + + This field is a member of `oneof`_ ``error_code``. + setting_error (google.ads.googleads.v24.errors.types.SettingErrorEnum.SettingError): + The reasons for the setting error + + This field is a member of `oneof`_ ``error_code``. + string_format_error (google.ads.googleads.v24.errors.types.StringFormatErrorEnum.StringFormatError): + The reasons for the string format error + + This field is a member of `oneof`_ ``error_code``. + string_length_error (google.ads.googleads.v24.errors.types.StringLengthErrorEnum.StringLengthError): + The reasons for the string length error + + This field is a member of `oneof`_ ``error_code``. + operation_access_denied_error (google.ads.googleads.v24.errors.types.OperationAccessDeniedErrorEnum.OperationAccessDeniedError): + The reasons for the operation access denied + error + + This field is a member of `oneof`_ ``error_code``. + resource_access_denied_error (google.ads.googleads.v24.errors.types.ResourceAccessDeniedErrorEnum.ResourceAccessDeniedError): + The reasons for the resource access denied + error + + This field is a member of `oneof`_ ``error_code``. + resource_count_limit_exceeded_error (google.ads.googleads.v24.errors.types.ResourceCountLimitExceededErrorEnum.ResourceCountLimitExceededError): + The reasons for the resource count limit + exceeded error + + This field is a member of `oneof`_ ``error_code``. + youtube_video_registration_error (google.ads.googleads.v24.errors.types.YoutubeVideoRegistrationErrorEnum.YoutubeVideoRegistrationError): + The reasons for YouTube video registration + errors. + + This field is a member of `oneof`_ ``error_code``. + ad_group_bid_modifier_error (google.ads.googleads.v24.errors.types.AdGroupBidModifierErrorEnum.AdGroupBidModifierError): + The reasons for the ad group bid modifier + error + + This field is a member of `oneof`_ ``error_code``. + context_error (google.ads.googleads.v24.errors.types.ContextErrorEnum.ContextError): + The reasons for the context error + + This field is a member of `oneof`_ ``error_code``. + field_error (google.ads.googleads.v24.errors.types.FieldErrorEnum.FieldError): + The reasons for the field error + + This field is a member of `oneof`_ ``error_code``. + shared_set_error (google.ads.googleads.v24.errors.types.SharedSetErrorEnum.SharedSetError): + The reasons for the shared set error + + This field is a member of `oneof`_ ``error_code``. + shared_criterion_error (google.ads.googleads.v24.errors.types.SharedCriterionErrorEnum.SharedCriterionError): + The reasons for the shared criterion error + + This field is a member of `oneof`_ ``error_code``. + campaign_shared_set_error (google.ads.googleads.v24.errors.types.CampaignSharedSetErrorEnum.CampaignSharedSetError): + The reasons for the campaign shared set error + + This field is a member of `oneof`_ ``error_code``. + conversion_action_error (google.ads.googleads.v24.errors.types.ConversionActionErrorEnum.ConversionActionError): + The reasons for the conversion action error + + This field is a member of `oneof`_ ``error_code``. + conversion_adjustment_upload_error (google.ads.googleads.v24.errors.types.ConversionAdjustmentUploadErrorEnum.ConversionAdjustmentUploadError): + The reasons for the conversion adjustment + upload error + + This field is a member of `oneof`_ ``error_code``. + conversion_custom_variable_error (google.ads.googleads.v24.errors.types.ConversionCustomVariableErrorEnum.ConversionCustomVariableError): + The reasons for the conversion custom + variable error + + This field is a member of `oneof`_ ``error_code``. + conversion_upload_error (google.ads.googleads.v24.errors.types.ConversionUploadErrorEnum.ConversionUploadError): + The reasons for the conversion upload error + + This field is a member of `oneof`_ ``error_code``. + conversion_value_rule_error (google.ads.googleads.v24.errors.types.ConversionValueRuleErrorEnum.ConversionValueRuleError): + The reasons for the conversion value rule + error + + This field is a member of `oneof`_ ``error_code``. + conversion_value_rule_set_error (google.ads.googleads.v24.errors.types.ConversionValueRuleSetErrorEnum.ConversionValueRuleSetError): + The reasons for the conversion value rule set + error + + This field is a member of `oneof`_ ``error_code``. + header_error (google.ads.googleads.v24.errors.types.HeaderErrorEnum.HeaderError): + The reasons for the header error. + + This field is a member of `oneof`_ ``error_code``. + database_error (google.ads.googleads.v24.errors.types.DatabaseErrorEnum.DatabaseError): + The reasons for the database error. + + This field is a member of `oneof`_ ``error_code``. + policy_finding_error (google.ads.googleads.v24.errors.types.PolicyFindingErrorEnum.PolicyFindingError): + The reasons for the policy finding error. + + This field is a member of `oneof`_ ``error_code``. + enum_error (google.ads.googleads.v24.errors.types.EnumErrorEnum.EnumError): + The reason for enum error. + + This field is a member of `oneof`_ ``error_code``. + keyword_plan_error (google.ads.googleads.v24.errors.types.KeywordPlanErrorEnum.KeywordPlanError): + The reason for keyword plan error. + + This field is a member of `oneof`_ ``error_code``. + keyword_plan_campaign_error (google.ads.googleads.v24.errors.types.KeywordPlanCampaignErrorEnum.KeywordPlanCampaignError): + The reason for keyword plan campaign error. + + This field is a member of `oneof`_ ``error_code``. + keyword_plan_campaign_keyword_error (google.ads.googleads.v24.errors.types.KeywordPlanCampaignKeywordErrorEnum.KeywordPlanCampaignKeywordError): + The reason for keyword plan campaign keyword + error. + + This field is a member of `oneof`_ ``error_code``. + keyword_plan_ad_group_error (google.ads.googleads.v24.errors.types.KeywordPlanAdGroupErrorEnum.KeywordPlanAdGroupError): + The reason for keyword plan ad group error. + + This field is a member of `oneof`_ ``error_code``. + keyword_plan_ad_group_keyword_error (google.ads.googleads.v24.errors.types.KeywordPlanAdGroupKeywordErrorEnum.KeywordPlanAdGroupKeywordError): + The reason for keyword plan ad group keyword + error. + + This field is a member of `oneof`_ ``error_code``. + keyword_plan_idea_error (google.ads.googleads.v24.errors.types.KeywordPlanIdeaErrorEnum.KeywordPlanIdeaError): + The reason for keyword idea error. + + This field is a member of `oneof`_ ``error_code``. + account_budget_proposal_error (google.ads.googleads.v24.errors.types.AccountBudgetProposalErrorEnum.AccountBudgetProposalError): + The reasons for account budget proposal + errors. + + This field is a member of `oneof`_ ``error_code``. + user_list_error (google.ads.googleads.v24.errors.types.UserListErrorEnum.UserListError): + The reasons for the user list error + + This field is a member of `oneof`_ ``error_code``. + change_event_error (google.ads.googleads.v24.errors.types.ChangeEventErrorEnum.ChangeEventError): + The reasons for the change event error + + This field is a member of `oneof`_ ``error_code``. + change_status_error (google.ads.googleads.v24.errors.types.ChangeStatusErrorEnum.ChangeStatusError): + The reasons for the change status error + + This field is a member of `oneof`_ ``error_code``. + feed_error (google.ads.googleads.v24.errors.types.FeedErrorEnum.FeedError): + The reasons for the feed error + + This field is a member of `oneof`_ ``error_code``. + geo_target_constant_suggestion_error (google.ads.googleads.v24.errors.types.GeoTargetConstantSuggestionErrorEnum.GeoTargetConstantSuggestionError): + The reasons for the geo target constant + suggestion error. + + This field is a member of `oneof`_ ``error_code``. + campaign_draft_error (google.ads.googleads.v24.errors.types.CampaignDraftErrorEnum.CampaignDraftError): + The reasons for the campaign draft error + + This field is a member of `oneof`_ ``error_code``. + feed_item_error (google.ads.googleads.v24.errors.types.FeedItemErrorEnum.FeedItemError): + The reasons for the feed item error + + This field is a member of `oneof`_ ``error_code``. + label_error (google.ads.googleads.v24.errors.types.LabelErrorEnum.LabelError): + The reason for the label error. + + This field is a member of `oneof`_ ``error_code``. + billing_setup_error (google.ads.googleads.v24.errors.types.BillingSetupErrorEnum.BillingSetupError): + The reasons for the billing setup error + + This field is a member of `oneof`_ ``error_code``. + customer_client_link_error (google.ads.googleads.v24.errors.types.CustomerClientLinkErrorEnum.CustomerClientLinkError): + The reasons for the customer client link + error + + This field is a member of `oneof`_ ``error_code``. + customer_manager_link_error (google.ads.googleads.v24.errors.types.CustomerManagerLinkErrorEnum.CustomerManagerLinkError): + The reasons for the customer manager link + error + + This field is a member of `oneof`_ ``error_code``. + feed_mapping_error (google.ads.googleads.v24.errors.types.FeedMappingErrorEnum.FeedMappingError): + The reasons for the feed mapping error + + This field is a member of `oneof`_ ``error_code``. + customer_feed_error (google.ads.googleads.v24.errors.types.CustomerFeedErrorEnum.CustomerFeedError): + The reasons for the customer feed error + + This field is a member of `oneof`_ ``error_code``. + ad_group_feed_error (google.ads.googleads.v24.errors.types.AdGroupFeedErrorEnum.AdGroupFeedError): + The reasons for the ad group feed error + + This field is a member of `oneof`_ ``error_code``. + campaign_feed_error (google.ads.googleads.v24.errors.types.CampaignFeedErrorEnum.CampaignFeedError): + The reasons for the campaign feed error + + This field is a member of `oneof`_ ``error_code``. + custom_interest_error (google.ads.googleads.v24.errors.types.CustomInterestErrorEnum.CustomInterestError): + The reasons for the custom interest error + + This field is a member of `oneof`_ ``error_code``. + campaign_experiment_error (google.ads.googleads.v24.errors.types.CampaignExperimentErrorEnum.CampaignExperimentError): + The reasons for the campaign experiment error + + This field is a member of `oneof`_ ``error_code``. + extension_feed_item_error (google.ads.googleads.v24.errors.types.ExtensionFeedItemErrorEnum.ExtensionFeedItemError): + The reasons for the extension feed item error + + This field is a member of `oneof`_ ``error_code``. + ad_parameter_error (google.ads.googleads.v24.errors.types.AdParameterErrorEnum.AdParameterError): + The reasons for the ad parameter error + + This field is a member of `oneof`_ ``error_code``. + feed_item_validation_error (google.ads.googleads.v24.errors.types.FeedItemValidationErrorEnum.FeedItemValidationError): + The reasons for the feed item validation + error + + This field is a member of `oneof`_ ``error_code``. + extension_setting_error (google.ads.googleads.v24.errors.types.ExtensionSettingErrorEnum.ExtensionSettingError): + The reasons for the extension setting error + + This field is a member of `oneof`_ ``error_code``. + feed_item_set_error (google.ads.googleads.v24.errors.types.FeedItemSetErrorEnum.FeedItemSetError): + The reasons for the feed item set error + + This field is a member of `oneof`_ ``error_code``. + feed_item_set_link_error (google.ads.googleads.v24.errors.types.FeedItemSetLinkErrorEnum.FeedItemSetLinkError): + The reasons for the feed item set link error + + This field is a member of `oneof`_ ``error_code``. + feed_item_target_error (google.ads.googleads.v24.errors.types.FeedItemTargetErrorEnum.FeedItemTargetError): + The reasons for the feed item target error + + This field is a member of `oneof`_ ``error_code``. + policy_violation_error (google.ads.googleads.v24.errors.types.PolicyViolationErrorEnum.PolicyViolationError): + The reasons for the policy violation error + + This field is a member of `oneof`_ ``error_code``. + partial_failure_error (google.ads.googleads.v24.errors.types.PartialFailureErrorEnum.PartialFailureError): + The reasons for the mutate job error + + This field is a member of `oneof`_ ``error_code``. + click_view_error (google.ads.googleads.v24.errors.types.ClickViewErrorEnum.ClickViewError): + The reasons for the click view error + + This field is a member of `oneof`_ ``error_code``. + policy_validation_parameter_error (google.ads.googleads.v24.errors.types.PolicyValidationParameterErrorEnum.PolicyValidationParameterError): + The reasons for the policy validation + parameter error + + This field is a member of `oneof`_ ``error_code``. + size_limit_error (google.ads.googleads.v24.errors.types.SizeLimitErrorEnum.SizeLimitError): + The reasons for the size limit error + + This field is a member of `oneof`_ ``error_code``. + offline_user_data_job_error (google.ads.googleads.v24.errors.types.OfflineUserDataJobErrorEnum.OfflineUserDataJobError): + The reasons for the offline user data job + error. + + This field is a member of `oneof`_ ``error_code``. + not_allowlisted_error (google.ads.googleads.v24.errors.types.NotAllowlistedErrorEnum.NotAllowlistedError): + The reasons for the not allowlisted error + + This field is a member of `oneof`_ ``error_code``. + manager_link_error (google.ads.googleads.v24.errors.types.ManagerLinkErrorEnum.ManagerLinkError): + The reasons for the manager link error + + This field is a member of `oneof`_ ``error_code``. + currency_code_error (google.ads.googleads.v24.errors.types.CurrencyCodeErrorEnum.CurrencyCodeError): + The reasons for the currency code error + + This field is a member of `oneof`_ ``error_code``. + experiment_error (google.ads.googleads.v24.errors.types.ExperimentErrorEnum.ExperimentError): + The reasons for the experiment error + + This field is a member of `oneof`_ ``error_code``. + access_invitation_error (google.ads.googleads.v24.errors.types.AccessInvitationErrorEnum.AccessInvitationError): + The reasons for the access invitation error + + This field is a member of `oneof`_ ``error_code``. + reach_plan_error (google.ads.googleads.v24.errors.types.ReachPlanErrorEnum.ReachPlanError): + The reasons for the reach plan error + + This field is a member of `oneof`_ ``error_code``. + invoice_error (google.ads.googleads.v24.errors.types.InvoiceErrorEnum.InvoiceError): + The reasons for the invoice error + + This field is a member of `oneof`_ ``error_code``. + payments_account_error (google.ads.googleads.v24.errors.types.PaymentsAccountErrorEnum.PaymentsAccountError): + The reasons for errors in payments accounts + service + + This field is a member of `oneof`_ ``error_code``. + time_zone_error (google.ads.googleads.v24.errors.types.TimeZoneErrorEnum.TimeZoneError): + The reasons for the time zone error + + This field is a member of `oneof`_ ``error_code``. + asset_link_error (google.ads.googleads.v24.errors.types.AssetLinkErrorEnum.AssetLinkError): + The reasons for the asset link error + + This field is a member of `oneof`_ ``error_code``. + user_data_error (google.ads.googleads.v24.errors.types.UserDataErrorEnum.UserDataError): + The reasons for the user data error. + + This field is a member of `oneof`_ ``error_code``. + batch_job_error (google.ads.googleads.v24.errors.types.BatchJobErrorEnum.BatchJobError): + The reasons for the batch job error + + This field is a member of `oneof`_ ``error_code``. + account_link_error (google.ads.googleads.v24.errors.types.AccountLinkErrorEnum.AccountLinkError): + The reasons for the account link status + change error + + This field is a member of `oneof`_ ``error_code``. + third_party_app_analytics_link_error (google.ads.googleads.v24.errors.types.ThirdPartyAppAnalyticsLinkErrorEnum.ThirdPartyAppAnalyticsLinkError): + The reasons for the third party app analytics + link mutate error + + This field is a member of `oneof`_ ``error_code``. + customer_user_access_error (google.ads.googleads.v24.errors.types.CustomerUserAccessErrorEnum.CustomerUserAccessError): + The reasons for the customer user access + mutate error + + This field is a member of `oneof`_ ``error_code``. + custom_audience_error (google.ads.googleads.v24.errors.types.CustomAudienceErrorEnum.CustomAudienceError): + The reasons for the custom audience error + + This field is a member of `oneof`_ ``error_code``. + audience_error (google.ads.googleads.v24.errors.types.AudienceErrorEnum.AudienceError): + The reasons for the audience error + + This field is a member of `oneof`_ ``error_code``. + search_term_insight_error (google.ads.googleads.v24.errors.types.SearchTermInsightErrorEnum.SearchTermInsightError): + The reasons for the Search term insight error + + This field is a member of `oneof`_ ``error_code``. + smart_campaign_error (google.ads.googleads.v24.errors.types.SmartCampaignErrorEnum.SmartCampaignError): + The reasons for the Smart campaign error + + This field is a member of `oneof`_ ``error_code``. + experiment_arm_error (google.ads.googleads.v24.errors.types.ExperimentArmErrorEnum.ExperimentArmError): + The reasons for the experiment arm error + + This field is a member of `oneof`_ ``error_code``. + audience_insights_error (google.ads.googleads.v24.errors.types.AudienceInsightsErrorEnum.AudienceInsightsError): + The reasons for the Audience Insights error + + This field is a member of `oneof`_ ``error_code``. + product_link_error (google.ads.googleads.v24.errors.types.ProductLinkErrorEnum.ProductLinkError): + The reasons for the product link error + + This field is a member of `oneof`_ ``error_code``. + data_link_error (google.ads.googleads.v24.errors.types.DataLinkErrorEnum.DataLinkError): + The reasons for the data link error + + This field is a member of `oneof`_ ``error_code``. + customer_sk_ad_network_conversion_value_schema_error (google.ads.googleads.v24.errors.types.CustomerSkAdNetworkConversionValueSchemaErrorEnum.CustomerSkAdNetworkConversionValueSchemaError): + The reasons for the customer SK Ad network + conversion value schema error + + This field is a member of `oneof`_ ``error_code``. + currency_error (google.ads.googleads.v24.errors.types.CurrencyErrorEnum.CurrencyError): + The reasons for the currency errors. + + This field is a member of `oneof`_ ``error_code``. + asset_group_signal_error (google.ads.googleads.v24.errors.types.AssetGroupSignalErrorEnum.AssetGroupSignalError): + The reasons for the asset group hint error + + This field is a member of `oneof`_ ``error_code``. + product_link_invitation_error (google.ads.googleads.v24.errors.types.ProductLinkInvitationErrorEnum.ProductLinkInvitationError): + The reasons for the product link invitation + error + + This field is a member of `oneof`_ ``error_code``. + customer_lifecycle_goal_error (google.ads.googleads.v24.errors.types.CustomerLifecycleGoalErrorEnum.CustomerLifecycleGoalError): + The reasons for the customer lifecycle goal + error + + This field is a member of `oneof`_ ``error_code``. + campaign_lifecycle_goal_error (google.ads.googleads.v24.errors.types.CampaignLifecycleGoalErrorEnum.CampaignLifecycleGoalError): + The reasons for the campaign lifecycle goal + error + + This field is a member of `oneof`_ ``error_code``. + identity_verification_error (google.ads.googleads.v24.errors.types.IdentityVerificationErrorEnum.IdentityVerificationError): + The reasons for an identity verification + error. + + This field is a member of `oneof`_ ``error_code``. + user_list_customer_type_error (google.ads.googleads.v24.errors.types.UserListCustomerTypeErrorEnum.UserListCustomerTypeError): + The reasons for a user list customer type + error. + + This field is a member of `oneof`_ ``error_code``. + shopping_product_error (google.ads.googleads.v24.errors.types.ShoppingProductErrorEnum.ShoppingProductError): + The reasons for error in querying shopping + product. + + This field is a member of `oneof`_ ``error_code``. + automatically_created_asset_removal_error (google.ads.googleads.v24.errors.types.AutomaticallyCreatedAssetRemovalErrorEnum.AutomaticallyCreatedAssetRemovalError): + The reasons for error in automatically + created asset removal action. + + This field is a member of `oneof`_ ``error_code``. + shareable_preview_error (google.ads.googleads.v24.errors.types.ShareablePreviewErrorEnum.ShareablePreviewError): + The reasons for the shareable preview error. + + This field is a member of `oneof`_ ``error_code``. + campaign_goal_config_error (google.ads.googleads.v24.errors.types.CampaignGoalConfigErrorEnum.CampaignGoalConfigError): + The reasons for the campaign goal config + error. + + This field is a member of `oneof`_ ``error_code``. + goal_error (google.ads.googleads.v24.errors.types.GoalErrorEnum.GoalError): + The reasons for the goal error. + + This field is a member of `oneof`_ ``error_code``. + brand_guidelines_migration_error (google.ads.googleads.v24.errors.types.BrandGuidelinesMigrationErrorEnum.BrandGuidelinesMigrationError): + The reasons for the brand guidelines + migration error. + + This field is a member of `oneof`_ ``error_code``. + asset_generation_error (google.ads.googleads.v24.errors.types.AssetGenerationErrorEnum.AssetGenerationError): + The reasons for the GenAI asset generation + error. + + This field is a member of `oneof`_ ``error_code``. + benchmarks_error (google.ads.googleads.v24.errors.types.BenchmarksErrorEnum.BenchmarksError): + The reasons for the Benchmarks error. + + This field is a member of `oneof`_ ``error_code``. + incentive_error (google.ads.googleads.v24.errors.types.IncentiveErrorEnum.IncentiveError): + The reasons for the incentive error + + This field is a member of `oneof`_ ``error_code``. + content_creator_insights_error (google.ads.googleads.v24.errors.types.ContentCreatorInsightsErrorEnum.ContentCreatorInsightsError): + The reasons for the Content Creator Insights + error. + + This field is a member of `oneof`_ ``error_code``. + video_reservation_error (google.ads.googleads.v24.errors.types.VideoReservationErrorEnum.VideoReservationError): + The reasons for the video reservation error. + + This field is a member of `oneof`_ ``error_code``. + """ + + request_error: gage_request_error.RequestErrorEnum.RequestError = ( + proto.Field( + proto.ENUM, + number=1, + oneof="error_code", + enum=gage_request_error.RequestErrorEnum.RequestError, + ) + ) + bidding_strategy_error: ( + gage_bidding_strategy_error.BiddingStrategyErrorEnum.BiddingStrategyError + ) = proto.Field( + proto.ENUM, + number=2, + oneof="error_code", + enum=gage_bidding_strategy_error.BiddingStrategyErrorEnum.BiddingStrategyError, + ) + url_field_error: gage_url_field_error.UrlFieldErrorEnum.UrlFieldError = ( + proto.Field( + proto.ENUM, + number=3, + oneof="error_code", + enum=gage_url_field_error.UrlFieldErrorEnum.UrlFieldError, + ) + ) + list_operation_error: ( + gage_list_operation_error.ListOperationErrorEnum.ListOperationError + ) = proto.Field( + proto.ENUM, + number=4, + oneof="error_code", + enum=gage_list_operation_error.ListOperationErrorEnum.ListOperationError, + ) + query_error: gage_query_error.QueryErrorEnum.QueryError = proto.Field( + proto.ENUM, + number=5, + oneof="error_code", + enum=gage_query_error.QueryErrorEnum.QueryError, + ) + mutate_error: gage_mutate_error.MutateErrorEnum.MutateError = proto.Field( + proto.ENUM, + number=7, + oneof="error_code", + enum=gage_mutate_error.MutateErrorEnum.MutateError, + ) + field_mask_error: ( + gage_field_mask_error.FieldMaskErrorEnum.FieldMaskError + ) = proto.Field( + proto.ENUM, + number=8, + oneof="error_code", + enum=gage_field_mask_error.FieldMaskErrorEnum.FieldMaskError, + ) + authorization_error: ( + gage_authorization_error.AuthorizationErrorEnum.AuthorizationError + ) = proto.Field( + proto.ENUM, + number=9, + oneof="error_code", + enum=gage_authorization_error.AuthorizationErrorEnum.AuthorizationError, + ) + internal_error: gage_internal_error.InternalErrorEnum.InternalError = ( + proto.Field( + proto.ENUM, + number=10, + oneof="error_code", + enum=gage_internal_error.InternalErrorEnum.InternalError, + ) + ) + quota_error: gage_quota_error.QuotaErrorEnum.QuotaError = proto.Field( + proto.ENUM, + number=11, + oneof="error_code", + enum=gage_quota_error.QuotaErrorEnum.QuotaError, + ) + ad_error: gage_ad_error.AdErrorEnum.AdError = proto.Field( + proto.ENUM, + number=12, + oneof="error_code", + enum=gage_ad_error.AdErrorEnum.AdError, + ) + ad_group_error: gage_ad_group_error.AdGroupErrorEnum.AdGroupError = ( + proto.Field( + proto.ENUM, + number=13, + oneof="error_code", + enum=gage_ad_group_error.AdGroupErrorEnum.AdGroupError, + ) + ) + campaign_budget_error: ( + gage_campaign_budget_error.CampaignBudgetErrorEnum.CampaignBudgetError + ) = proto.Field( + proto.ENUM, + number=14, + oneof="error_code", + enum=gage_campaign_budget_error.CampaignBudgetErrorEnum.CampaignBudgetError, + ) + campaign_error: gage_campaign_error.CampaignErrorEnum.CampaignError = ( + proto.Field( + proto.ENUM, + number=15, + oneof="error_code", + enum=gage_campaign_error.CampaignErrorEnum.CampaignError, + ) + ) + video_campaign_error: ( + gage_video_campaign_error.VideoCampaignErrorEnum.VideoCampaignError + ) = proto.Field( + proto.ENUM, + number=182, + oneof="error_code", + enum=gage_video_campaign_error.VideoCampaignErrorEnum.VideoCampaignError, + ) + authentication_error: ( + gage_authentication_error.AuthenticationErrorEnum.AuthenticationError + ) = proto.Field( + proto.ENUM, + number=17, + oneof="error_code", + enum=gage_authentication_error.AuthenticationErrorEnum.AuthenticationError, + ) + action_error: gage_action_error.ActionErrorEnum.ActionError = proto.Field( + proto.ENUM, + number=196, + oneof="error_code", + enum=gage_action_error.ActionErrorEnum.ActionError, + ) + ad_group_criterion_customizer_error: ( + gage_ad_group_criterion_customizer_error.AdGroupCriterionCustomizerErrorEnum.AdGroupCriterionCustomizerError + ) = proto.Field( + proto.ENUM, + number=161, + oneof="error_code", + enum=gage_ad_group_criterion_customizer_error.AdGroupCriterionCustomizerErrorEnum.AdGroupCriterionCustomizerError, + ) + ad_group_criterion_error: ( + gage_ad_group_criterion_error.AdGroupCriterionErrorEnum.AdGroupCriterionError + ) = proto.Field( + proto.ENUM, + number=18, + oneof="error_code", + enum=gage_ad_group_criterion_error.AdGroupCriterionErrorEnum.AdGroupCriterionError, + ) + ad_group_customizer_error: ( + gage_ad_group_customizer_error.AdGroupCustomizerErrorEnum.AdGroupCustomizerError + ) = proto.Field( + proto.ENUM, + number=159, + oneof="error_code", + enum=gage_ad_group_customizer_error.AdGroupCustomizerErrorEnum.AdGroupCustomizerError, + ) + ad_customizer_error: ( + gage_ad_customizer_error.AdCustomizerErrorEnum.AdCustomizerError + ) = proto.Field( + proto.ENUM, + number=19, + oneof="error_code", + enum=gage_ad_customizer_error.AdCustomizerErrorEnum.AdCustomizerError, + ) + ad_group_ad_error: ( + gage_ad_group_ad_error.AdGroupAdErrorEnum.AdGroupAdError + ) = proto.Field( + proto.ENUM, + number=21, + oneof="error_code", + enum=gage_ad_group_ad_error.AdGroupAdErrorEnum.AdGroupAdError, + ) + ad_sharing_error: ( + gage_ad_sharing_error.AdSharingErrorEnum.AdSharingError + ) = proto.Field( + proto.ENUM, + number=24, + oneof="error_code", + enum=gage_ad_sharing_error.AdSharingErrorEnum.AdSharingError, + ) + adx_error: gage_adx_error.AdxErrorEnum.AdxError = proto.Field( + proto.ENUM, + number=25, + oneof="error_code", + enum=gage_adx_error.AdxErrorEnum.AdxError, + ) + asset_error: gage_asset_error.AssetErrorEnum.AssetError = proto.Field( + proto.ENUM, + number=107, + oneof="error_code", + enum=gage_asset_error.AssetErrorEnum.AssetError, + ) + asset_group_asset_error: ( + gage_asset_group_asset_error.AssetGroupAssetErrorEnum.AssetGroupAssetError + ) = proto.Field( + proto.ENUM, + number=149, + oneof="error_code", + enum=gage_asset_group_asset_error.AssetGroupAssetErrorEnum.AssetGroupAssetError, + ) + asset_group_listing_group_filter_error: ( + gage_asset_group_listing_group_filter_error.AssetGroupListingGroupFilterErrorEnum.AssetGroupListingGroupFilterError + ) = proto.Field( + proto.ENUM, + number=155, + oneof="error_code", + enum=gage_asset_group_listing_group_filter_error.AssetGroupListingGroupFilterErrorEnum.AssetGroupListingGroupFilterError, + ) + asset_group_error: ( + gage_asset_group_error.AssetGroupErrorEnum.AssetGroupError + ) = proto.Field( + proto.ENUM, + number=148, + oneof="error_code", + enum=gage_asset_group_error.AssetGroupErrorEnum.AssetGroupError, + ) + asset_set_asset_error: ( + gage_asset_set_asset_error.AssetSetAssetErrorEnum.AssetSetAssetError + ) = proto.Field( + proto.ENUM, + number=153, + oneof="error_code", + enum=gage_asset_set_asset_error.AssetSetAssetErrorEnum.AssetSetAssetError, + ) + asset_set_link_error: ( + gage_asset_set_link_error.AssetSetLinkErrorEnum.AssetSetLinkError + ) = proto.Field( + proto.ENUM, + number=154, + oneof="error_code", + enum=gage_asset_set_link_error.AssetSetLinkErrorEnum.AssetSetLinkError, + ) + asset_set_error: gage_asset_set_error.AssetSetErrorEnum.AssetSetError = ( + proto.Field( + proto.ENUM, + number=152, + oneof="error_code", + enum=gage_asset_set_error.AssetSetErrorEnum.AssetSetError, + ) + ) + bidding_error: gage_bidding_error.BiddingErrorEnum.BiddingError = ( + proto.Field( + proto.ENUM, + number=26, + oneof="error_code", + enum=gage_bidding_error.BiddingErrorEnum.BiddingError, + ) + ) + campaign_criterion_error: ( + gage_campaign_criterion_error.CampaignCriterionErrorEnum.CampaignCriterionError + ) = proto.Field( + proto.ENUM, + number=29, + oneof="error_code", + enum=gage_campaign_criterion_error.CampaignCriterionErrorEnum.CampaignCriterionError, + ) + campaign_conversion_goal_error: ( + gage_campaign_conversion_goal_error.CampaignConversionGoalErrorEnum.CampaignConversionGoalError + ) = proto.Field( + proto.ENUM, + number=166, + oneof="error_code", + enum=gage_campaign_conversion_goal_error.CampaignConversionGoalErrorEnum.CampaignConversionGoalError, + ) + campaign_customizer_error: ( + gage_campaign_customizer_error.CampaignCustomizerErrorEnum.CampaignCustomizerError + ) = proto.Field( + proto.ENUM, + number=160, + oneof="error_code", + enum=gage_campaign_customizer_error.CampaignCustomizerErrorEnum.CampaignCustomizerError, + ) + collection_size_error: ( + gage_collection_size_error.CollectionSizeErrorEnum.CollectionSizeError + ) = proto.Field( + proto.ENUM, + number=31, + oneof="error_code", + enum=gage_collection_size_error.CollectionSizeErrorEnum.CollectionSizeError, + ) + conversion_goal_campaign_config_error: ( + gage_conversion_goal_campaign_config_error.ConversionGoalCampaignConfigErrorEnum.ConversionGoalCampaignConfigError + ) = proto.Field( + proto.ENUM, + number=165, + oneof="error_code", + enum=gage_conversion_goal_campaign_config_error.ConversionGoalCampaignConfigErrorEnum.ConversionGoalCampaignConfigError, + ) + country_code_error: ( + gage_country_code_error.CountryCodeErrorEnum.CountryCodeError + ) = proto.Field( + proto.ENUM, + number=109, + oneof="error_code", + enum=gage_country_code_error.CountryCodeErrorEnum.CountryCodeError, + ) + criterion_error: gage_criterion_error.CriterionErrorEnum.CriterionError = ( + proto.Field( + proto.ENUM, + number=32, + oneof="error_code", + enum=gage_criterion_error.CriterionErrorEnum.CriterionError, + ) + ) + custom_conversion_goal_error: ( + gage_custom_conversion_goal_error.CustomConversionGoalErrorEnum.CustomConversionGoalError + ) = proto.Field( + proto.ENUM, + number=150, + oneof="error_code", + enum=gage_custom_conversion_goal_error.CustomConversionGoalErrorEnum.CustomConversionGoalError, + ) + customer_customizer_error: ( + gage_customer_customizer_error.CustomerCustomizerErrorEnum.CustomerCustomizerError + ) = proto.Field( + proto.ENUM, + number=158, + oneof="error_code", + enum=gage_customer_customizer_error.CustomerCustomizerErrorEnum.CustomerCustomizerError, + ) + customer_error: gage_customer_error.CustomerErrorEnum.CustomerError = ( + proto.Field( + proto.ENUM, + number=90, + oneof="error_code", + enum=gage_customer_error.CustomerErrorEnum.CustomerError, + ) + ) + customizer_attribute_error: ( + gage_customizer_attribute_error.CustomizerAttributeErrorEnum.CustomizerAttributeError + ) = proto.Field( + proto.ENUM, + number=151, + oneof="error_code", + enum=gage_customizer_attribute_error.CustomizerAttributeErrorEnum.CustomizerAttributeError, + ) + date_error: gage_date_error.DateErrorEnum.DateError = proto.Field( + proto.ENUM, + number=33, + oneof="error_code", + enum=gage_date_error.DateErrorEnum.DateError, + ) + date_range_error: ( + gage_date_range_error.DateRangeErrorEnum.DateRangeError + ) = proto.Field( + proto.ENUM, + number=34, + oneof="error_code", + enum=gage_date_range_error.DateRangeErrorEnum.DateRangeError, + ) + distinct_error: gage_distinct_error.DistinctErrorEnum.DistinctError = ( + proto.Field( + proto.ENUM, + number=35, + oneof="error_code", + enum=gage_distinct_error.DistinctErrorEnum.DistinctError, + ) + ) + feed_attribute_reference_error: ( + gage_feed_attribute_reference_error.FeedAttributeReferenceErrorEnum.FeedAttributeReferenceError + ) = proto.Field( + proto.ENUM, + number=36, + oneof="error_code", + enum=gage_feed_attribute_reference_error.FeedAttributeReferenceErrorEnum.FeedAttributeReferenceError, + ) + final_url_expansion_asset_view_error: ( + gage_final_url_expansion_asset_view_error.FinalUrlExpansionAssetViewErrorEnum.FinalUrlExpansionAssetViewError + ) = proto.Field( + proto.ENUM, + number=193, + oneof="error_code", + enum=gage_final_url_expansion_asset_view_error.FinalUrlExpansionAssetViewErrorEnum.FinalUrlExpansionAssetViewError, + ) + function_error: gage_function_error.FunctionErrorEnum.FunctionError = ( + proto.Field( + proto.ENUM, + number=37, + oneof="error_code", + enum=gage_function_error.FunctionErrorEnum.FunctionError, + ) + ) + function_parsing_error: ( + gage_function_parsing_error.FunctionParsingErrorEnum.FunctionParsingError + ) = proto.Field( + proto.ENUM, + number=38, + oneof="error_code", + enum=gage_function_parsing_error.FunctionParsingErrorEnum.FunctionParsingError, + ) + id_error: gage_id_error.IdErrorEnum.IdError = proto.Field( + proto.ENUM, + number=39, + oneof="error_code", + enum=gage_id_error.IdErrorEnum.IdError, + ) + image_error: gage_image_error.ImageErrorEnum.ImageError = proto.Field( + proto.ENUM, + number=40, + oneof="error_code", + enum=gage_image_error.ImageErrorEnum.ImageError, + ) + language_code_error: ( + gage_language_code_error.LanguageCodeErrorEnum.LanguageCodeError + ) = proto.Field( + proto.ENUM, + number=110, + oneof="error_code", + enum=gage_language_code_error.LanguageCodeErrorEnum.LanguageCodeError, + ) + media_bundle_error: ( + gage_media_bundle_error.MediaBundleErrorEnum.MediaBundleError + ) = proto.Field( + proto.ENUM, + number=42, + oneof="error_code", + enum=gage_media_bundle_error.MediaBundleErrorEnum.MediaBundleError, + ) + media_upload_error: ( + gage_media_upload_error.MediaUploadErrorEnum.MediaUploadError + ) = proto.Field( + proto.ENUM, + number=116, + oneof="error_code", + enum=gage_media_upload_error.MediaUploadErrorEnum.MediaUploadError, + ) + media_file_error: ( + gage_media_file_error.MediaFileErrorEnum.MediaFileError + ) = proto.Field( + proto.ENUM, + number=86, + oneof="error_code", + enum=gage_media_file_error.MediaFileErrorEnum.MediaFileError, + ) + merchant_center_error: ( + gage_merchant_center_error.MerchantCenterErrorEnum.MerchantCenterError + ) = proto.Field( + proto.ENUM, + number=162, + oneof="error_code", + enum=gage_merchant_center_error.MerchantCenterErrorEnum.MerchantCenterError, + ) + multiplier_error: ( + gage_multiplier_error.MultiplierErrorEnum.MultiplierError + ) = proto.Field( + proto.ENUM, + number=44, + oneof="error_code", + enum=gage_multiplier_error.MultiplierErrorEnum.MultiplierError, + ) + new_resource_creation_error: ( + gage_new_resource_creation_error.NewResourceCreationErrorEnum.NewResourceCreationError + ) = proto.Field( + proto.ENUM, + number=45, + oneof="error_code", + enum=gage_new_resource_creation_error.NewResourceCreationErrorEnum.NewResourceCreationError, + ) + not_empty_error: gage_not_empty_error.NotEmptyErrorEnum.NotEmptyError = ( + proto.Field( + proto.ENUM, + number=46, + oneof="error_code", + enum=gage_not_empty_error.NotEmptyErrorEnum.NotEmptyError, + ) + ) + null_error: gage_null_error.NullErrorEnum.NullError = proto.Field( + proto.ENUM, + number=47, + oneof="error_code", + enum=gage_null_error.NullErrorEnum.NullError, + ) + operator_error: gage_operator_error.OperatorErrorEnum.OperatorError = ( + proto.Field( + proto.ENUM, + number=48, + oneof="error_code", + enum=gage_operator_error.OperatorErrorEnum.OperatorError, + ) + ) + range_error: gage_range_error.RangeErrorEnum.RangeError = proto.Field( + proto.ENUM, + number=49, + oneof="error_code", + enum=gage_range_error.RangeErrorEnum.RangeError, + ) + recommendation_error: ( + gage_recommendation_error.RecommendationErrorEnum.RecommendationError + ) = proto.Field( + proto.ENUM, + number=58, + oneof="error_code", + enum=gage_recommendation_error.RecommendationErrorEnum.RecommendationError, + ) + recommendation_subscription_error: ( + gage_recommendation_subscription_error.RecommendationSubscriptionErrorEnum.RecommendationSubscriptionError + ) = proto.Field( + proto.ENUM, + number=180, + oneof="error_code", + enum=gage_recommendation_subscription_error.RecommendationSubscriptionErrorEnum.RecommendationSubscriptionError, + ) + region_code_error: ( + gage_region_code_error.RegionCodeErrorEnum.RegionCodeError + ) = proto.Field( + proto.ENUM, + number=51, + oneof="error_code", + enum=gage_region_code_error.RegionCodeErrorEnum.RegionCodeError, + ) + setting_error: gage_setting_error.SettingErrorEnum.SettingError = ( + proto.Field( + proto.ENUM, + number=52, + oneof="error_code", + enum=gage_setting_error.SettingErrorEnum.SettingError, + ) + ) + string_format_error: ( + gage_string_format_error.StringFormatErrorEnum.StringFormatError + ) = proto.Field( + proto.ENUM, + number=53, + oneof="error_code", + enum=gage_string_format_error.StringFormatErrorEnum.StringFormatError, + ) + string_length_error: ( + gage_string_length_error.StringLengthErrorEnum.StringLengthError + ) = proto.Field( + proto.ENUM, + number=54, + oneof="error_code", + enum=gage_string_length_error.StringLengthErrorEnum.StringLengthError, + ) + operation_access_denied_error: ( + gage_operation_access_denied_error.OperationAccessDeniedErrorEnum.OperationAccessDeniedError + ) = proto.Field( + proto.ENUM, + number=55, + oneof="error_code", + enum=gage_operation_access_denied_error.OperationAccessDeniedErrorEnum.OperationAccessDeniedError, + ) + resource_access_denied_error: ( + gage_resource_access_denied_error.ResourceAccessDeniedErrorEnum.ResourceAccessDeniedError + ) = proto.Field( + proto.ENUM, + number=56, + oneof="error_code", + enum=gage_resource_access_denied_error.ResourceAccessDeniedErrorEnum.ResourceAccessDeniedError, + ) + resource_count_limit_exceeded_error: ( + gage_resource_count_limit_exceeded_error.ResourceCountLimitExceededErrorEnum.ResourceCountLimitExceededError + ) = proto.Field( + proto.ENUM, + number=57, + oneof="error_code", + enum=gage_resource_count_limit_exceeded_error.ResourceCountLimitExceededErrorEnum.ResourceCountLimitExceededError, + ) + youtube_video_registration_error: ( + gage_youtube_video_registration_error.YoutubeVideoRegistrationErrorEnum.YoutubeVideoRegistrationError + ) = proto.Field( + proto.ENUM, + number=117, + oneof="error_code", + enum=gage_youtube_video_registration_error.YoutubeVideoRegistrationErrorEnum.YoutubeVideoRegistrationError, + ) + ad_group_bid_modifier_error: ( + gage_ad_group_bid_modifier_error.AdGroupBidModifierErrorEnum.AdGroupBidModifierError + ) = proto.Field( + proto.ENUM, + number=59, + oneof="error_code", + enum=gage_ad_group_bid_modifier_error.AdGroupBidModifierErrorEnum.AdGroupBidModifierError, + ) + context_error: gage_context_error.ContextErrorEnum.ContextError = ( + proto.Field( + proto.ENUM, + number=60, + oneof="error_code", + enum=gage_context_error.ContextErrorEnum.ContextError, + ) + ) + field_error: gage_field_error.FieldErrorEnum.FieldError = proto.Field( + proto.ENUM, + number=61, + oneof="error_code", + enum=gage_field_error.FieldErrorEnum.FieldError, + ) + shared_set_error: ( + gage_shared_set_error.SharedSetErrorEnum.SharedSetError + ) = proto.Field( + proto.ENUM, + number=62, + oneof="error_code", + enum=gage_shared_set_error.SharedSetErrorEnum.SharedSetError, + ) + shared_criterion_error: ( + gage_shared_criterion_error.SharedCriterionErrorEnum.SharedCriterionError + ) = proto.Field( + proto.ENUM, + number=63, + oneof="error_code", + enum=gage_shared_criterion_error.SharedCriterionErrorEnum.SharedCriterionError, + ) + campaign_shared_set_error: ( + gage_campaign_shared_set_error.CampaignSharedSetErrorEnum.CampaignSharedSetError + ) = proto.Field( + proto.ENUM, + number=64, + oneof="error_code", + enum=gage_campaign_shared_set_error.CampaignSharedSetErrorEnum.CampaignSharedSetError, + ) + conversion_action_error: ( + gage_conversion_action_error.ConversionActionErrorEnum.ConversionActionError + ) = proto.Field( + proto.ENUM, + number=65, + oneof="error_code", + enum=gage_conversion_action_error.ConversionActionErrorEnum.ConversionActionError, + ) + conversion_adjustment_upload_error: ( + gage_conversion_adjustment_upload_error.ConversionAdjustmentUploadErrorEnum.ConversionAdjustmentUploadError + ) = proto.Field( + proto.ENUM, + number=115, + oneof="error_code", + enum=gage_conversion_adjustment_upload_error.ConversionAdjustmentUploadErrorEnum.ConversionAdjustmentUploadError, + ) + conversion_custom_variable_error: ( + gage_conversion_custom_variable_error.ConversionCustomVariableErrorEnum.ConversionCustomVariableError + ) = proto.Field( + proto.ENUM, + number=143, + oneof="error_code", + enum=gage_conversion_custom_variable_error.ConversionCustomVariableErrorEnum.ConversionCustomVariableError, + ) + conversion_upload_error: ( + gage_conversion_upload_error.ConversionUploadErrorEnum.ConversionUploadError + ) = proto.Field( + proto.ENUM, + number=111, + oneof="error_code", + enum=gage_conversion_upload_error.ConversionUploadErrorEnum.ConversionUploadError, + ) + conversion_value_rule_error: ( + gage_conversion_value_rule_error.ConversionValueRuleErrorEnum.ConversionValueRuleError + ) = proto.Field( + proto.ENUM, + number=145, + oneof="error_code", + enum=gage_conversion_value_rule_error.ConversionValueRuleErrorEnum.ConversionValueRuleError, + ) + conversion_value_rule_set_error: ( + gage_conversion_value_rule_set_error.ConversionValueRuleSetErrorEnum.ConversionValueRuleSetError + ) = proto.Field( + proto.ENUM, + number=146, + oneof="error_code", + enum=gage_conversion_value_rule_set_error.ConversionValueRuleSetErrorEnum.ConversionValueRuleSetError, + ) + header_error: gage_header_error.HeaderErrorEnum.HeaderError = proto.Field( + proto.ENUM, + number=66, + oneof="error_code", + enum=gage_header_error.HeaderErrorEnum.HeaderError, + ) + database_error: gage_database_error.DatabaseErrorEnum.DatabaseError = ( + proto.Field( + proto.ENUM, + number=67, + oneof="error_code", + enum=gage_database_error.DatabaseErrorEnum.DatabaseError, + ) + ) + policy_finding_error: ( + gage_policy_finding_error.PolicyFindingErrorEnum.PolicyFindingError + ) = proto.Field( + proto.ENUM, + number=68, + oneof="error_code", + enum=gage_policy_finding_error.PolicyFindingErrorEnum.PolicyFindingError, + ) + enum_error: gage_enum_error.EnumErrorEnum.EnumError = proto.Field( + proto.ENUM, + number=70, + oneof="error_code", + enum=gage_enum_error.EnumErrorEnum.EnumError, + ) + keyword_plan_error: ( + gage_keyword_plan_error.KeywordPlanErrorEnum.KeywordPlanError + ) = proto.Field( + proto.ENUM, + number=71, + oneof="error_code", + enum=gage_keyword_plan_error.KeywordPlanErrorEnum.KeywordPlanError, + ) + keyword_plan_campaign_error: ( + gage_keyword_plan_campaign_error.KeywordPlanCampaignErrorEnum.KeywordPlanCampaignError + ) = proto.Field( + proto.ENUM, + number=72, + oneof="error_code", + enum=gage_keyword_plan_campaign_error.KeywordPlanCampaignErrorEnum.KeywordPlanCampaignError, + ) + keyword_plan_campaign_keyword_error: ( + gage_keyword_plan_campaign_keyword_error.KeywordPlanCampaignKeywordErrorEnum.KeywordPlanCampaignKeywordError + ) = proto.Field( + proto.ENUM, + number=132, + oneof="error_code", + enum=gage_keyword_plan_campaign_keyword_error.KeywordPlanCampaignKeywordErrorEnum.KeywordPlanCampaignKeywordError, + ) + keyword_plan_ad_group_error: ( + gage_keyword_plan_ad_group_error.KeywordPlanAdGroupErrorEnum.KeywordPlanAdGroupError + ) = proto.Field( + proto.ENUM, + number=74, + oneof="error_code", + enum=gage_keyword_plan_ad_group_error.KeywordPlanAdGroupErrorEnum.KeywordPlanAdGroupError, + ) + keyword_plan_ad_group_keyword_error: ( + gage_keyword_plan_ad_group_keyword_error.KeywordPlanAdGroupKeywordErrorEnum.KeywordPlanAdGroupKeywordError + ) = proto.Field( + proto.ENUM, + number=133, + oneof="error_code", + enum=gage_keyword_plan_ad_group_keyword_error.KeywordPlanAdGroupKeywordErrorEnum.KeywordPlanAdGroupKeywordError, + ) + keyword_plan_idea_error: ( + gage_keyword_plan_idea_error.KeywordPlanIdeaErrorEnum.KeywordPlanIdeaError + ) = proto.Field( + proto.ENUM, + number=76, + oneof="error_code", + enum=gage_keyword_plan_idea_error.KeywordPlanIdeaErrorEnum.KeywordPlanIdeaError, + ) + account_budget_proposal_error: ( + gage_account_budget_proposal_error.AccountBudgetProposalErrorEnum.AccountBudgetProposalError + ) = proto.Field( + proto.ENUM, + number=77, + oneof="error_code", + enum=gage_account_budget_proposal_error.AccountBudgetProposalErrorEnum.AccountBudgetProposalError, + ) + user_list_error: gage_user_list_error.UserListErrorEnum.UserListError = ( + proto.Field( + proto.ENUM, + number=78, + oneof="error_code", + enum=gage_user_list_error.UserListErrorEnum.UserListError, + ) + ) + change_event_error: ( + gage_change_event_error.ChangeEventErrorEnum.ChangeEventError + ) = proto.Field( + proto.ENUM, + number=136, + oneof="error_code", + enum=gage_change_event_error.ChangeEventErrorEnum.ChangeEventError, + ) + change_status_error: ( + gage_change_status_error.ChangeStatusErrorEnum.ChangeStatusError + ) = proto.Field( + proto.ENUM, + number=79, + oneof="error_code", + enum=gage_change_status_error.ChangeStatusErrorEnum.ChangeStatusError, + ) + feed_error: gage_feed_error.FeedErrorEnum.FeedError = proto.Field( + proto.ENUM, + number=80, + oneof="error_code", + enum=gage_feed_error.FeedErrorEnum.FeedError, + ) + geo_target_constant_suggestion_error: ( + gage_geo_target_constant_suggestion_error.GeoTargetConstantSuggestionErrorEnum.GeoTargetConstantSuggestionError + ) = proto.Field( + proto.ENUM, + number=81, + oneof="error_code", + enum=gage_geo_target_constant_suggestion_error.GeoTargetConstantSuggestionErrorEnum.GeoTargetConstantSuggestionError, + ) + campaign_draft_error: ( + gage_campaign_draft_error.CampaignDraftErrorEnum.CampaignDraftError + ) = proto.Field( + proto.ENUM, + number=82, + oneof="error_code", + enum=gage_campaign_draft_error.CampaignDraftErrorEnum.CampaignDraftError, + ) + feed_item_error: gage_feed_item_error.FeedItemErrorEnum.FeedItemError = ( + proto.Field( + proto.ENUM, + number=83, + oneof="error_code", + enum=gage_feed_item_error.FeedItemErrorEnum.FeedItemError, + ) + ) + label_error: gage_label_error.LabelErrorEnum.LabelError = proto.Field( + proto.ENUM, + number=84, + oneof="error_code", + enum=gage_label_error.LabelErrorEnum.LabelError, + ) + billing_setup_error: ( + gage_billing_setup_error.BillingSetupErrorEnum.BillingSetupError + ) = proto.Field( + proto.ENUM, + number=87, + oneof="error_code", + enum=gage_billing_setup_error.BillingSetupErrorEnum.BillingSetupError, + ) + customer_client_link_error: ( + gage_customer_client_link_error.CustomerClientLinkErrorEnum.CustomerClientLinkError + ) = proto.Field( + proto.ENUM, + number=88, + oneof="error_code", + enum=gage_customer_client_link_error.CustomerClientLinkErrorEnum.CustomerClientLinkError, + ) + customer_manager_link_error: ( + gage_customer_manager_link_error.CustomerManagerLinkErrorEnum.CustomerManagerLinkError + ) = proto.Field( + proto.ENUM, + number=91, + oneof="error_code", + enum=gage_customer_manager_link_error.CustomerManagerLinkErrorEnum.CustomerManagerLinkError, + ) + feed_mapping_error: ( + gage_feed_mapping_error.FeedMappingErrorEnum.FeedMappingError + ) = proto.Field( + proto.ENUM, + number=92, + oneof="error_code", + enum=gage_feed_mapping_error.FeedMappingErrorEnum.FeedMappingError, + ) + customer_feed_error: ( + gage_customer_feed_error.CustomerFeedErrorEnum.CustomerFeedError + ) = proto.Field( + proto.ENUM, + number=93, + oneof="error_code", + enum=gage_customer_feed_error.CustomerFeedErrorEnum.CustomerFeedError, + ) + ad_group_feed_error: ( + gage_ad_group_feed_error.AdGroupFeedErrorEnum.AdGroupFeedError + ) = proto.Field( + proto.ENUM, + number=94, + oneof="error_code", + enum=gage_ad_group_feed_error.AdGroupFeedErrorEnum.AdGroupFeedError, + ) + campaign_feed_error: ( + gage_campaign_feed_error.CampaignFeedErrorEnum.CampaignFeedError + ) = proto.Field( + proto.ENUM, + number=96, + oneof="error_code", + enum=gage_campaign_feed_error.CampaignFeedErrorEnum.CampaignFeedError, + ) + custom_interest_error: ( + gage_custom_interest_error.CustomInterestErrorEnum.CustomInterestError + ) = proto.Field( + proto.ENUM, + number=97, + oneof="error_code", + enum=gage_custom_interest_error.CustomInterestErrorEnum.CustomInterestError, + ) + campaign_experiment_error: ( + gage_campaign_experiment_error.CampaignExperimentErrorEnum.CampaignExperimentError + ) = proto.Field( + proto.ENUM, + number=98, + oneof="error_code", + enum=gage_campaign_experiment_error.CampaignExperimentErrorEnum.CampaignExperimentError, + ) + extension_feed_item_error: ( + gage_extension_feed_item_error.ExtensionFeedItemErrorEnum.ExtensionFeedItemError + ) = proto.Field( + proto.ENUM, + number=100, + oneof="error_code", + enum=gage_extension_feed_item_error.ExtensionFeedItemErrorEnum.ExtensionFeedItemError, + ) + ad_parameter_error: ( + gage_ad_parameter_error.AdParameterErrorEnum.AdParameterError + ) = proto.Field( + proto.ENUM, + number=101, + oneof="error_code", + enum=gage_ad_parameter_error.AdParameterErrorEnum.AdParameterError, + ) + feed_item_validation_error: ( + gage_feed_item_validation_error.FeedItemValidationErrorEnum.FeedItemValidationError + ) = proto.Field( + proto.ENUM, + number=102, + oneof="error_code", + enum=gage_feed_item_validation_error.FeedItemValidationErrorEnum.FeedItemValidationError, + ) + extension_setting_error: ( + gage_extension_setting_error.ExtensionSettingErrorEnum.ExtensionSettingError + ) = proto.Field( + proto.ENUM, + number=103, + oneof="error_code", + enum=gage_extension_setting_error.ExtensionSettingErrorEnum.ExtensionSettingError, + ) + feed_item_set_error: ( + gage_feed_item_set_error.FeedItemSetErrorEnum.FeedItemSetError + ) = proto.Field( + proto.ENUM, + number=140, + oneof="error_code", + enum=gage_feed_item_set_error.FeedItemSetErrorEnum.FeedItemSetError, + ) + feed_item_set_link_error: ( + gage_feed_item_set_link_error.FeedItemSetLinkErrorEnum.FeedItemSetLinkError + ) = proto.Field( + proto.ENUM, + number=141, + oneof="error_code", + enum=gage_feed_item_set_link_error.FeedItemSetLinkErrorEnum.FeedItemSetLinkError, + ) + feed_item_target_error: ( + gage_feed_item_target_error.FeedItemTargetErrorEnum.FeedItemTargetError + ) = proto.Field( + proto.ENUM, + number=104, + oneof="error_code", + enum=gage_feed_item_target_error.FeedItemTargetErrorEnum.FeedItemTargetError, + ) + policy_violation_error: ( + gage_policy_violation_error.PolicyViolationErrorEnum.PolicyViolationError + ) = proto.Field( + proto.ENUM, + number=105, + oneof="error_code", + enum=gage_policy_violation_error.PolicyViolationErrorEnum.PolicyViolationError, + ) + partial_failure_error: ( + gage_partial_failure_error.PartialFailureErrorEnum.PartialFailureError + ) = proto.Field( + proto.ENUM, + number=112, + oneof="error_code", + enum=gage_partial_failure_error.PartialFailureErrorEnum.PartialFailureError, + ) + click_view_error: ( + gage_click_view_error.ClickViewErrorEnum.ClickViewError + ) = proto.Field( + proto.ENUM, + number=113, + oneof="error_code", + enum=gage_click_view_error.ClickViewErrorEnum.ClickViewError, + ) + policy_validation_parameter_error: ( + gage_policy_validation_parameter_error.PolicyValidationParameterErrorEnum.PolicyValidationParameterError + ) = proto.Field( + proto.ENUM, + number=114, + oneof="error_code", + enum=gage_policy_validation_parameter_error.PolicyValidationParameterErrorEnum.PolicyValidationParameterError, + ) + size_limit_error: ( + gage_size_limit_error.SizeLimitErrorEnum.SizeLimitError + ) = proto.Field( + proto.ENUM, + number=118, + oneof="error_code", + enum=gage_size_limit_error.SizeLimitErrorEnum.SizeLimitError, + ) + offline_user_data_job_error: ( + gage_offline_user_data_job_error.OfflineUserDataJobErrorEnum.OfflineUserDataJobError + ) = proto.Field( + proto.ENUM, + number=119, + oneof="error_code", + enum=gage_offline_user_data_job_error.OfflineUserDataJobErrorEnum.OfflineUserDataJobError, + ) + not_allowlisted_error: ( + gage_not_allowlisted_error.NotAllowlistedErrorEnum.NotAllowlistedError + ) = proto.Field( + proto.ENUM, + number=137, + oneof="error_code", + enum=gage_not_allowlisted_error.NotAllowlistedErrorEnum.NotAllowlistedError, + ) + manager_link_error: ( + gage_manager_link_error.ManagerLinkErrorEnum.ManagerLinkError + ) = proto.Field( + proto.ENUM, + number=121, + oneof="error_code", + enum=gage_manager_link_error.ManagerLinkErrorEnum.ManagerLinkError, + ) + currency_code_error: ( + gage_currency_code_error.CurrencyCodeErrorEnum.CurrencyCodeError + ) = proto.Field( + proto.ENUM, + number=122, + oneof="error_code", + enum=gage_currency_code_error.CurrencyCodeErrorEnum.CurrencyCodeError, + ) + experiment_error: ( + gage_experiment_error.ExperimentErrorEnum.ExperimentError + ) = proto.Field( + proto.ENUM, + number=123, + oneof="error_code", + enum=gage_experiment_error.ExperimentErrorEnum.ExperimentError, + ) + access_invitation_error: ( + gage_access_invitation_error.AccessInvitationErrorEnum.AccessInvitationError + ) = proto.Field( + proto.ENUM, + number=124, + oneof="error_code", + enum=gage_access_invitation_error.AccessInvitationErrorEnum.AccessInvitationError, + ) + reach_plan_error: ( + gage_reach_plan_error.ReachPlanErrorEnum.ReachPlanError + ) = proto.Field( + proto.ENUM, + number=125, + oneof="error_code", + enum=gage_reach_plan_error.ReachPlanErrorEnum.ReachPlanError, + ) + invoice_error: gage_invoice_error.InvoiceErrorEnum.InvoiceError = ( + proto.Field( + proto.ENUM, + number=126, + oneof="error_code", + enum=gage_invoice_error.InvoiceErrorEnum.InvoiceError, + ) + ) + payments_account_error: ( + gage_payments_account_error.PaymentsAccountErrorEnum.PaymentsAccountError + ) = proto.Field( + proto.ENUM, + number=127, + oneof="error_code", + enum=gage_payments_account_error.PaymentsAccountErrorEnum.PaymentsAccountError, + ) + time_zone_error: gage_time_zone_error.TimeZoneErrorEnum.TimeZoneError = ( + proto.Field( + proto.ENUM, + number=128, + oneof="error_code", + enum=gage_time_zone_error.TimeZoneErrorEnum.TimeZoneError, + ) + ) + asset_link_error: ( + gage_asset_link_error.AssetLinkErrorEnum.AssetLinkError + ) = proto.Field( + proto.ENUM, + number=129, + oneof="error_code", + enum=gage_asset_link_error.AssetLinkErrorEnum.AssetLinkError, + ) + user_data_error: gage_user_data_error.UserDataErrorEnum.UserDataError = ( + proto.Field( + proto.ENUM, + number=130, + oneof="error_code", + enum=gage_user_data_error.UserDataErrorEnum.UserDataError, + ) + ) + batch_job_error: gage_batch_job_error.BatchJobErrorEnum.BatchJobError = ( + proto.Field( + proto.ENUM, + number=131, + oneof="error_code", + enum=gage_batch_job_error.BatchJobErrorEnum.BatchJobError, + ) + ) + account_link_error: ( + gage_account_link_error.AccountLinkErrorEnum.AccountLinkError + ) = proto.Field( + proto.ENUM, + number=134, + oneof="error_code", + enum=gage_account_link_error.AccountLinkErrorEnum.AccountLinkError, + ) + third_party_app_analytics_link_error: ( + gage_third_party_app_analytics_link_error.ThirdPartyAppAnalyticsLinkErrorEnum.ThirdPartyAppAnalyticsLinkError + ) = proto.Field( + proto.ENUM, + number=135, + oneof="error_code", + enum=gage_third_party_app_analytics_link_error.ThirdPartyAppAnalyticsLinkErrorEnum.ThirdPartyAppAnalyticsLinkError, + ) + customer_user_access_error: ( + gage_customer_user_access_error.CustomerUserAccessErrorEnum.CustomerUserAccessError + ) = proto.Field( + proto.ENUM, + number=138, + oneof="error_code", + enum=gage_customer_user_access_error.CustomerUserAccessErrorEnum.CustomerUserAccessError, + ) + custom_audience_error: ( + gage_custom_audience_error.CustomAudienceErrorEnum.CustomAudienceError + ) = proto.Field( + proto.ENUM, + number=139, + oneof="error_code", + enum=gage_custom_audience_error.CustomAudienceErrorEnum.CustomAudienceError, + ) + audience_error: gage_audience_error.AudienceErrorEnum.AudienceError = ( + proto.Field( + proto.ENUM, + number=164, + oneof="error_code", + enum=gage_audience_error.AudienceErrorEnum.AudienceError, + ) + ) + search_term_insight_error: ( + gage_search_term_insight_error.SearchTermInsightErrorEnum.SearchTermInsightError + ) = proto.Field( + proto.ENUM, + number=174, + oneof="error_code", + enum=gage_search_term_insight_error.SearchTermInsightErrorEnum.SearchTermInsightError, + ) + smart_campaign_error: ( + gage_smart_campaign_error.SmartCampaignErrorEnum.SmartCampaignError + ) = proto.Field( + proto.ENUM, + number=147, + oneof="error_code", + enum=gage_smart_campaign_error.SmartCampaignErrorEnum.SmartCampaignError, + ) + experiment_arm_error: ( + gage_experiment_arm_error.ExperimentArmErrorEnum.ExperimentArmError + ) = proto.Field( + proto.ENUM, + number=156, + oneof="error_code", + enum=gage_experiment_arm_error.ExperimentArmErrorEnum.ExperimentArmError, + ) + audience_insights_error: ( + gage_audience_insights_error.AudienceInsightsErrorEnum.AudienceInsightsError + ) = proto.Field( + proto.ENUM, + number=167, + oneof="error_code", + enum=gage_audience_insights_error.AudienceInsightsErrorEnum.AudienceInsightsError, + ) + product_link_error: ( + gage_product_link_error.ProductLinkErrorEnum.ProductLinkError + ) = proto.Field( + proto.ENUM, + number=169, + oneof="error_code", + enum=gage_product_link_error.ProductLinkErrorEnum.ProductLinkError, + ) + data_link_error: gage_data_link_error.DataLinkErrorEnum.DataLinkError = ( + proto.Field( + proto.ENUM, + number=187, + oneof="error_code", + enum=gage_data_link_error.DataLinkErrorEnum.DataLinkError, + ) + ) + customer_sk_ad_network_conversion_value_schema_error: ( + gage_customer_sk_ad_network_conversion_value_schema_error.CustomerSkAdNetworkConversionValueSchemaErrorEnum.CustomerSkAdNetworkConversionValueSchemaError + ) = proto.Field( + proto.ENUM, + number=170, + oneof="error_code", + enum=gage_customer_sk_ad_network_conversion_value_schema_error.CustomerSkAdNetworkConversionValueSchemaErrorEnum.CustomerSkAdNetworkConversionValueSchemaError, + ) + currency_error: gage_currency_error.CurrencyErrorEnum.CurrencyError = ( + proto.Field( + proto.ENUM, + number=171, + oneof="error_code", + enum=gage_currency_error.CurrencyErrorEnum.CurrencyError, + ) + ) + asset_group_signal_error: ( + gage_asset_group_signal_error.AssetGroupSignalErrorEnum.AssetGroupSignalError + ) = proto.Field( + proto.ENUM, + number=176, + oneof="error_code", + enum=gage_asset_group_signal_error.AssetGroupSignalErrorEnum.AssetGroupSignalError, + ) + product_link_invitation_error: ( + gage_product_link_invitation_error.ProductLinkInvitationErrorEnum.ProductLinkInvitationError + ) = proto.Field( + proto.ENUM, + number=177, + oneof="error_code", + enum=gage_product_link_invitation_error.ProductLinkInvitationErrorEnum.ProductLinkInvitationError, + ) + customer_lifecycle_goal_error: ( + gage_customer_lifecycle_goal_error.CustomerLifecycleGoalErrorEnum.CustomerLifecycleGoalError + ) = proto.Field( + proto.ENUM, + number=178, + oneof="error_code", + enum=gage_customer_lifecycle_goal_error.CustomerLifecycleGoalErrorEnum.CustomerLifecycleGoalError, + ) + campaign_lifecycle_goal_error: ( + gage_campaign_lifecycle_goal_error.CampaignLifecycleGoalErrorEnum.CampaignLifecycleGoalError + ) = proto.Field( + proto.ENUM, + number=179, + oneof="error_code", + enum=gage_campaign_lifecycle_goal_error.CampaignLifecycleGoalErrorEnum.CampaignLifecycleGoalError, + ) + identity_verification_error: ( + gage_identity_verification_error.IdentityVerificationErrorEnum.IdentityVerificationError + ) = proto.Field( + proto.ENUM, + number=181, + oneof="error_code", + enum=gage_identity_verification_error.IdentityVerificationErrorEnum.IdentityVerificationError, + ) + user_list_customer_type_error: ( + gage_user_list_customer_type_error.UserListCustomerTypeErrorEnum.UserListCustomerTypeError + ) = proto.Field( + proto.ENUM, + number=183, + oneof="error_code", + enum=gage_user_list_customer_type_error.UserListCustomerTypeErrorEnum.UserListCustomerTypeError, + ) + shopping_product_error: ( + gage_shopping_product_error.ShoppingProductErrorEnum.ShoppingProductError + ) = proto.Field( + proto.ENUM, + number=184, + oneof="error_code", + enum=gage_shopping_product_error.ShoppingProductErrorEnum.ShoppingProductError, + ) + automatically_created_asset_removal_error: ( + gage_automatically_created_asset_removal_error.AutomaticallyCreatedAssetRemovalErrorEnum.AutomaticallyCreatedAssetRemovalError + ) = proto.Field( + proto.ENUM, + number=185, + oneof="error_code", + enum=gage_automatically_created_asset_removal_error.AutomaticallyCreatedAssetRemovalErrorEnum.AutomaticallyCreatedAssetRemovalError, + ) + shareable_preview_error: ( + gage_shareable_preview_error.ShareablePreviewErrorEnum.ShareablePreviewError + ) = proto.Field( + proto.ENUM, + number=186, + oneof="error_code", + enum=gage_shareable_preview_error.ShareablePreviewErrorEnum.ShareablePreviewError, + ) + campaign_goal_config_error: ( + gage_campaign_goal_config_error.CampaignGoalConfigErrorEnum.CampaignGoalConfigError + ) = proto.Field( + proto.ENUM, + number=188, + oneof="error_code", + enum=gage_campaign_goal_config_error.CampaignGoalConfigErrorEnum.CampaignGoalConfigError, + ) + goal_error: gage_goal_error.GoalErrorEnum.GoalError = proto.Field( + proto.ENUM, + number=189, + oneof="error_code", + enum=gage_goal_error.GoalErrorEnum.GoalError, + ) + brand_guidelines_migration_error: ( + gage_brand_guidelines_migration_error.BrandGuidelinesMigrationErrorEnum.BrandGuidelinesMigrationError + ) = proto.Field( + proto.ENUM, + number=191, + oneof="error_code", + enum=gage_brand_guidelines_migration_error.BrandGuidelinesMigrationErrorEnum.BrandGuidelinesMigrationError, + ) + asset_generation_error: ( + gage_asset_generation_error.AssetGenerationErrorEnum.AssetGenerationError + ) = proto.Field( + proto.ENUM, + number=194, + oneof="error_code", + enum=gage_asset_generation_error.AssetGenerationErrorEnum.AssetGenerationError, + ) + benchmarks_error: ( + gage_benchmarks_error.BenchmarksErrorEnum.BenchmarksError + ) = proto.Field( + proto.ENUM, + number=195, + oneof="error_code", + enum=gage_benchmarks_error.BenchmarksErrorEnum.BenchmarksError, + ) + incentive_error: gage_incentive_error.IncentiveErrorEnum.IncentiveError = ( + proto.Field( + proto.ENUM, + number=197, + oneof="error_code", + enum=gage_incentive_error.IncentiveErrorEnum.IncentiveError, + ) + ) + content_creator_insights_error: ( + gage_content_creator_insights_error.ContentCreatorInsightsErrorEnum.ContentCreatorInsightsError + ) = proto.Field( + proto.ENUM, + number=198, + oneof="error_code", + enum=gage_content_creator_insights_error.ContentCreatorInsightsErrorEnum.ContentCreatorInsightsError, + ) + video_reservation_error: ( + gage_video_reservation_error.VideoReservationErrorEnum.VideoReservationError + ) = proto.Field( + proto.ENUM, + number=199, + oneof="error_code", + enum=gage_video_reservation_error.VideoReservationErrorEnum.VideoReservationError, + ) + + +class ErrorLocation(proto.Message): + r"""Describes the part of the request proto that caused the + error. + + Attributes: + field_path_elements (MutableSequence[google.ads.googleads.v24.errors.types.ErrorLocation.FieldPathElement]): + A field path that indicates which field was + invalid in the request. + """ + + class FieldPathElement(proto.Message): + r"""A part of a field path. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + field_name (str): + The name of a field or a oneof + index (int): + If field_name is a repeated field, this is the element that + failed + + This field is a member of `oneof`_ ``_index``. + """ + + field_name: str = proto.Field( + proto.STRING, + number=1, + ) + index: int = proto.Field( + proto.INT32, + number=3, + optional=True, + ) + + field_path_elements: MutableSequence[FieldPathElement] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message=FieldPathElement, + ) + ) + + +class ErrorDetails(proto.Message): + r"""Additional error details. + + Attributes: + unpublished_error_code (str): + The error code that should have been + returned, but wasn't. This is used when the + error code is not published in the client + specified version. + policy_violation_details (google.ads.googleads.v24.errors.types.PolicyViolationDetails): + Describes an ad policy violation. + policy_finding_details (google.ads.googleads.v24.errors.types.PolicyFindingDetails): + Describes policy violation findings. + quota_error_details (google.ads.googleads.v24.errors.types.QuotaErrorDetails): + Details on the quota error, including the + scope (account or developer), the rate bucket + name and the retry delay. + resource_count_details (google.ads.googleads.v24.errors.types.ResourceCountDetails): + Details for a resource count limit exceeded + error. + budget_per_day_minimum_error_details (google.ads.googleads.v24.errors.types.BudgetPerDayMinimumErrorDetails): + Details for a budget below per-day minimum + error. + reservation_error_details (google.ads.googleads.v24.errors.types.ReservationErrorDetails): + Details for a reservation error. + """ + + unpublished_error_code: str = proto.Field( + proto.STRING, + number=1, + ) + policy_violation_details: "PolicyViolationDetails" = proto.Field( + proto.MESSAGE, + number=2, + message="PolicyViolationDetails", + ) + policy_finding_details: "PolicyFindingDetails" = proto.Field( + proto.MESSAGE, + number=3, + message="PolicyFindingDetails", + ) + quota_error_details: "QuotaErrorDetails" = proto.Field( + proto.MESSAGE, + number=4, + message="QuotaErrorDetails", + ) + resource_count_details: "ResourceCountDetails" = proto.Field( + proto.MESSAGE, + number=5, + message="ResourceCountDetails", + ) + budget_per_day_minimum_error_details: "BudgetPerDayMinimumErrorDetails" = ( + proto.Field( + proto.MESSAGE, + number=6, + message="BudgetPerDayMinimumErrorDetails", + ) + ) + reservation_error_details: "ReservationErrorDetails" = proto.Field( + proto.MESSAGE, + number=7, + message="ReservationErrorDetails", + ) + + +class PolicyViolationDetails(proto.Message): + r"""Error returned as part of a mutate response. + This error indicates single policy violation by some text in one + of the fields. + + Attributes: + external_policy_description (str): + Human readable description of policy + violation. + key (google.ads.googleads.v24.common.types.PolicyViolationKey): + Unique identifier for this violation. + If policy is exemptible, this key may be used to + request exemption. + external_policy_name (str): + Human readable name of the policy. + is_exemptible (bool): + Whether user can file an exemption request + for this violation. + """ + + external_policy_description: str = proto.Field( + proto.STRING, + number=2, + ) + key: policy.PolicyViolationKey = proto.Field( + proto.MESSAGE, + number=4, + message=policy.PolicyViolationKey, + ) + external_policy_name: str = proto.Field( + proto.STRING, + number=5, + ) + is_exemptible: bool = proto.Field( + proto.BOOL, + number=6, + ) + + +class PolicyFindingDetails(proto.Message): + r"""Error returned as part of a mutate response. + This error indicates one or more policy findings in the fields + of a resource. + + Attributes: + policy_topic_entries (MutableSequence[google.ads.googleads.v24.common.types.PolicyTopicEntry]): + The list of policy topics for the resource. Contains the + PROHIBITED or FULLY_LIMITED policy topic entries that + prevented the resource from being saved (among any other + entries the resource may also have). + """ + + policy_topic_entries: MutableSequence[policy.PolicyTopicEntry] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=policy.PolicyTopicEntry, + ) + ) + + +class QuotaErrorDetails(proto.Message): + r"""Additional quota error details when there is QuotaError. + + Attributes: + rate_scope (google.ads.googleads.v24.errors.types.QuotaErrorDetails.QuotaRateScope): + The rate scope of the quota limit. + rate_name (str): + The high level description of the quota + bucket. Examples are "Get requests for standard + access" or "Requests per account". + retry_delay (google.protobuf.duration_pb2.Duration): + Backoff period that customers should wait + before sending next request. + """ + + class QuotaRateScope(proto.Enum): + r"""Enum of possible scopes that quota buckets belong to. + + Values: + UNSPECIFIED (0): + Unspecified enum + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ACCOUNT (2): + Per customer account quota + DEVELOPER (3): + Per project or DevToken quota + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ACCOUNT = 2 + DEVELOPER = 3 + + rate_scope: QuotaRateScope = proto.Field( + proto.ENUM, + number=1, + enum=QuotaRateScope, + ) + rate_name: str = proto.Field( + proto.STRING, + number=2, + ) + retry_delay: duration_pb2.Duration = proto.Field( + proto.MESSAGE, + number=3, + message=duration_pb2.Duration, + ) + + +class ResourceCountDetails(proto.Message): + r"""Error details returned when an resource count limit was + exceeded. + + Attributes: + enclosing_id (str): + The ID of the resource whose limit was + exceeded. External customer ID if the limit is + for a customer. + enclosing_resource (str): + The name of the resource (Customer, Campaign + etc.) whose limit was exceeded. + limit (int): + The limit which was exceeded. + limit_type (google.ads.googleads.v24.enums.types.ResourceLimitTypeEnum.ResourceLimitType): + The resource limit type which was exceeded. + existing_count (int): + The count of existing entities. + """ + + enclosing_id: str = proto.Field( + proto.STRING, + number=1, + ) + enclosing_resource: str = proto.Field( + proto.STRING, + number=5, + ) + limit: int = proto.Field( + proto.INT32, + number=2, + ) + limit_type: resource_limit_type.ResourceLimitTypeEnum.ResourceLimitType = ( + proto.Field( + proto.ENUM, + number=3, + enum=resource_limit_type.ResourceLimitTypeEnum.ResourceLimitType, + ) + ) + existing_count: int = proto.Field( + proto.INT32, + number=4, + ) + + +class BudgetPerDayMinimumErrorDetails(proto.Message): + r"""Error details for a budget below per-day minimum error. + + Attributes: + currency_code (str): + The advertiser's currency, represented as a + three-letter ISO 4217 currency code (such as + "USD"). + budget_per_day_minimum_micros (int): + The minimum budget required by the campaign + per day, in micros of the advertiser currency. + Applies to both daily and custom budgets. + minimum_budget_amount_micros (int): + The minimum value for the budget's amount + field required by the campaign, in micros of the + advertiser currency. Only set if this error is + caused by the amount field value. + minimum_budget_total_amount_micros (int): + The minimum value for the budget's total_amount field + required by the campaign given its configured start and end + time, in micros of the advertiser currency. Only set if this + error is caused by the total_amount field value. + failed_budget_amount_micros (int): + The budget amount value that was rejected as + too low, in micros of the advertiser currency. + Only set if this error is caused by the amount + field value. + failed_budget_total_amount_micros (int): + The budget total_amount value that was rejected as too low, + in micros of the advertiser currency. Only set if this error + is caused by the total_amount field value. + """ + + currency_code: str = proto.Field( + proto.STRING, + number=1, + ) + budget_per_day_minimum_micros: int = proto.Field( + proto.INT64, + number=2, + ) + minimum_budget_amount_micros: int = proto.Field( + proto.INT64, + number=3, + ) + minimum_budget_total_amount_micros: int = proto.Field( + proto.INT64, + number=4, + ) + failed_budget_amount_micros: int = proto.Field( + proto.INT64, + number=5, + ) + failed_budget_total_amount_micros: int = proto.Field( + proto.INT64, + number=6, + ) + + +class ReservationErrorDetails(proto.Message): + r"""Error details returned for BookCampaigns or QuoteCampaigns. + + Attributes: + campaign (str): + The resource name of the campaign affected by the error, as + it was specified in the request. It could contain a + temporary ID. Format: + customers/{customer_id}/campaigns/{campaign_id} + quotes (MutableSequence[google.ads.googleads.v24.common.types.CampaignReservationQuote]): + A list of proposed quotes for all the + campaigns in the request. For the failed + campaign, the given quote allows booking. + quote_signature (str): + A signature of the returned quote. The + signature covers the entire set of campaigns in + the request, and can be used in subsequent + requests for the same set of campaigns. + """ + + campaign: str = proto.Field( + proto.STRING, + number=1, + ) + quotes: MutableSequence[ + campaign_reservation_quote.CampaignReservationQuote + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=campaign_reservation_quote.CampaignReservationQuote, + ) + quote_signature: str = proto.Field( + proto.STRING, + number=3, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/experiment_arm_error.py b/google/ads/googleads/v24/errors/types/experiment_arm_error.py new file mode 100644 index 000000000..c48e3330c --- /dev/null +++ b/google/ads/googleads/v24/errors/types/experiment_arm_error.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ExperimentArmErrorEnum", + }, +) + + +class ExperimentArmErrorEnum(proto.Message): + r"""Container for enum describing possible experiment arm error.""" + + class ExperimentArmError(proto.Enum): + r"""Enum describing possible experiment arm errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + EXPERIMENT_ARM_COUNT_LIMIT_EXCEEDED (2): + Number of experiment arms is above limit. + INVALID_CAMPAIGN_STATUS (3): + Cannot add campaign with invalid status to + the experiment arm. + DUPLICATE_EXPERIMENT_ARM_NAME (4): + Cannot add duplicate experiment arm name in + one experiment. + CANNOT_SET_TREATMENT_ARM_CAMPAIGN (5): + Cannot set campaigns of treatment experiment + arm. + CANNOT_MODIFY_CAMPAIGN_IDS (6): + Cannot edit campaign ids in trial arms in non + SETUP experiment. + CANNOT_MODIFY_CAMPAIGN_WITHOUT_SUFFIX_SET (7): + Cannot modify the campaigns in the control + arm if there is not a suffix set in the trial. + CANNOT_MUTATE_TRAFFIC_SPLIT_AFTER_START (8): + Traffic split related settings (like traffic + share bounds) can't be modified after the trial + has started. + CANNOT_ADD_CAMPAIGN_WITH_SHARED_BUDGET (9): + Cannot use shared budget on experiment's + control campaign. + CANNOT_ADD_CAMPAIGN_WITH_CUSTOM_BUDGET (10): + Cannot use custom budget on experiment's + control campaigns. + CANNOT_ADD_CAMPAIGNS_WITH_DYNAMIC_ASSETS_ENABLED (11): + Cannot have enable_dynamic_assets turned on in experiment's + campaigns. + UNSUPPORTED_CAMPAIGN_ADVERTISING_CHANNEL_SUB_TYPE (12): + Cannot use campaign's advertising channel sub + type in experiment. + CANNOT_ADD_BASE_CAMPAIGN_WITH_DATE_RANGE (13): + Experiment date range must be within base + campaign's date range. + BIDDING_STRATEGY_NOT_SUPPORTED_IN_EXPERIMENTS (14): + Bidding strategy is not supported in + experiments. + TRAFFIC_SPLIT_NOT_SUPPORTED_FOR_CHANNEL_TYPE (15): + Traffic split is not supported for some + channel types. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EXPERIMENT_ARM_COUNT_LIMIT_EXCEEDED = 2 + INVALID_CAMPAIGN_STATUS = 3 + DUPLICATE_EXPERIMENT_ARM_NAME = 4 + CANNOT_SET_TREATMENT_ARM_CAMPAIGN = 5 + CANNOT_MODIFY_CAMPAIGN_IDS = 6 + CANNOT_MODIFY_CAMPAIGN_WITHOUT_SUFFIX_SET = 7 + CANNOT_MUTATE_TRAFFIC_SPLIT_AFTER_START = 8 + CANNOT_ADD_CAMPAIGN_WITH_SHARED_BUDGET = 9 + CANNOT_ADD_CAMPAIGN_WITH_CUSTOM_BUDGET = 10 + CANNOT_ADD_CAMPAIGNS_WITH_DYNAMIC_ASSETS_ENABLED = 11 + UNSUPPORTED_CAMPAIGN_ADVERTISING_CHANNEL_SUB_TYPE = 12 + CANNOT_ADD_BASE_CAMPAIGN_WITH_DATE_RANGE = 13 + BIDDING_STRATEGY_NOT_SUPPORTED_IN_EXPERIMENTS = 14 + TRAFFIC_SPLIT_NOT_SUPPORTED_FOR_CHANNEL_TYPE = 15 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/experiment_error.py b/google/ads/googleads/v24/errors/types/experiment_error.py new file mode 100644 index 000000000..e706fd102 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/experiment_error.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ExperimentErrorEnum", + }, +) + + +class ExperimentErrorEnum(proto.Message): + r"""Container for enum describing possible experiment error.""" + + class ExperimentError(proto.Enum): + r"""Enum describing possible experiment errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CANNOT_SET_START_DATE_IN_PAST (2): + The start date of an experiment cannot be set + in the past. Use a start date in the future. + END_DATE_BEFORE_START_DATE (3): + The end date of an experiment is before its + start date. Use an end date after the start + date. + START_DATE_TOO_FAR_IN_FUTURE (4): + The start date of an experiment is too far in + the future. Use a start date no more than 1 year + in the future. + DUPLICATE_EXPERIMENT_NAME (5): + The experiment has the same name as an + existing active experiment. + CANNOT_MODIFY_REMOVED_EXPERIMENT (6): + Experiments can only be modified when they + are ENABLED. + START_DATE_ALREADY_PASSED (7): + The start date of an experiment cannot be + modified if the existing start date has already + passed. + CANNOT_SET_END_DATE_IN_PAST (8): + The end date of an experiment cannot be set + in the past. + CANNOT_SET_STATUS_TO_REMOVED (9): + The status of an experiment cannot be set to + REMOVED. + CANNOT_MODIFY_PAST_END_DATE (10): + The end date of an expired experiment cannot + be modified. + INVALID_STATUS (11): + The status is invalid. + INVALID_CAMPAIGN_CHANNEL_TYPE (12): + Experiment arm contains campaigns with + invalid advertising channel type. + OVERLAPPING_MEMBERS_AND_DATE_RANGE (13): + A pair of trials share members and have + overlapping date ranges. + INVALID_TRIAL_ARM_TRAFFIC_SPLIT (14): + Experiment arm contains invalid traffic + split. + TRAFFIC_SPLIT_OVERLAPPING (15): + Experiment contains trial arms with + overlapping traffic split. + SUM_TRIAL_ARM_TRAFFIC_UNEQUALS_TO_TRIAL_TRAFFIC_SPLIT_DENOMINATOR (16): + The total traffic split of trial arms is not + equal to 100. + CANNOT_MODIFY_TRAFFIC_SPLIT_AFTER_START (17): + Traffic split related settings (like traffic + share bounds) can't be modified after the + experiment has started. + EXPERIMENT_NOT_FOUND (18): + The experiment could not be found. + EXPERIMENT_NOT_YET_STARTED (19): + Experiment has not begun. + CANNOT_HAVE_MULTIPLE_CONTROL_ARMS (20): + The experiment cannot have more than one + control arm. + IN_DESIGN_CAMPAIGNS_NOT_SET (21): + The experiment doesn't set in-design + campaigns. + CANNOT_SET_STATUS_TO_GRADUATED (22): + Clients must use the graduate action to + graduate experiments and cannot set the status + to GRADUATED directly. + CANNOT_CREATE_EXPERIMENT_CAMPAIGN_WITH_SHARED_BUDGET (23): + Cannot use shared budget on base campaign + when scheduling an experiment. + CANNOT_CREATE_EXPERIMENT_CAMPAIGN_WITH_CUSTOM_BUDGET (24): + Cannot use custom budget on base campaign + when scheduling an experiment. + STATUS_TRANSITION_INVALID (25): + Invalid status transition. + DUPLICATE_EXPERIMENT_CAMPAIGN_NAME (26): + The experiment campaign name conflicts with a + pre-existing campaign. + CANNOT_REMOVE_IN_CREATION_EXPERIMENT (27): + Cannot remove in creation experiments. + CANNOT_ADD_CAMPAIGN_WITH_DEPRECATED_AD_TYPES (28): + Cannot add campaign with deprecated ad types. Deprecated ad + types: ENHANCED_DISPLAY, GALLERY, GMAIL, KEYWORDLESS, TEXT. + CANNOT_ENABLE_SYNC_FOR_UNSUPPORTED_EXPERIMENT_TYPE (29): + Sync can only be enabled for supported experiment types. + Supported experiment types: SEARCH_CUSTOM, DISPLAY_CUSTOM, + DISPLAY_AUTOMATED_BIDDING_STRATEGY, + SEARCH_AUTOMATED_BIDDING_STRATEGY. + INVALID_DURATION_FOR_AN_EXPERIMENT (30): + Experiment length cannot be longer than max + length. + MISSING_EU_POLITICAL_ADVERTISING_SELF_DECLARATION (31): + The experiment's campaigns must self-declare + whether they contain political advertising that + targets the European Union. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CANNOT_SET_START_DATE_IN_PAST = 2 + END_DATE_BEFORE_START_DATE = 3 + START_DATE_TOO_FAR_IN_FUTURE = 4 + DUPLICATE_EXPERIMENT_NAME = 5 + CANNOT_MODIFY_REMOVED_EXPERIMENT = 6 + START_DATE_ALREADY_PASSED = 7 + CANNOT_SET_END_DATE_IN_PAST = 8 + CANNOT_SET_STATUS_TO_REMOVED = 9 + CANNOT_MODIFY_PAST_END_DATE = 10 + INVALID_STATUS = 11 + INVALID_CAMPAIGN_CHANNEL_TYPE = 12 + OVERLAPPING_MEMBERS_AND_DATE_RANGE = 13 + INVALID_TRIAL_ARM_TRAFFIC_SPLIT = 14 + TRAFFIC_SPLIT_OVERLAPPING = 15 + SUM_TRIAL_ARM_TRAFFIC_UNEQUALS_TO_TRIAL_TRAFFIC_SPLIT_DENOMINATOR = 16 + CANNOT_MODIFY_TRAFFIC_SPLIT_AFTER_START = 17 + EXPERIMENT_NOT_FOUND = 18 + EXPERIMENT_NOT_YET_STARTED = 19 + CANNOT_HAVE_MULTIPLE_CONTROL_ARMS = 20 + IN_DESIGN_CAMPAIGNS_NOT_SET = 21 + CANNOT_SET_STATUS_TO_GRADUATED = 22 + CANNOT_CREATE_EXPERIMENT_CAMPAIGN_WITH_SHARED_BUDGET = 23 + CANNOT_CREATE_EXPERIMENT_CAMPAIGN_WITH_CUSTOM_BUDGET = 24 + STATUS_TRANSITION_INVALID = 25 + DUPLICATE_EXPERIMENT_CAMPAIGN_NAME = 26 + CANNOT_REMOVE_IN_CREATION_EXPERIMENT = 27 + CANNOT_ADD_CAMPAIGN_WITH_DEPRECATED_AD_TYPES = 28 + CANNOT_ENABLE_SYNC_FOR_UNSUPPORTED_EXPERIMENT_TYPE = 29 + INVALID_DURATION_FOR_AN_EXPERIMENT = 30 + MISSING_EU_POLITICAL_ADVERTISING_SELF_DECLARATION = 31 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/extension_feed_item_error.py b/google/ads/googleads/v24/errors/types/extension_feed_item_error.py new file mode 100644 index 000000000..6666ecc35 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/extension_feed_item_error.py @@ -0,0 +1,223 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ExtensionFeedItemErrorEnum", + }, +) + + +class ExtensionFeedItemErrorEnum(proto.Message): + r"""Container for enum describing possible extension feed item + error. + + """ + + class ExtensionFeedItemError(proto.Enum): + r"""Enum describing possible extension feed item errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + VALUE_OUT_OF_RANGE (2): + Value is not within the accepted range. + URL_LIST_TOO_LONG (3): + Url list is too long. + CANNOT_HAVE_RESTRICTION_ON_EMPTY_GEO_TARGETING (4): + Cannot have a geo targeting restriction + without having geo targeting. + CANNOT_SET_WITH_FINAL_URLS (5): + Cannot simultaneously set sitelink field with + final urls. + CANNOT_SET_WITHOUT_FINAL_URLS (6): + Must set field with final urls. + INVALID_PHONE_NUMBER (7): + Phone number for a call extension is invalid. + PHONE_NUMBER_NOT_SUPPORTED_FOR_COUNTRY (8): + Phone number for a call extension is not + supported for the given country code. + CARRIER_SPECIFIC_SHORT_NUMBER_NOT_ALLOWED (9): + A carrier specific number in short format is + not allowed for call extensions. + PREMIUM_RATE_NUMBER_NOT_ALLOWED (10): + Premium rate numbers are not allowed for call + extensions. + DISALLOWED_NUMBER_TYPE (11): + Phone number type for a call extension is not + allowed. For example, personal number is not + allowed for a call extension in most regions. + INVALID_DOMESTIC_PHONE_NUMBER_FORMAT (12): + Phone number for a call extension does not + meet domestic format requirements. + VANITY_PHONE_NUMBER_NOT_ALLOWED (13): + Vanity phone numbers (for example, those + including letters) are not allowed for call + extensions. + INVALID_CALL_CONVERSION_ACTION (14): + Call conversion action provided for a call + extension is invalid. + CUSTOMER_NOT_ON_ALLOWLIST_FOR_CALLTRACKING (47): + For a call extension, the customer is not on + the allow-list for call tracking. + CALLTRACKING_NOT_SUPPORTED_FOR_COUNTRY (16): + Call tracking is not supported for the given + country for a call extension. + CUSTOMER_CONSENT_FOR_CALL_RECORDING_REQUIRED (17): + Customer hasn't consented for call recording, + which is required for creating/updating call + feed items. See + https://support.google.com/google-ads/answer/7412639. + INVALID_APP_ID (18): + App id provided for an app extension is + invalid. + QUOTES_IN_REVIEW_EXTENSION_SNIPPET (19): + Quotation marks present in the review text + for a review extension. + HYPHENS_IN_REVIEW_EXTENSION_SNIPPET (20): + Hyphen character present in the review text + for a review extension. + REVIEW_EXTENSION_SOURCE_INELIGIBLE (21): + A denylisted review source name or url was + provided for a review extension. + SOURCE_NAME_IN_REVIEW_EXTENSION_TEXT (22): + Review source name should not be found in the + review text. + INCONSISTENT_CURRENCY_CODES (23): + Inconsistent currency codes. + PRICE_EXTENSION_HAS_DUPLICATED_HEADERS (24): + Price extension cannot have duplicated + headers. + PRICE_ITEM_HAS_DUPLICATED_HEADER_AND_DESCRIPTION (25): + Price item cannot have duplicated header and + description. + PRICE_EXTENSION_HAS_TOO_FEW_ITEMS (26): + Price extension has too few items. + PRICE_EXTENSION_HAS_TOO_MANY_ITEMS (27): + Price extension has too many items. + UNSUPPORTED_VALUE (28): + The input value is not currently supported. + UNSUPPORTED_VALUE_IN_SELECTED_LANGUAGE (29): + The input value is not currently supported in + the selected language of an extension. + INVALID_DEVICE_PREFERENCE (30): + Unknown or unsupported device preference. + INVALID_SCHEDULE_END (31): + Invalid feed item schedule end time (for + example, endHour = 24 and endMinute != 0). + DATE_TIME_MUST_BE_IN_ACCOUNT_TIME_ZONE (32): + Date time zone does not match the account's + time zone. + INVALID_SNIPPETS_HEADER (33): + Invalid structured snippet header. + CANNOT_OPERATE_ON_REMOVED_FEED_ITEM (34): + Cannot operate on removed feed item. + PHONE_NUMBER_NOT_SUPPORTED_WITH_CALLTRACKING_FOR_COUNTRY (35): + Phone number not supported when call tracking + enabled for country. + CONFLICTING_CALL_CONVERSION_SETTINGS (36): + Cannot set call_conversion_action while + call_conversion_tracking_enabled is set to true. + EXTENSION_TYPE_MISMATCH (37): + The type of the input extension feed item + doesn't match the existing extension feed item. + EXTENSION_SUBTYPE_REQUIRED (38): + The oneof field extension for example, + subtype of extension feed item is required. + EXTENSION_TYPE_UNSUPPORTED (39): + The referenced feed item is not mapped to a + supported extension type. + CANNOT_OPERATE_ON_FEED_WITH_MULTIPLE_MAPPINGS (40): + Cannot operate on a Feed with more than one + active FeedMapping. + CANNOT_OPERATE_ON_FEED_WITH_KEY_ATTRIBUTES (41): + Cannot operate on a Feed that has key + attributes. + INVALID_PRICE_FORMAT (42): + Input price is not in a valid format. + PROMOTION_INVALID_TIME (43): + The promotion time is invalid. + TOO_MANY_DECIMAL_PLACES_SPECIFIED (44): + This field has too many decimal places + specified. + CONCRETE_EXTENSION_TYPE_REQUIRED (45): + Concrete sub type of ExtensionFeedItem is + required for this operation. + SCHEDULE_END_NOT_AFTER_START (46): + Feed item schedule end time must be after + start time. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + VALUE_OUT_OF_RANGE = 2 + URL_LIST_TOO_LONG = 3 + CANNOT_HAVE_RESTRICTION_ON_EMPTY_GEO_TARGETING = 4 + CANNOT_SET_WITH_FINAL_URLS = 5 + CANNOT_SET_WITHOUT_FINAL_URLS = 6 + INVALID_PHONE_NUMBER = 7 + PHONE_NUMBER_NOT_SUPPORTED_FOR_COUNTRY = 8 + CARRIER_SPECIFIC_SHORT_NUMBER_NOT_ALLOWED = 9 + PREMIUM_RATE_NUMBER_NOT_ALLOWED = 10 + DISALLOWED_NUMBER_TYPE = 11 + INVALID_DOMESTIC_PHONE_NUMBER_FORMAT = 12 + VANITY_PHONE_NUMBER_NOT_ALLOWED = 13 + INVALID_CALL_CONVERSION_ACTION = 14 + CUSTOMER_NOT_ON_ALLOWLIST_FOR_CALLTRACKING = 47 + CALLTRACKING_NOT_SUPPORTED_FOR_COUNTRY = 16 + CUSTOMER_CONSENT_FOR_CALL_RECORDING_REQUIRED = 17 + INVALID_APP_ID = 18 + QUOTES_IN_REVIEW_EXTENSION_SNIPPET = 19 + HYPHENS_IN_REVIEW_EXTENSION_SNIPPET = 20 + REVIEW_EXTENSION_SOURCE_INELIGIBLE = 21 + SOURCE_NAME_IN_REVIEW_EXTENSION_TEXT = 22 + INCONSISTENT_CURRENCY_CODES = 23 + PRICE_EXTENSION_HAS_DUPLICATED_HEADERS = 24 + PRICE_ITEM_HAS_DUPLICATED_HEADER_AND_DESCRIPTION = 25 + PRICE_EXTENSION_HAS_TOO_FEW_ITEMS = 26 + PRICE_EXTENSION_HAS_TOO_MANY_ITEMS = 27 + UNSUPPORTED_VALUE = 28 + UNSUPPORTED_VALUE_IN_SELECTED_LANGUAGE = 29 + INVALID_DEVICE_PREFERENCE = 30 + INVALID_SCHEDULE_END = 31 + DATE_TIME_MUST_BE_IN_ACCOUNT_TIME_ZONE = 32 + INVALID_SNIPPETS_HEADER = 33 + CANNOT_OPERATE_ON_REMOVED_FEED_ITEM = 34 + PHONE_NUMBER_NOT_SUPPORTED_WITH_CALLTRACKING_FOR_COUNTRY = 35 + CONFLICTING_CALL_CONVERSION_SETTINGS = 36 + EXTENSION_TYPE_MISMATCH = 37 + EXTENSION_SUBTYPE_REQUIRED = 38 + EXTENSION_TYPE_UNSUPPORTED = 39 + CANNOT_OPERATE_ON_FEED_WITH_MULTIPLE_MAPPINGS = 40 + CANNOT_OPERATE_ON_FEED_WITH_KEY_ATTRIBUTES = 41 + INVALID_PRICE_FORMAT = 42 + PROMOTION_INVALID_TIME = 43 + TOO_MANY_DECIMAL_PLACES_SPECIFIED = 44 + CONCRETE_EXTENSION_TYPE_REQUIRED = 45 + SCHEDULE_END_NOT_AFTER_START = 46 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/extension_setting_error.py b/google/ads/googleads/v24/errors/types/extension_setting_error.py new file mode 100644 index 000000000..3c63faec1 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/extension_setting_error.py @@ -0,0 +1,307 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ExtensionSettingErrorEnum", + }, +) + + +class ExtensionSettingErrorEnum(proto.Message): + r"""Container for enum describing validation errors of extension + settings. + + """ + + class ExtensionSettingError(proto.Enum): + r"""Enum describing possible extension setting errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + EXTENSIONS_REQUIRED (2): + A platform restriction was provided without + input extensions or existing extensions. + FEED_TYPE_EXTENSION_TYPE_MISMATCH (3): + The provided feed type does not correspond to + the provided extensions. + INVALID_FEED_TYPE (4): + The provided feed type cannot be used. + INVALID_FEED_TYPE_FOR_CUSTOMER_EXTENSION_SETTING (5): + The provided feed type cannot be used at the + customer level. + CANNOT_CHANGE_FEED_ITEM_ON_CREATE (6): + Cannot change a feed item field on a CREATE + operation. + CANNOT_UPDATE_NEWLY_CREATED_EXTENSION (7): + Cannot update an extension that is not + already in this setting. + NO_EXISTING_AD_GROUP_EXTENSION_SETTING_FOR_TYPE (8): + There is no existing AdGroupExtensionSetting + for this type. + NO_EXISTING_CAMPAIGN_EXTENSION_SETTING_FOR_TYPE (9): + There is no existing CampaignExtensionSetting + for this type. + NO_EXISTING_CUSTOMER_EXTENSION_SETTING_FOR_TYPE (10): + There is no existing CustomerExtensionSetting + for this type. + AD_GROUP_EXTENSION_SETTING_ALREADY_EXISTS (11): + The AdGroupExtensionSetting already exists. + UPDATE should be used to modify the existing + AdGroupExtensionSetting. + CAMPAIGN_EXTENSION_SETTING_ALREADY_EXISTS (12): + The CampaignExtensionSetting already exists. + UPDATE should be used to modify the existing + CampaignExtensionSetting. + CUSTOMER_EXTENSION_SETTING_ALREADY_EXISTS (13): + The CustomerExtensionSetting already exists. + UPDATE should be used to modify the existing + CustomerExtensionSetting. + AD_GROUP_FEED_ALREADY_EXISTS_FOR_PLACEHOLDER_TYPE (14): + An active ad group feed already exists for + this place holder type. + CAMPAIGN_FEED_ALREADY_EXISTS_FOR_PLACEHOLDER_TYPE (15): + An active campaign feed already exists for + this place holder type. + CUSTOMER_FEED_ALREADY_EXISTS_FOR_PLACEHOLDER_TYPE (16): + An active customer feed already exists for + this place holder type. + VALUE_OUT_OF_RANGE (17): + Value is not within the accepted range. + CANNOT_SET_FIELD_WITH_FINAL_URLS (18): + Cannot simultaneously set specified field + with final urls. + FINAL_URLS_NOT_SET (19): + Must set field with final urls. + INVALID_PHONE_NUMBER (20): + Phone number for a call extension is invalid. + PHONE_NUMBER_NOT_SUPPORTED_FOR_COUNTRY (21): + Phone number for a call extension is not + supported for the given country code. + CARRIER_SPECIFIC_SHORT_NUMBER_NOT_ALLOWED (22): + A carrier specific number in short format is + not allowed for call extensions. + PREMIUM_RATE_NUMBER_NOT_ALLOWED (23): + Premium rate numbers are not allowed for call + extensions. + DISALLOWED_NUMBER_TYPE (24): + Phone number type for a call extension is not + allowed. + INVALID_DOMESTIC_PHONE_NUMBER_FORMAT (25): + Phone number for a call extension does not + meet domestic format requirements. + VANITY_PHONE_NUMBER_NOT_ALLOWED (26): + Vanity phone numbers (for example, those + including letters) are not allowed for call + extensions. + INVALID_COUNTRY_CODE (27): + Country code provided for a call extension is + invalid. + INVALID_CALL_CONVERSION_TYPE_ID (28): + Call conversion type id provided for a call + extension is invalid. + CUSTOMER_NOT_IN_ALLOWLIST_FOR_CALLTRACKING (69): + For a call extension, the customer is not on + the allow-list for call tracking. + CALLTRACKING_NOT_SUPPORTED_FOR_COUNTRY (30): + Call tracking is not supported for the given + country for a call extension. + INVALID_APP_ID (31): + App id provided for an app extension is + invalid. + QUOTES_IN_REVIEW_EXTENSION_SNIPPET (32): + Quotation marks present in the review text + for a review extension. + HYPHENS_IN_REVIEW_EXTENSION_SNIPPET (33): + Hyphen character present in the review text + for a review extension. + REVIEW_EXTENSION_SOURCE_NOT_ELIGIBLE (34): + A blocked review source name or url was + provided for a review extension. + SOURCE_NAME_IN_REVIEW_EXTENSION_TEXT (35): + Review source name should not be found in the + review text. + MISSING_FIELD (36): + Field must be set. + INCONSISTENT_CURRENCY_CODES (37): + Inconsistent currency codes. + PRICE_EXTENSION_HAS_DUPLICATED_HEADERS (38): + Price extension cannot have duplicated + headers. + PRICE_ITEM_HAS_DUPLICATED_HEADER_AND_DESCRIPTION (39): + Price item cannot have duplicated header and + description. + PRICE_EXTENSION_HAS_TOO_FEW_ITEMS (40): + Price extension has too few items + PRICE_EXTENSION_HAS_TOO_MANY_ITEMS (41): + Price extension has too many items + UNSUPPORTED_VALUE (42): + The input value is not currently supported. + INVALID_DEVICE_PREFERENCE (43): + Unknown or unsupported device preference. + INVALID_SCHEDULE_END (45): + Invalid feed item schedule end time (for + example, endHour = 24 and endMinute != 0). + DATE_TIME_MUST_BE_IN_ACCOUNT_TIME_ZONE (47): + Date time zone does not match the account's + time zone. + OVERLAPPING_SCHEDULES_NOT_ALLOWED (48): + Overlapping feed item schedule times (for + example, 7-10AM and 8-11AM) are not allowed. + SCHEDULE_END_NOT_AFTER_START (49): + Feed item schedule end time must be after + start time. + TOO_MANY_SCHEDULES_PER_DAY (50): + There are too many feed item schedules per + day. + DUPLICATE_EXTENSION_FEED_ITEM_EDIT (51): + Cannot edit the same extension feed item more + than once in the same request. + INVALID_SNIPPETS_HEADER (52): + Invalid structured snippet header. + PHONE_NUMBER_NOT_SUPPORTED_WITH_CALLTRACKING_FOR_COUNTRY (53): + Phone number with call tracking enabled is + not supported for the specified country. + CAMPAIGN_TARGETING_MISMATCH (54): + The targeted adgroup must belong to the + targeted campaign. + CANNOT_OPERATE_ON_REMOVED_FEED (55): + The feed used by the ExtensionSetting is + removed and cannot be operated on. Remove the + ExtensionSetting to allow a new one to be + created using an active feed. + EXTENSION_TYPE_REQUIRED (56): + The ExtensionFeedItem type is required for + this operation. + INCOMPATIBLE_UNDERLYING_MATCHING_FUNCTION (57): + The matching function that links the + extension feed to the customer, campaign, or ad + group is not compatible with the + ExtensionSetting services. + START_DATE_AFTER_END_DATE (58): + Start date must be before end date. + INVALID_PRICE_FORMAT (59): + Input price is not in a valid format. + PROMOTION_INVALID_TIME (60): + The promotion time is invalid. + PROMOTION_CANNOT_SET_PERCENT_DISCOUNT_AND_MONEY_DISCOUNT (61): + Cannot set both percent discount and money + discount fields. + PROMOTION_CANNOT_SET_PROMOTION_CODE_AND_ORDERS_OVER_AMOUNT (62): + Cannot set both promotion code and orders + over amount fields. + TOO_MANY_DECIMAL_PLACES_SPECIFIED (63): + This field has too many decimal places + specified. + INVALID_LANGUAGE_CODE (64): + The language code is not valid. + UNSUPPORTED_LANGUAGE (65): + The language is not supported. + CUSTOMER_CONSENT_FOR_CALL_RECORDING_REQUIRED (66): + Customer hasn't consented for call recording, + which is required for adding/updating call + extensions. See + https://support.google.com/google-ads/answer/7412639. + EXTENSION_SETTING_UPDATE_IS_A_NOOP (67): + The UPDATE operation does not specify any + fields other than the resource name in the + update mask. + DISALLOWED_TEXT (68): + The extension contains text which has been + prohibited on policy grounds. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EXTENSIONS_REQUIRED = 2 + FEED_TYPE_EXTENSION_TYPE_MISMATCH = 3 + INVALID_FEED_TYPE = 4 + INVALID_FEED_TYPE_FOR_CUSTOMER_EXTENSION_SETTING = 5 + CANNOT_CHANGE_FEED_ITEM_ON_CREATE = 6 + CANNOT_UPDATE_NEWLY_CREATED_EXTENSION = 7 + NO_EXISTING_AD_GROUP_EXTENSION_SETTING_FOR_TYPE = 8 + NO_EXISTING_CAMPAIGN_EXTENSION_SETTING_FOR_TYPE = 9 + NO_EXISTING_CUSTOMER_EXTENSION_SETTING_FOR_TYPE = 10 + AD_GROUP_EXTENSION_SETTING_ALREADY_EXISTS = 11 + CAMPAIGN_EXTENSION_SETTING_ALREADY_EXISTS = 12 + CUSTOMER_EXTENSION_SETTING_ALREADY_EXISTS = 13 + AD_GROUP_FEED_ALREADY_EXISTS_FOR_PLACEHOLDER_TYPE = 14 + CAMPAIGN_FEED_ALREADY_EXISTS_FOR_PLACEHOLDER_TYPE = 15 + CUSTOMER_FEED_ALREADY_EXISTS_FOR_PLACEHOLDER_TYPE = 16 + VALUE_OUT_OF_RANGE = 17 + CANNOT_SET_FIELD_WITH_FINAL_URLS = 18 + FINAL_URLS_NOT_SET = 19 + INVALID_PHONE_NUMBER = 20 + PHONE_NUMBER_NOT_SUPPORTED_FOR_COUNTRY = 21 + CARRIER_SPECIFIC_SHORT_NUMBER_NOT_ALLOWED = 22 + PREMIUM_RATE_NUMBER_NOT_ALLOWED = 23 + DISALLOWED_NUMBER_TYPE = 24 + INVALID_DOMESTIC_PHONE_NUMBER_FORMAT = 25 + VANITY_PHONE_NUMBER_NOT_ALLOWED = 26 + INVALID_COUNTRY_CODE = 27 + INVALID_CALL_CONVERSION_TYPE_ID = 28 + CUSTOMER_NOT_IN_ALLOWLIST_FOR_CALLTRACKING = 69 + CALLTRACKING_NOT_SUPPORTED_FOR_COUNTRY = 30 + INVALID_APP_ID = 31 + QUOTES_IN_REVIEW_EXTENSION_SNIPPET = 32 + HYPHENS_IN_REVIEW_EXTENSION_SNIPPET = 33 + REVIEW_EXTENSION_SOURCE_NOT_ELIGIBLE = 34 + SOURCE_NAME_IN_REVIEW_EXTENSION_TEXT = 35 + MISSING_FIELD = 36 + INCONSISTENT_CURRENCY_CODES = 37 + PRICE_EXTENSION_HAS_DUPLICATED_HEADERS = 38 + PRICE_ITEM_HAS_DUPLICATED_HEADER_AND_DESCRIPTION = 39 + PRICE_EXTENSION_HAS_TOO_FEW_ITEMS = 40 + PRICE_EXTENSION_HAS_TOO_MANY_ITEMS = 41 + UNSUPPORTED_VALUE = 42 + INVALID_DEVICE_PREFERENCE = 43 + INVALID_SCHEDULE_END = 45 + DATE_TIME_MUST_BE_IN_ACCOUNT_TIME_ZONE = 47 + OVERLAPPING_SCHEDULES_NOT_ALLOWED = 48 + SCHEDULE_END_NOT_AFTER_START = 49 + TOO_MANY_SCHEDULES_PER_DAY = 50 + DUPLICATE_EXTENSION_FEED_ITEM_EDIT = 51 + INVALID_SNIPPETS_HEADER = 52 + PHONE_NUMBER_NOT_SUPPORTED_WITH_CALLTRACKING_FOR_COUNTRY = 53 + CAMPAIGN_TARGETING_MISMATCH = 54 + CANNOT_OPERATE_ON_REMOVED_FEED = 55 + EXTENSION_TYPE_REQUIRED = 56 + INCOMPATIBLE_UNDERLYING_MATCHING_FUNCTION = 57 + START_DATE_AFTER_END_DATE = 58 + INVALID_PRICE_FORMAT = 59 + PROMOTION_INVALID_TIME = 60 + PROMOTION_CANNOT_SET_PERCENT_DISCOUNT_AND_MONEY_DISCOUNT = 61 + PROMOTION_CANNOT_SET_PROMOTION_CODE_AND_ORDERS_OVER_AMOUNT = 62 + TOO_MANY_DECIMAL_PLACES_SPECIFIED = 63 + INVALID_LANGUAGE_CODE = 64 + UNSUPPORTED_LANGUAGE = 65 + CUSTOMER_CONSENT_FOR_CALL_RECORDING_REQUIRED = 66 + EXTENSION_SETTING_UPDATE_IS_A_NOOP = 67 + DISALLOWED_TEXT = 68 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/feed_attribute_reference_error.py b/google/ads/googleads/v24/errors/types/feed_attribute_reference_error.py new file mode 100644 index 000000000..85ccbf79d --- /dev/null +++ b/google/ads/googleads/v24/errors/types/feed_attribute_reference_error.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "FeedAttributeReferenceErrorEnum", + }, +) + + +class FeedAttributeReferenceErrorEnum(proto.Message): + r"""Container for enum describing possible feed attribute + reference errors. + + """ + + class FeedAttributeReferenceError(proto.Enum): + r"""Enum describing possible feed attribute reference errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CANNOT_REFERENCE_REMOVED_FEED (2): + A feed referenced by ID has been removed. + INVALID_FEED_NAME (3): + There is no enabled feed with the given name. + INVALID_FEED_ATTRIBUTE_NAME (4): + There is no feed attribute in an enabled feed + with the given name. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CANNOT_REFERENCE_REMOVED_FEED = 2 + INVALID_FEED_NAME = 3 + INVALID_FEED_ATTRIBUTE_NAME = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/feed_error.py b/google/ads/googleads/v24/errors/types/feed_error.py new file mode 100644 index 000000000..d06336054 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/feed_error.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "FeedErrorEnum", + }, +) + + +class FeedErrorEnum(proto.Message): + r"""Container for enum describing possible feed errors.""" + + class FeedError(proto.Enum): + r"""Enum describing possible feed errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + ATTRIBUTE_NAMES_NOT_UNIQUE (2): + The names of the FeedAttributes must be + unique. + ATTRIBUTES_DO_NOT_MATCH_EXISTING_ATTRIBUTES (3): + The attribute list must be an exact copy of + the existing list if the attribute ID's are + present. + CANNOT_SPECIFY_USER_ORIGIN_FOR_SYSTEM_FEED (4): + Cannot specify USER origin for a system + generated feed. + CANNOT_SPECIFY_GOOGLE_ORIGIN_FOR_NON_SYSTEM_FEED (5): + Cannot specify GOOGLE origin for a non-system + generated feed. + CANNOT_SPECIFY_FEED_ATTRIBUTES_FOR_SYSTEM_FEED (6): + Cannot specify feed attributes for system + feed. + CANNOT_UPDATE_FEED_ATTRIBUTES_WITH_ORIGIN_GOOGLE (7): + Cannot update FeedAttributes on feed with + origin GOOGLE. + FEED_REMOVED (8): + The given ID refers to a removed Feed. + Removed Feeds are immutable. + INVALID_ORIGIN_VALUE (9): + The origin of the feed is not valid for the + client. + FEED_ORIGIN_IS_NOT_USER (10): + A user can only create and modify feeds with + USER origin. + INVALID_AUTH_TOKEN_FOR_EMAIL (11): + Invalid auth token for the given email. + INVALID_EMAIL (12): + Invalid email specified. + DUPLICATE_FEED_NAME (13): + Feed name matches that of another active + Feed. + INVALID_FEED_NAME (14): + Name of feed is not allowed. + MISSING_OAUTH_INFO (15): + Missing OAuthInfo. + NEW_ATTRIBUTE_CANNOT_BE_PART_OF_UNIQUE_KEY (16): + New FeedAttributes must not affect the unique + key. + TOO_MANY_ATTRIBUTES (17): + Too many FeedAttributes for a Feed. + INVALID_BUSINESS_ACCOUNT (18): + The business account is not valid. + BUSINESS_ACCOUNT_CANNOT_ACCESS_LOCATION_ACCOUNT (19): + Business account cannot access Business + Profile. + INVALID_AFFILIATE_CHAIN_ID (20): + Invalid chain ID provided for affiliate + location feed. + DUPLICATE_SYSTEM_FEED (21): + There is already a feed with the given system + feed generation data. + GMB_ACCESS_ERROR (22): + An error occurred accessing Business Profile. + CANNOT_HAVE_LOCATION_AND_AFFILIATE_LOCATION_FEEDS (23): + A customer cannot have both LOCATION and AFFILIATE_LOCATION + feeds. + LEGACY_EXTENSION_TYPE_READ_ONLY (24): + Feed-based extension is read-only for this + extension type. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ATTRIBUTE_NAMES_NOT_UNIQUE = 2 + ATTRIBUTES_DO_NOT_MATCH_EXISTING_ATTRIBUTES = 3 + CANNOT_SPECIFY_USER_ORIGIN_FOR_SYSTEM_FEED = 4 + CANNOT_SPECIFY_GOOGLE_ORIGIN_FOR_NON_SYSTEM_FEED = 5 + CANNOT_SPECIFY_FEED_ATTRIBUTES_FOR_SYSTEM_FEED = 6 + CANNOT_UPDATE_FEED_ATTRIBUTES_WITH_ORIGIN_GOOGLE = 7 + FEED_REMOVED = 8 + INVALID_ORIGIN_VALUE = 9 + FEED_ORIGIN_IS_NOT_USER = 10 + INVALID_AUTH_TOKEN_FOR_EMAIL = 11 + INVALID_EMAIL = 12 + DUPLICATE_FEED_NAME = 13 + INVALID_FEED_NAME = 14 + MISSING_OAUTH_INFO = 15 + NEW_ATTRIBUTE_CANNOT_BE_PART_OF_UNIQUE_KEY = 16 + TOO_MANY_ATTRIBUTES = 17 + INVALID_BUSINESS_ACCOUNT = 18 + BUSINESS_ACCOUNT_CANNOT_ACCESS_LOCATION_ACCOUNT = 19 + INVALID_AFFILIATE_CHAIN_ID = 20 + DUPLICATE_SYSTEM_FEED = 21 + GMB_ACCESS_ERROR = 22 + CANNOT_HAVE_LOCATION_AND_AFFILIATE_LOCATION_FEEDS = 23 + LEGACY_EXTENSION_TYPE_READ_ONLY = 24 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/feed_item_error.py b/google/ads/googleads/v24/errors/types/feed_item_error.py new file mode 100644 index 000000000..a83cf2c5a --- /dev/null +++ b/google/ads/googleads/v24/errors/types/feed_item_error.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "FeedItemErrorEnum", + }, +) + + +class FeedItemErrorEnum(proto.Message): + r"""Container for enum describing possible feed item errors.""" + + class FeedItemError(proto.Enum): + r"""Enum describing possible feed item errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CANNOT_CONVERT_ATTRIBUTE_VALUE_FROM_STRING (2): + Cannot convert the feed attribute value from + string to its real type. + CANNOT_OPERATE_ON_REMOVED_FEED_ITEM (3): + Cannot operate on removed feed item. + DATE_TIME_MUST_BE_IN_ACCOUNT_TIME_ZONE (4): + Date time zone does not match the account's + time zone. + KEY_ATTRIBUTES_NOT_FOUND (5): + Feed item with the key attributes could not + be found. + INVALID_URL (6): + Url feed attribute value is not valid. + MISSING_KEY_ATTRIBUTES (7): + Some key attributes are missing. + KEY_ATTRIBUTES_NOT_UNIQUE (8): + Feed item has same key attributes as another + feed item. + CANNOT_MODIFY_KEY_ATTRIBUTE_VALUE (9): + Cannot modify key attributes on an existing + feed item. + SIZE_TOO_LARGE_FOR_MULTI_VALUE_ATTRIBUTE (10): + The feed attribute value is too large. + LEGACY_FEED_TYPE_READ_ONLY (11): + Feed is read only. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CANNOT_CONVERT_ATTRIBUTE_VALUE_FROM_STRING = 2 + CANNOT_OPERATE_ON_REMOVED_FEED_ITEM = 3 + DATE_TIME_MUST_BE_IN_ACCOUNT_TIME_ZONE = 4 + KEY_ATTRIBUTES_NOT_FOUND = 5 + INVALID_URL = 6 + MISSING_KEY_ATTRIBUTES = 7 + KEY_ATTRIBUTES_NOT_UNIQUE = 8 + CANNOT_MODIFY_KEY_ATTRIBUTE_VALUE = 9 + SIZE_TOO_LARGE_FOR_MULTI_VALUE_ATTRIBUTE = 10 + LEGACY_FEED_TYPE_READ_ONLY = 11 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/feed_item_set_error.py b/google/ads/googleads/v24/errors/types/feed_item_set_error.py new file mode 100644 index 000000000..ae3730c8b --- /dev/null +++ b/google/ads/googleads/v24/errors/types/feed_item_set_error.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "FeedItemSetErrorEnum", + }, +) + + +class FeedItemSetErrorEnum(proto.Message): + r"""Container for enum describing possible feed item set errors.""" + + class FeedItemSetError(proto.Enum): + r"""Enum describing possible feed item set errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + FEED_ITEM_SET_REMOVED (2): + The given ID refers to a removed FeedItemSet. + CANNOT_CLEAR_DYNAMIC_FILTER (3): + The dynamic filter of a feed item set cannot + be cleared on UPDATE if it exists. A set is + either static or dynamic once added, and that + cannot change. + CANNOT_CREATE_DYNAMIC_FILTER (4): + The dynamic filter of a feed item set cannot + be created on UPDATE if it does not exist. A set + is either static or dynamic once added, and that + cannot change. + INVALID_FEED_TYPE (5): + FeedItemSets can only be made for location or + affiliate location feeds. + DUPLICATE_NAME (6): + FeedItemSets duplicate name. Name should be + unique within an account. + WRONG_DYNAMIC_FILTER_FOR_FEED_TYPE (7): + The feed type of the parent Feed is not compatible with the + type of dynamic filter being set. For example, you can only + set dynamic_location_set_filter for LOCATION feed item sets. + DYNAMIC_FILTER_INVALID_CHAIN_IDS (8): + Chain ID specified for + AffiliateLocationFeedData is invalid. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + FEED_ITEM_SET_REMOVED = 2 + CANNOT_CLEAR_DYNAMIC_FILTER = 3 + CANNOT_CREATE_DYNAMIC_FILTER = 4 + INVALID_FEED_TYPE = 5 + DUPLICATE_NAME = 6 + WRONG_DYNAMIC_FILTER_FOR_FEED_TYPE = 7 + DYNAMIC_FILTER_INVALID_CHAIN_IDS = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/feed_item_set_link_error.py b/google/ads/googleads/v24/errors/types/feed_item_set_link_error.py new file mode 100644 index 000000000..6b2a18678 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/feed_item_set_link_error.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "FeedItemSetLinkErrorEnum", + }, +) + + +class FeedItemSetLinkErrorEnum(proto.Message): + r"""Container for enum describing possible feed item set link + errors. + + """ + + class FeedItemSetLinkError(proto.Enum): + r"""Enum describing possible feed item set link errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + FEED_ID_MISMATCH (2): + The feed IDs of the FeedItemSet and FeedItem + do not match. Only FeedItems in a given Feed can + be linked to a FeedItemSet in that Feed. + NO_MUTATE_ALLOWED_FOR_DYNAMIC_SET (3): + Cannot add or remove links to a dynamic set. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + FEED_ID_MISMATCH = 2 + NO_MUTATE_ALLOWED_FOR_DYNAMIC_SET = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/feed_item_target_error.py b/google/ads/googleads/v24/errors/types/feed_item_target_error.py new file mode 100644 index 000000000..049ed5094 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/feed_item_target_error.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "FeedItemTargetErrorEnum", + }, +) + + +class FeedItemTargetErrorEnum(proto.Message): + r"""Container for enum describing possible feed item target + errors. + + """ + + class FeedItemTargetError(proto.Enum): + r"""Enum describing possible feed item target errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + MUST_SET_TARGET_ONEOF_ON_CREATE (2): + On CREATE, the FeedItemTarget must have a + populated field in the oneof target. + FEED_ITEM_TARGET_ALREADY_EXISTS (3): + The specified feed item target already + exists, so it cannot be added. + FEED_ITEM_SCHEDULES_CANNOT_OVERLAP (4): + The schedules for a given feed item cannot + overlap. + TARGET_LIMIT_EXCEEDED_FOR_GIVEN_TYPE (5): + Too many targets of a given type were added + for a single feed item. + TOO_MANY_SCHEDULES_PER_DAY (6): + Too many AdSchedules are enabled for the feed + item for the given day. + CANNOT_HAVE_ENABLED_CAMPAIGN_AND_ENABLED_AD_GROUP_TARGETS (7): + A feed item may either have an enabled + campaign target or an enabled ad group target. + DUPLICATE_AD_SCHEDULE (8): + Duplicate ad schedules aren't allowed. + DUPLICATE_KEYWORD (9): + Duplicate keywords aren't allowed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MUST_SET_TARGET_ONEOF_ON_CREATE = 2 + FEED_ITEM_TARGET_ALREADY_EXISTS = 3 + FEED_ITEM_SCHEDULES_CANNOT_OVERLAP = 4 + TARGET_LIMIT_EXCEEDED_FOR_GIVEN_TYPE = 5 + TOO_MANY_SCHEDULES_PER_DAY = 6 + CANNOT_HAVE_ENABLED_CAMPAIGN_AND_ENABLED_AD_GROUP_TARGETS = 7 + DUPLICATE_AD_SCHEDULE = 8 + DUPLICATE_KEYWORD = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/feed_item_validation_error.py b/google/ads/googleads/v24/errors/types/feed_item_validation_error.py new file mode 100644 index 000000000..ca935c6d9 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/feed_item_validation_error.py @@ -0,0 +1,420 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "FeedItemValidationErrorEnum", + }, +) + + +class FeedItemValidationErrorEnum(proto.Message): + r"""Container for enum describing possible validation errors of a + feed item. + + """ + + class FeedItemValidationError(proto.Enum): + r"""The possible validation errors of a feed item. + + Values: + UNSPECIFIED (0): + No value has been specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + STRING_TOO_SHORT (2): + String is too short. + STRING_TOO_LONG (3): + String is too long. + VALUE_NOT_SPECIFIED (4): + Value is not provided. + INVALID_DOMESTIC_PHONE_NUMBER_FORMAT (5): + Phone number format is invalid for region. + INVALID_PHONE_NUMBER (6): + String does not represent a phone number. + PHONE_NUMBER_NOT_SUPPORTED_FOR_COUNTRY (7): + Phone number format is not compatible with + country code. + PREMIUM_RATE_NUMBER_NOT_ALLOWED (8): + Premium rate number is not allowed. + DISALLOWED_NUMBER_TYPE (9): + Phone number type is not allowed. + VALUE_OUT_OF_RANGE (10): + Specified value is outside of the valid + range. + CALLTRACKING_NOT_SUPPORTED_FOR_COUNTRY (11): + Call tracking is not supported in the + selected country. + CUSTOMER_NOT_IN_ALLOWLIST_FOR_CALLTRACKING (99): + Customer is not on the allow-list for call + tracking. + INVALID_COUNTRY_CODE (13): + Country code is invalid. + INVALID_APP_ID (14): + The specified mobile app id is invalid. + MISSING_ATTRIBUTES_FOR_FIELDS (15): + Some required field attributes are missing. + INVALID_TYPE_ID (16): + Invalid email button type for email + extension. + INVALID_EMAIL_ADDRESS (17): + Email address is invalid. + INVALID_HTTPS_URL (18): + The HTTPS URL in email extension is invalid. + MISSING_DELIVERY_ADDRESS (19): + Delivery address is missing from email + extension. + START_DATE_AFTER_END_DATE (20): + FeedItem scheduling start date comes after + end date. + MISSING_FEED_ITEM_START_TIME (21): + FeedItem scheduling start time is missing. + MISSING_FEED_ITEM_END_TIME (22): + FeedItem scheduling end time is missing. + MISSING_FEED_ITEM_ID (23): + Cannot compute system attributes on a + FeedItem that has no FeedItemId. + VANITY_PHONE_NUMBER_NOT_ALLOWED (24): + Call extension vanity phone numbers are not + supported. + INVALID_REVIEW_EXTENSION_SNIPPET (25): + Invalid review text. + INVALID_NUMBER_FORMAT (26): + Invalid format for numeric value in ad + parameter. + INVALID_DATE_FORMAT (27): + Invalid format for date value in ad + parameter. + INVALID_PRICE_FORMAT (28): + Invalid format for price value in ad + parameter. + UNKNOWN_PLACEHOLDER_FIELD (29): + Unrecognized type given for value in ad + parameter. + MISSING_ENHANCED_SITELINK_DESCRIPTION_LINE (30): + Enhanced sitelinks must have both description + lines specified. + REVIEW_EXTENSION_SOURCE_INELIGIBLE (31): + Review source is ineligible. + HYPHENS_IN_REVIEW_EXTENSION_SNIPPET (32): + Review text cannot contain hyphens or dashes. + DOUBLE_QUOTES_IN_REVIEW_EXTENSION_SNIPPET (33): + Review text cannot contain double quote + characters. + QUOTES_IN_REVIEW_EXTENSION_SNIPPET (34): + Review text cannot contain quote characters. + INVALID_FORM_ENCODED_PARAMS (35): + Parameters are encoded in the wrong format. + INVALID_URL_PARAMETER_NAME (36): + URL parameter name must contain only letters, + numbers, underscores, and dashes. + NO_GEOCODING_RESULT (37): + Cannot find address location. + SOURCE_NAME_IN_REVIEW_EXTENSION_TEXT (38): + Review extension text has source name. + CARRIER_SPECIFIC_SHORT_NUMBER_NOT_ALLOWED (39): + Some phone numbers can be shorter than usual. + Some of these short numbers are + carrier-specific, and we disallow those in ad + extensions because they will not be available to + all users. + INVALID_PLACEHOLDER_FIELD_ID (40): + Triggered when a request references a + placeholder field id that does not exist. + INVALID_URL_TAG (41): + URL contains invalid ValueTrack tags or + format. + LIST_TOO_LONG (42): + Provided list exceeds acceptable size. + INVALID_ATTRIBUTES_COMBINATION (43): + Certain combinations of attributes aren't + allowed to be specified in the same feed item. + DUPLICATE_VALUES (44): + An attribute has the same value repeatedly. + INVALID_CALL_CONVERSION_ACTION_ID (45): + Advertisers can link a conversion action with + a phone number to indicate that sufficiently + long calls forwarded to that phone number should + be counted as conversions of the specified type. + This is an error message indicating that the + conversion action specified is invalid (for + example, the conversion action does not exist + within the appropriate Google Ads account, or it + is a type of conversion not appropriate to phone + call conversions). + CANNOT_SET_WITHOUT_FINAL_URLS (46): + Tracking template requires final url to be + set. + APP_ID_DOESNT_EXIST_IN_APP_STORE (47): + An app id was provided that doesn't exist in + the given app store. + INVALID_FINAL_URL (48): + Invalid U2 final url. + INVALID_TRACKING_URL (49): + Invalid U2 tracking url. + INVALID_FINAL_URL_FOR_APP_DOWNLOAD_URL (50): + Final URL should start from App download URL. + LIST_TOO_SHORT (51): + List provided is too short. + INVALID_USER_ACTION (52): + User Action field has invalid value. + INVALID_TYPE_NAME (53): + Type field has invalid value. + INVALID_EVENT_CHANGE_STATUS (54): + Change status for event is invalid. + INVALID_SNIPPETS_HEADER (55): + The header of a structured snippets extension + is not one of the valid headers. + INVALID_ANDROID_APP_LINK (56): + Android app link is not formatted correctly + NUMBER_TYPE_WITH_CALLTRACKING_NOT_SUPPORTED_FOR_COUNTRY (57): + Phone number incompatible with call tracking + for country. + RESERVED_KEYWORD_OTHER (58): + The input is identical to a reserved keyword + DUPLICATE_OPTION_LABELS (59): + Each option label in the message extension + must be unique. + DUPLICATE_OPTION_PREFILLS (60): + Each option prefill in the message extension + must be unique. + UNEQUAL_LIST_LENGTHS (61): + In message extensions, the number of optional + labels and optional prefills must be the same. + INCONSISTENT_CURRENCY_CODES (62): + All currency codes in an ad extension must be + the same. + PRICE_EXTENSION_HAS_DUPLICATED_HEADERS (63): + Headers in price extension are not unique. + ITEM_HAS_DUPLICATED_HEADER_AND_DESCRIPTION (64): + Header and description in an item are the + same. + PRICE_EXTENSION_HAS_TOO_FEW_ITEMS (65): + Price extension has too few items. + UNSUPPORTED_VALUE (66): + The given value is not supported. + INVALID_FINAL_MOBILE_URL (67): + Invalid final mobile url. + INVALID_KEYWORDLESS_AD_RULE_LABEL (68): + The given string value of Label contains + invalid characters + VALUE_TRACK_PARAMETER_NOT_SUPPORTED (69): + The given URL contains value track + parameters. + UNSUPPORTED_VALUE_IN_SELECTED_LANGUAGE (70): + The given value is not supported in the + selected language of an extension. + INVALID_IOS_APP_LINK (71): + The iOS app link is not formatted correctly. + MISSING_IOS_APP_LINK_OR_IOS_APP_STORE_ID (72): + iOS app link or iOS app store id is missing. + PROMOTION_INVALID_TIME (73): + Promotion time is invalid. + PROMOTION_CANNOT_SET_PERCENT_OFF_AND_MONEY_AMOUNT_OFF (74): + Both the percent off and money amount off + fields are set. + PROMOTION_CANNOT_SET_PROMOTION_CODE_AND_ORDERS_OVER_AMOUNT (75): + Both the promotion code and orders over + amount fields are set. + TOO_MANY_DECIMAL_PLACES_SPECIFIED (76): + Too many decimal places are specified. + AD_CUSTOMIZERS_NOT_ALLOWED (77): + Ad Customizers are present and not allowed. + INVALID_LANGUAGE_CODE (78): + Language code is not valid. + UNSUPPORTED_LANGUAGE (79): + Language is not supported. + IF_FUNCTION_NOT_ALLOWED (80): + IF Function is present and not allowed. + INVALID_FINAL_URL_SUFFIX (81): + Final url suffix is not valid. + INVALID_TAG_IN_FINAL_URL_SUFFIX (82): + Final url suffix contains an invalid tag. + INVALID_FINAL_URL_SUFFIX_FORMAT (83): + Final url suffix is formatted incorrectly. + CUSTOMER_CONSENT_FOR_CALL_RECORDING_REQUIRED (84): + Consent for call recording, which is required + for the use of call extensions, was not provided + by the advertiser. See + https://support.google.com/google-ads/answer/7412639. + ONLY_ONE_DELIVERY_OPTION_IS_ALLOWED (85): + Multiple message delivery options are set. + NO_DELIVERY_OPTION_IS_SET (86): + No message delivery option is set. + INVALID_CONVERSION_REPORTING_STATE (87): + String value of conversion reporting state + field is not valid. + IMAGE_SIZE_WRONG (88): + Image size is not right. + EMAIL_DELIVERY_NOT_AVAILABLE_IN_COUNTRY (89): + Email delivery is not supported in the + country specified in the country code field. + AUTO_REPLY_NOT_AVAILABLE_IN_COUNTRY (90): + Auto reply is not supported in the country + specified in the country code field. + INVALID_LATITUDE_VALUE (91): + Invalid value specified for latitude. + INVALID_LONGITUDE_VALUE (92): + Invalid value specified for longitude. + TOO_MANY_LABELS (93): + Too many label fields provided. + INVALID_IMAGE_URL (94): + Invalid image url. + MISSING_LATITUDE_VALUE (95): + Latitude value is missing. + MISSING_LONGITUDE_VALUE (96): + Longitude value is missing. + ADDRESS_NOT_FOUND (97): + Unable to find address. + ADDRESS_NOT_TARGETABLE (98): + Cannot target provided address. + INVALID_ASSET_ID (100): + The specified asset ID does not exist. + INCOMPATIBLE_ASSET_TYPE (101): + The asset type cannot be set for the field. + IMAGE_ERROR_UNEXPECTED_SIZE (102): + The image has unexpected size. + IMAGE_ERROR_ASPECT_RATIO_NOT_ALLOWED (103): + The image aspect ratio is not allowed. + IMAGE_ERROR_FILE_TOO_LARGE (104): + The image file is too large. + IMAGE_ERROR_FORMAT_NOT_ALLOWED (105): + The image format is unsupported. + IMAGE_ERROR_CONSTRAINTS_VIOLATED (106): + Image violates constraints without more + details. + IMAGE_ERROR_SERVER_ERROR (107): + An error occurred when validating image. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + STRING_TOO_SHORT = 2 + STRING_TOO_LONG = 3 + VALUE_NOT_SPECIFIED = 4 + INVALID_DOMESTIC_PHONE_NUMBER_FORMAT = 5 + INVALID_PHONE_NUMBER = 6 + PHONE_NUMBER_NOT_SUPPORTED_FOR_COUNTRY = 7 + PREMIUM_RATE_NUMBER_NOT_ALLOWED = 8 + DISALLOWED_NUMBER_TYPE = 9 + VALUE_OUT_OF_RANGE = 10 + CALLTRACKING_NOT_SUPPORTED_FOR_COUNTRY = 11 + CUSTOMER_NOT_IN_ALLOWLIST_FOR_CALLTRACKING = 99 + INVALID_COUNTRY_CODE = 13 + INVALID_APP_ID = 14 + MISSING_ATTRIBUTES_FOR_FIELDS = 15 + INVALID_TYPE_ID = 16 + INVALID_EMAIL_ADDRESS = 17 + INVALID_HTTPS_URL = 18 + MISSING_DELIVERY_ADDRESS = 19 + START_DATE_AFTER_END_DATE = 20 + MISSING_FEED_ITEM_START_TIME = 21 + MISSING_FEED_ITEM_END_TIME = 22 + MISSING_FEED_ITEM_ID = 23 + VANITY_PHONE_NUMBER_NOT_ALLOWED = 24 + INVALID_REVIEW_EXTENSION_SNIPPET = 25 + INVALID_NUMBER_FORMAT = 26 + INVALID_DATE_FORMAT = 27 + INVALID_PRICE_FORMAT = 28 + UNKNOWN_PLACEHOLDER_FIELD = 29 + MISSING_ENHANCED_SITELINK_DESCRIPTION_LINE = 30 + REVIEW_EXTENSION_SOURCE_INELIGIBLE = 31 + HYPHENS_IN_REVIEW_EXTENSION_SNIPPET = 32 + DOUBLE_QUOTES_IN_REVIEW_EXTENSION_SNIPPET = 33 + QUOTES_IN_REVIEW_EXTENSION_SNIPPET = 34 + INVALID_FORM_ENCODED_PARAMS = 35 + INVALID_URL_PARAMETER_NAME = 36 + NO_GEOCODING_RESULT = 37 + SOURCE_NAME_IN_REVIEW_EXTENSION_TEXT = 38 + CARRIER_SPECIFIC_SHORT_NUMBER_NOT_ALLOWED = 39 + INVALID_PLACEHOLDER_FIELD_ID = 40 + INVALID_URL_TAG = 41 + LIST_TOO_LONG = 42 + INVALID_ATTRIBUTES_COMBINATION = 43 + DUPLICATE_VALUES = 44 + INVALID_CALL_CONVERSION_ACTION_ID = 45 + CANNOT_SET_WITHOUT_FINAL_URLS = 46 + APP_ID_DOESNT_EXIST_IN_APP_STORE = 47 + INVALID_FINAL_URL = 48 + INVALID_TRACKING_URL = 49 + INVALID_FINAL_URL_FOR_APP_DOWNLOAD_URL = 50 + LIST_TOO_SHORT = 51 + INVALID_USER_ACTION = 52 + INVALID_TYPE_NAME = 53 + INVALID_EVENT_CHANGE_STATUS = 54 + INVALID_SNIPPETS_HEADER = 55 + INVALID_ANDROID_APP_LINK = 56 + NUMBER_TYPE_WITH_CALLTRACKING_NOT_SUPPORTED_FOR_COUNTRY = 57 + RESERVED_KEYWORD_OTHER = 58 + DUPLICATE_OPTION_LABELS = 59 + DUPLICATE_OPTION_PREFILLS = 60 + UNEQUAL_LIST_LENGTHS = 61 + INCONSISTENT_CURRENCY_CODES = 62 + PRICE_EXTENSION_HAS_DUPLICATED_HEADERS = 63 + ITEM_HAS_DUPLICATED_HEADER_AND_DESCRIPTION = 64 + PRICE_EXTENSION_HAS_TOO_FEW_ITEMS = 65 + UNSUPPORTED_VALUE = 66 + INVALID_FINAL_MOBILE_URL = 67 + INVALID_KEYWORDLESS_AD_RULE_LABEL = 68 + VALUE_TRACK_PARAMETER_NOT_SUPPORTED = 69 + UNSUPPORTED_VALUE_IN_SELECTED_LANGUAGE = 70 + INVALID_IOS_APP_LINK = 71 + MISSING_IOS_APP_LINK_OR_IOS_APP_STORE_ID = 72 + PROMOTION_INVALID_TIME = 73 + PROMOTION_CANNOT_SET_PERCENT_OFF_AND_MONEY_AMOUNT_OFF = 74 + PROMOTION_CANNOT_SET_PROMOTION_CODE_AND_ORDERS_OVER_AMOUNT = 75 + TOO_MANY_DECIMAL_PLACES_SPECIFIED = 76 + AD_CUSTOMIZERS_NOT_ALLOWED = 77 + INVALID_LANGUAGE_CODE = 78 + UNSUPPORTED_LANGUAGE = 79 + IF_FUNCTION_NOT_ALLOWED = 80 + INVALID_FINAL_URL_SUFFIX = 81 + INVALID_TAG_IN_FINAL_URL_SUFFIX = 82 + INVALID_FINAL_URL_SUFFIX_FORMAT = 83 + CUSTOMER_CONSENT_FOR_CALL_RECORDING_REQUIRED = 84 + ONLY_ONE_DELIVERY_OPTION_IS_ALLOWED = 85 + NO_DELIVERY_OPTION_IS_SET = 86 + INVALID_CONVERSION_REPORTING_STATE = 87 + IMAGE_SIZE_WRONG = 88 + EMAIL_DELIVERY_NOT_AVAILABLE_IN_COUNTRY = 89 + AUTO_REPLY_NOT_AVAILABLE_IN_COUNTRY = 90 + INVALID_LATITUDE_VALUE = 91 + INVALID_LONGITUDE_VALUE = 92 + TOO_MANY_LABELS = 93 + INVALID_IMAGE_URL = 94 + MISSING_LATITUDE_VALUE = 95 + MISSING_LONGITUDE_VALUE = 96 + ADDRESS_NOT_FOUND = 97 + ADDRESS_NOT_TARGETABLE = 98 + INVALID_ASSET_ID = 100 + INCOMPATIBLE_ASSET_TYPE = 101 + IMAGE_ERROR_UNEXPECTED_SIZE = 102 + IMAGE_ERROR_ASPECT_RATIO_NOT_ALLOWED = 103 + IMAGE_ERROR_FILE_TOO_LARGE = 104 + IMAGE_ERROR_FORMAT_NOT_ALLOWED = 105 + IMAGE_ERROR_CONSTRAINTS_VIOLATED = 106 + IMAGE_ERROR_SERVER_ERROR = 107 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/feed_mapping_error.py b/google/ads/googleads/v24/errors/types/feed_mapping_error.py new file mode 100644 index 000000000..9ceff63a3 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/feed_mapping_error.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "FeedMappingErrorEnum", + }, +) + + +class FeedMappingErrorEnum(proto.Message): + r"""Container for enum describing possible feed item errors.""" + + class FeedMappingError(proto.Enum): + r"""Enum describing possible feed item errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_PLACEHOLDER_FIELD (2): + The given placeholder field does not exist. + INVALID_CRITERION_FIELD (3): + The given criterion field does not exist. + INVALID_PLACEHOLDER_TYPE (4): + The given placeholder type does not exist. + INVALID_CRITERION_TYPE (5): + The given criterion type does not exist. + NO_ATTRIBUTE_FIELD_MAPPINGS (7): + A feed mapping must contain at least one + attribute field mapping. + FEED_ATTRIBUTE_TYPE_MISMATCH (8): + The type of the feed attribute referenced in + the attribute field mapping must match the type + of the placeholder field. + CANNOT_OPERATE_ON_MAPPINGS_FOR_SYSTEM_GENERATED_FEED (9): + A feed mapping for a system generated feed + cannot be operated on. + MULTIPLE_MAPPINGS_FOR_PLACEHOLDER_TYPE (10): + Only one feed mapping for a placeholder type + is allowed per feed or customer (depending on + the placeholder type). + MULTIPLE_MAPPINGS_FOR_CRITERION_TYPE (11): + Only one feed mapping for a criterion type is + allowed per customer. + MULTIPLE_MAPPINGS_FOR_PLACEHOLDER_FIELD (12): + Only one feed attribute mapping for a + placeholder field is allowed (depending on the + placeholder type). + MULTIPLE_MAPPINGS_FOR_CRITERION_FIELD (13): + Only one feed attribute mapping for a + criterion field is allowed (depending on the + criterion type). + UNEXPECTED_ATTRIBUTE_FIELD_MAPPINGS (14): + This feed mapping may not contain any + explicit attribute field mappings. + LOCATION_PLACEHOLDER_ONLY_FOR_PLACES_FEEDS (15): + Location placeholder feed mappings can only + be created for Places feeds. + CANNOT_MODIFY_MAPPINGS_FOR_TYPED_FEED (16): + Mappings for typed feeds cannot be modified. + INVALID_PLACEHOLDER_TYPE_FOR_NON_SYSTEM_GENERATED_FEED (17): + The given placeholder type can only be mapped + to system generated feeds. + INVALID_PLACEHOLDER_TYPE_FOR_SYSTEM_GENERATED_FEED_TYPE (18): + The given placeholder type cannot be mapped + to a system generated feed with the given type. + ATTRIBUTE_FIELD_MAPPING_MISSING_FIELD (19): + The "field" oneof was not set in an + AttributeFieldMapping. + LEGACY_FEED_TYPE_READ_ONLY (20): + Feed is read only. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_PLACEHOLDER_FIELD = 2 + INVALID_CRITERION_FIELD = 3 + INVALID_PLACEHOLDER_TYPE = 4 + INVALID_CRITERION_TYPE = 5 + NO_ATTRIBUTE_FIELD_MAPPINGS = 7 + FEED_ATTRIBUTE_TYPE_MISMATCH = 8 + CANNOT_OPERATE_ON_MAPPINGS_FOR_SYSTEM_GENERATED_FEED = 9 + MULTIPLE_MAPPINGS_FOR_PLACEHOLDER_TYPE = 10 + MULTIPLE_MAPPINGS_FOR_CRITERION_TYPE = 11 + MULTIPLE_MAPPINGS_FOR_PLACEHOLDER_FIELD = 12 + MULTIPLE_MAPPINGS_FOR_CRITERION_FIELD = 13 + UNEXPECTED_ATTRIBUTE_FIELD_MAPPINGS = 14 + LOCATION_PLACEHOLDER_ONLY_FOR_PLACES_FEEDS = 15 + CANNOT_MODIFY_MAPPINGS_FOR_TYPED_FEED = 16 + INVALID_PLACEHOLDER_TYPE_FOR_NON_SYSTEM_GENERATED_FEED = 17 + INVALID_PLACEHOLDER_TYPE_FOR_SYSTEM_GENERATED_FEED_TYPE = 18 + ATTRIBUTE_FIELD_MAPPING_MISSING_FIELD = 19 + LEGACY_FEED_TYPE_READ_ONLY = 20 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/field_error.py b/google/ads/googleads/v24/errors/types/field_error.py new file mode 100644 index 000000000..ff63db54f --- /dev/null +++ b/google/ads/googleads/v24/errors/types/field_error.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "FieldErrorEnum", + }, +) + + +class FieldErrorEnum(proto.Message): + r"""Container for enum describing possible field errors.""" + + class FieldError(proto.Enum): + r"""Enum describing possible field errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + REQUIRED (2): + The required field was not present. + IMMUTABLE_FIELD (3): + The field attempted to be mutated is + immutable. + INVALID_VALUE (4): + The field's value is invalid. + VALUE_MUST_BE_UNSET (5): + The field cannot be set. + REQUIRED_NONEMPTY_LIST (6): + The required repeated field was empty. + FIELD_CANNOT_BE_CLEARED (7): + The field cannot be cleared. + BLOCKED_VALUE (9): + The field's value is on a deny-list for this + field. + FIELD_CAN_ONLY_BE_CLEARED (10): + The field's value cannot be modified, except + for clearing. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + REQUIRED = 2 + IMMUTABLE_FIELD = 3 + INVALID_VALUE = 4 + VALUE_MUST_BE_UNSET = 5 + REQUIRED_NONEMPTY_LIST = 6 + FIELD_CANNOT_BE_CLEARED = 7 + BLOCKED_VALUE = 9 + FIELD_CAN_ONLY_BE_CLEARED = 10 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/field_mask_error.py b/google/ads/googleads/v24/errors/types/field_mask_error.py new file mode 100644 index 000000000..9791722db --- /dev/null +++ b/google/ads/googleads/v24/errors/types/field_mask_error.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "FieldMaskErrorEnum", + }, +) + + +class FieldMaskErrorEnum(proto.Message): + r"""Container for enum describing possible field mask errors.""" + + class FieldMaskError(proto.Enum): + r"""Enum describing possible field mask errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + FIELD_MASK_MISSING (5): + The field mask must be provided for update + operations. + FIELD_MASK_NOT_ALLOWED (4): + The field mask must be empty for create and + remove operations. + FIELD_NOT_FOUND (2): + The field mask contained an invalid field. + FIELD_HAS_SUBFIELDS (3): + The field mask updated a field with + subfields. Fields with subfields may be cleared, + but not updated. To fix this, the field mask + should select all the subfields of the invalid + field. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + FIELD_MASK_MISSING = 5 + FIELD_MASK_NOT_ALLOWED = 4 + FIELD_NOT_FOUND = 2 + FIELD_HAS_SUBFIELDS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/final_url_expansion_asset_view_error.py b/google/ads/googleads/v24/errors/types/final_url_expansion_asset_view_error.py new file mode 100644 index 000000000..12e090362 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/final_url_expansion_asset_view_error.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "FinalUrlExpansionAssetViewErrorEnum", + }, +) + + +class FinalUrlExpansionAssetViewErrorEnum(proto.Message): + r"""Container for enum describing possible final url expansion + asset view errors. + + """ + + class FinalUrlExpansionAssetViewError(proto.Enum): + r"""Enum describing possible final url expansion asset view + errors. + + Values: + UNSPECIFIED (0): + Name unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + MISSING_REQUIRED_FILTER (2): + At least one required filter has to be + applied in the query. + REQUIRES_ADVERTISING_CHANNEL_TYPE_FILTER (3): + Advertising channel type filter is required. + INVALID_ADVERTISING_CHANNEL_TYPE_IN_FILTER (4): + Advertising channel type filter has an + invalid value. + CANNOT_SELECT_ASSET_GROUP (5): + Asset group cannot be selected in the query. + CANNOT_SELECT_AD_GROUP (6): + Ad group cannot be selected in the query. + REQUIRES_FILTER_BY_SINGLE_RESOURCE (7): + A selected field/resource requires filtering + by a single resource. + CANNOT_SELECT_BOTH_AD_GROUP_AND_ASSET_GROUP (8): + Both ad group and asset group cannot be + selected in the query. + CANNOT_FILTER_BY_BOTH_AD_GROUP_AND_ASSET_GROUP (9): + Both ad group and asset group cannot be + filtered in the query. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MISSING_REQUIRED_FILTER = 2 + REQUIRES_ADVERTISING_CHANNEL_TYPE_FILTER = 3 + INVALID_ADVERTISING_CHANNEL_TYPE_IN_FILTER = 4 + CANNOT_SELECT_ASSET_GROUP = 5 + CANNOT_SELECT_AD_GROUP = 6 + REQUIRES_FILTER_BY_SINGLE_RESOURCE = 7 + CANNOT_SELECT_BOTH_AD_GROUP_AND_ASSET_GROUP = 8 + CANNOT_FILTER_BY_BOTH_AD_GROUP_AND_ASSET_GROUP = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/function_error.py b/google/ads/googleads/v24/errors/types/function_error.py new file mode 100644 index 000000000..c1fe45a7d --- /dev/null +++ b/google/ads/googleads/v24/errors/types/function_error.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "FunctionErrorEnum", + }, +) + + +class FunctionErrorEnum(proto.Message): + r"""Container for enum describing possible function errors.""" + + class FunctionError(proto.Enum): + r"""Enum describing possible function errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_FUNCTION_FORMAT (2): + The format of the function is not recognized + as a supported function format. + DATA_TYPE_MISMATCH (3): + Operand data types do not match. + INVALID_CONJUNCTION_OPERANDS (4): + The operands cannot be used together in a + conjunction. + INVALID_NUMBER_OF_OPERANDS (5): + Invalid numer of Operands. + INVALID_OPERAND_TYPE (6): + Operand Type not supported. + INVALID_OPERATOR (7): + Operator not supported. + INVALID_REQUEST_CONTEXT_TYPE (8): + Request context type not supported. + INVALID_FUNCTION_FOR_CALL_PLACEHOLDER (9): + The matching function is not allowed for call + placeholders + INVALID_FUNCTION_FOR_PLACEHOLDER (10): + The matching function is not allowed for the + specified placeholder + INVALID_OPERAND (11): + Invalid operand. + MISSING_CONSTANT_OPERAND_VALUE (12): + Missing value for the constant operand. + INVALID_CONSTANT_OPERAND_VALUE (13): + The value of the constant operand is invalid. + INVALID_NESTING (14): + Invalid function nesting. + MULTIPLE_FEED_IDS_NOT_SUPPORTED (15): + The Feed ID was different from another Feed + ID in the same function. + INVALID_FUNCTION_FOR_FEED_WITH_FIXED_SCHEMA (16): + The matching function is invalid for use with + a feed with a fixed schema. + INVALID_ATTRIBUTE_NAME (17): + Invalid attribute name. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_FUNCTION_FORMAT = 2 + DATA_TYPE_MISMATCH = 3 + INVALID_CONJUNCTION_OPERANDS = 4 + INVALID_NUMBER_OF_OPERANDS = 5 + INVALID_OPERAND_TYPE = 6 + INVALID_OPERATOR = 7 + INVALID_REQUEST_CONTEXT_TYPE = 8 + INVALID_FUNCTION_FOR_CALL_PLACEHOLDER = 9 + INVALID_FUNCTION_FOR_PLACEHOLDER = 10 + INVALID_OPERAND = 11 + MISSING_CONSTANT_OPERAND_VALUE = 12 + INVALID_CONSTANT_OPERAND_VALUE = 13 + INVALID_NESTING = 14 + MULTIPLE_FEED_IDS_NOT_SUPPORTED = 15 + INVALID_FUNCTION_FOR_FEED_WITH_FIXED_SCHEMA = 16 + INVALID_ATTRIBUTE_NAME = 17 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/function_parsing_error.py b/google/ads/googleads/v24/errors/types/function_parsing_error.py new file mode 100644 index 000000000..dd3a28636 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/function_parsing_error.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "FunctionParsingErrorEnum", + }, +) + + +class FunctionParsingErrorEnum(proto.Message): + r"""Container for enum describing possible function parsing + errors. + + """ + + class FunctionParsingError(proto.Enum): + r"""Enum describing possible function parsing errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + NO_MORE_INPUT (2): + Unexpected end of function string. + EXPECTED_CHARACTER (3): + Could not find an expected character. + UNEXPECTED_SEPARATOR (4): + Unexpected separator character. + UNMATCHED_LEFT_BRACKET (5): + Unmatched left bracket or parenthesis. + UNMATCHED_RIGHT_BRACKET (6): + Unmatched right bracket or parenthesis. + TOO_MANY_NESTED_FUNCTIONS (7): + Functions are nested too deeply. + MISSING_RIGHT_HAND_OPERAND (8): + Missing right-hand-side operand. + INVALID_OPERATOR_NAME (9): + Invalid operator/function name. + FEED_ATTRIBUTE_OPERAND_ARGUMENT_NOT_INTEGER (10): + Feed attribute operand's argument is not an + integer. + NO_OPERANDS (11): + Missing function operands. + TOO_MANY_OPERANDS (12): + Function had too many operands. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NO_MORE_INPUT = 2 + EXPECTED_CHARACTER = 3 + UNEXPECTED_SEPARATOR = 4 + UNMATCHED_LEFT_BRACKET = 5 + UNMATCHED_RIGHT_BRACKET = 6 + TOO_MANY_NESTED_FUNCTIONS = 7 + MISSING_RIGHT_HAND_OPERAND = 8 + INVALID_OPERATOR_NAME = 9 + FEED_ATTRIBUTE_OPERAND_ARGUMENT_NOT_INTEGER = 10 + NO_OPERANDS = 11 + TOO_MANY_OPERANDS = 12 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/geo_target_constant_suggestion_error.py b/google/ads/googleads/v24/errors/types/geo_target_constant_suggestion_error.py new file mode 100644 index 000000000..4543f912e --- /dev/null +++ b/google/ads/googleads/v24/errors/types/geo_target_constant_suggestion_error.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "GeoTargetConstantSuggestionErrorEnum", + }, +) + + +class GeoTargetConstantSuggestionErrorEnum(proto.Message): + r"""Container for enum describing possible geo target constant + suggestion errors. + + """ + + class GeoTargetConstantSuggestionError(proto.Enum): + r"""Enum describing possible geo target constant suggestion + errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + LOCATION_NAME_SIZE_LIMIT (2): + A location name cannot be greater than 300 + characters. + LOCATION_NAME_LIMIT (3): + At most 25 location names can be specified in + a SuggestGeoTargetConstants method. + INVALID_COUNTRY_CODE (4): + The country code is invalid. + REQUEST_PARAMETERS_UNSET (5): + Geo target constant resource names or + location names must be provided in the request. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LOCATION_NAME_SIZE_LIMIT = 2 + LOCATION_NAME_LIMIT = 3 + INVALID_COUNTRY_CODE = 4 + REQUEST_PARAMETERS_UNSET = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/goal_error.py b/google/ads/googleads/v24/errors/types/goal_error.py new file mode 100644 index 000000000..1e8db5bd1 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/goal_error.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "GoalErrorEnum", + }, +) + + +class GoalErrorEnum(proto.Message): + r"""Container for enum describing possible goal errors.""" + + class GoalError(proto.Enum): + r"""Enum describing possible goal errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + RETENTION_GOAL_ALREADY_EXISTS (4): + Retention goal already exists. + HIGH_LIFETIME_VALUE_PRESENT_BUT_VALUE_ABSENT (5): + When using customer lifecycle optimization + goal, if high lifetime value is present then + value should be present. + HIGH_LIFETIME_VALUE_LESS_THAN_OR_EQUAL_TO_VALUE (6): + When using customer lifecycle optimization + goal, high lifetime value should be greater than + value. + CUSTOMER_LIFECYCLE_OPTIMIZATION_ACCOUNT_TYPE_NOT_ALLOWED (7): + Only Google Ads account can have customer + lifecycle optimization goal. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + RETENTION_GOAL_ALREADY_EXISTS = 4 + HIGH_LIFETIME_VALUE_PRESENT_BUT_VALUE_ABSENT = 5 + HIGH_LIFETIME_VALUE_LESS_THAN_OR_EQUAL_TO_VALUE = 6 + CUSTOMER_LIFECYCLE_OPTIMIZATION_ACCOUNT_TYPE_NOT_ALLOWED = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/header_error.py b/google/ads/googleads/v24/errors/types/header_error.py new file mode 100644 index 000000000..ee5670995 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/header_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "HeaderErrorEnum", + }, +) + + +class HeaderErrorEnum(proto.Message): + r"""Container for enum describing possible header errors.""" + + class HeaderError(proto.Enum): + r"""Enum describing possible header errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_LOGIN_CUSTOMER_ID (3): + The login customer ID could not be validated. + INVALID_LINKED_CUSTOMER_ID (7): + The linked customer ID could not be + validated. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_LOGIN_CUSTOMER_ID = 3 + INVALID_LINKED_CUSTOMER_ID = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/id_error.py b/google/ads/googleads/v24/errors/types/id_error.py new file mode 100644 index 000000000..cdf87d9a8 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/id_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "IdErrorEnum", + }, +) + + +class IdErrorEnum(proto.Message): + r"""Container for enum describing possible ID errors.""" + + class IdError(proto.Enum): + r"""Enum describing possible ID errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + NOT_FOUND (2): + ID not found + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NOT_FOUND = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/identity_verification_error.py b/google/ads/googleads/v24/errors/types/identity_verification_error.py new file mode 100644 index 000000000..1d331a26d --- /dev/null +++ b/google/ads/googleads/v24/errors/types/identity_verification_error.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "IdentityVerificationErrorEnum", + }, +) + + +class IdentityVerificationErrorEnum(proto.Message): + r"""Container for enum describing possible identity verification + errors. + + """ + + class IdentityVerificationError(proto.Enum): + r"""Enum describing possible identity verification errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + NO_EFFECTIVE_BILLING (2): + No effective billing linked to this customer. + BILLING_NOT_ON_MONTHLY_INVOICING (3): + Customer is not on monthly invoicing. + VERIFICATION_ALREADY_STARTED (4): + Verification for this program type was + already started. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NO_EFFECTIVE_BILLING = 2 + BILLING_NOT_ON_MONTHLY_INVOICING = 3 + VERIFICATION_ALREADY_STARTED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/image_error.py b/google/ads/googleads/v24/errors/types/image_error.py new file mode 100644 index 000000000..666e04de7 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/image_error.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ImageErrorEnum", + }, +) + + +class ImageErrorEnum(proto.Message): + r"""Container for enum describing possible image errors.""" + + class ImageError(proto.Enum): + r"""Enum describing possible image errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_IMAGE (2): + The image is not valid. + STORAGE_ERROR (3): + The image could not be stored. + BAD_REQUEST (4): + There was a problem with the request. + UNEXPECTED_SIZE (5): + The image is not of legal dimensions. + ANIMATED_NOT_ALLOWED (6): + Animated image are not permitted. + ANIMATION_TOO_LONG (7): + Animation is too long. + SERVER_ERROR (8): + There was an error on the server. + CMYK_JPEG_NOT_ALLOWED (9): + Image cannot be in CMYK color format. + FLASH_NOT_ALLOWED (10): + Flash images are not permitted. + FLASH_WITHOUT_CLICKTAG (11): + Flash images must support clickTag. + FLASH_ERROR_AFTER_FIXING_CLICK_TAG (12): + A flash error has occurred after fixing the + click tag. + ANIMATED_VISUAL_EFFECT (13): + Unacceptable visual effects. + FLASH_ERROR (14): + There was a problem with the flash image. + LAYOUT_PROBLEM (15): + Incorrect image layout. + PROBLEM_READING_IMAGE_FILE (16): + There was a problem reading the image file. + ERROR_STORING_IMAGE (17): + There was an error storing the image. + ASPECT_RATIO_NOT_ALLOWED (18): + The aspect ratio of the image is not allowed. + FLASH_HAS_NETWORK_OBJECTS (19): + Flash cannot have network objects. + FLASH_HAS_NETWORK_METHODS (20): + Flash cannot have network methods. + FLASH_HAS_URL (21): + Flash cannot have a Url. + FLASH_HAS_MOUSE_TRACKING (22): + Flash cannot use mouse tracking. + FLASH_HAS_RANDOM_NUM (23): + Flash cannot have a random number. + FLASH_SELF_TARGETS (24): + Ad click target cannot be '\_self'. + FLASH_BAD_GETURL_TARGET (25): + GetUrl method should only use '\_blank'. + FLASH_VERSION_NOT_SUPPORTED (26): + Flash version is not supported. + FLASH_WITHOUT_HARD_CODED_CLICK_URL (27): + Flash movies need to have hard coded click + URL or clickTAG + INVALID_FLASH_FILE (28): + Uploaded flash file is corrupted. + FAILED_TO_FIX_CLICK_TAG_IN_FLASH (29): + Uploaded flash file can be parsed, but the + click tag can not be fixed properly. + FLASH_ACCESSES_NETWORK_RESOURCES (30): + Flash movie accesses network resources + FLASH_EXTERNAL_JS_CALL (31): + Flash movie attempts to call external + javascript code + FLASH_EXTERNAL_FS_CALL (32): + Flash movie attempts to call flash system + commands + FILE_TOO_LARGE (33): + Image file is too large. + IMAGE_DATA_TOO_LARGE (34): + Image data is too large. + IMAGE_PROCESSING_ERROR (35): + Error while processing the image. + IMAGE_TOO_SMALL (36): + Image is too small. + INVALID_INPUT (37): + Input was invalid. + PROBLEM_READING_FILE (38): + There was a problem reading the image file. + IMAGE_CONSTRAINTS_VIOLATED (39): + Image constraints are violated, but details like + ASPECT_RATIO_NOT_ALLOWED can't be provided. This happens + when asset spec contains more than one constraint and + different criteria of different constraints are violated. + FORMAT_NOT_ALLOWED (40): + Image format is not allowed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_IMAGE = 2 + STORAGE_ERROR = 3 + BAD_REQUEST = 4 + UNEXPECTED_SIZE = 5 + ANIMATED_NOT_ALLOWED = 6 + ANIMATION_TOO_LONG = 7 + SERVER_ERROR = 8 + CMYK_JPEG_NOT_ALLOWED = 9 + FLASH_NOT_ALLOWED = 10 + FLASH_WITHOUT_CLICKTAG = 11 + FLASH_ERROR_AFTER_FIXING_CLICK_TAG = 12 + ANIMATED_VISUAL_EFFECT = 13 + FLASH_ERROR = 14 + LAYOUT_PROBLEM = 15 + PROBLEM_READING_IMAGE_FILE = 16 + ERROR_STORING_IMAGE = 17 + ASPECT_RATIO_NOT_ALLOWED = 18 + FLASH_HAS_NETWORK_OBJECTS = 19 + FLASH_HAS_NETWORK_METHODS = 20 + FLASH_HAS_URL = 21 + FLASH_HAS_MOUSE_TRACKING = 22 + FLASH_HAS_RANDOM_NUM = 23 + FLASH_SELF_TARGETS = 24 + FLASH_BAD_GETURL_TARGET = 25 + FLASH_VERSION_NOT_SUPPORTED = 26 + FLASH_WITHOUT_HARD_CODED_CLICK_URL = 27 + INVALID_FLASH_FILE = 28 + FAILED_TO_FIX_CLICK_TAG_IN_FLASH = 29 + FLASH_ACCESSES_NETWORK_RESOURCES = 30 + FLASH_EXTERNAL_JS_CALL = 31 + FLASH_EXTERNAL_FS_CALL = 32 + FILE_TOO_LARGE = 33 + IMAGE_DATA_TOO_LARGE = 34 + IMAGE_PROCESSING_ERROR = 35 + IMAGE_TOO_SMALL = 36 + INVALID_INPUT = 37 + PROBLEM_READING_FILE = 38 + IMAGE_CONSTRAINTS_VIOLATED = 39 + FORMAT_NOT_ALLOWED = 40 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/incentive_error.py b/google/ads/googleads/v24/errors/types/incentive_error.py new file mode 100644 index 000000000..9aa8e3094 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/incentive_error.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "IncentiveErrorEnum", + }, +) + + +class IncentiveErrorEnum(proto.Message): + r"""Container for enum describing possible incentive errors.""" + + class IncentiveError(proto.Enum): + r"""Enum describing possible incentive errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_INCENTIVE_ID (2): + The incentive ID is either invalid or not + supported for the given country. + MAX_INCENTIVES_REDEEMED (3): + The maximum number of coupons has been + redeemed. + ACCOUNT_TOO_OLD (4): + This incentive cannot be applied because too + much time has passed since the account's first + ad impression. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_INCENTIVE_ID = 2 + MAX_INCENTIVES_REDEEMED = 3 + ACCOUNT_TOO_OLD = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/internal_error.py b/google/ads/googleads/v24/errors/types/internal_error.py new file mode 100644 index 000000000..5dc8ca531 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/internal_error.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "InternalErrorEnum", + }, +) + + +class InternalErrorEnum(proto.Message): + r"""Container for enum describing possible internal errors.""" + + class InternalError(proto.Enum): + r"""Enum describing possible internal errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INTERNAL_ERROR (2): + Google Ads API encountered unexpected + internal error. + ERROR_CODE_NOT_PUBLISHED (3): + The intended error code doesn't exist in + specified API version. It will be released in a + future API version. + TRANSIENT_ERROR (4): + Google Ads API encountered an unexpected + transient error. The user should retry their + request in these cases. + DEADLINE_EXCEEDED (5): + The request took longer than a deadline. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INTERNAL_ERROR = 2 + ERROR_CODE_NOT_PUBLISHED = 3 + TRANSIENT_ERROR = 4 + DEADLINE_EXCEEDED = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/invoice_error.py b/google/ads/googleads/v24/errors/types/invoice_error.py new file mode 100644 index 000000000..cbbef5f5c --- /dev/null +++ b/google/ads/googleads/v24/errors/types/invoice_error.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "InvoiceErrorEnum", + }, +) + + +class InvoiceErrorEnum(proto.Message): + r"""Container for enum describing possible invoice errors.""" + + class InvoiceError(proto.Enum): + r"""Enum describing possible invoice errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + YEAR_MONTH_TOO_OLD (2): + Cannot request invoices issued before + 2019-01-01. + NOT_INVOICED_CUSTOMER (3): + Cannot request invoices for customer who + doesn't receive invoices. + BILLING_SETUP_NOT_APPROVED (4): + Cannot request invoices for a non approved + billing setup. + BILLING_SETUP_NOT_ON_MONTHLY_INVOICING (5): + Cannot request invoices for a billing setup + that is not on monthly invoicing. + NON_SERVING_CUSTOMER (6): + Cannot request invoices for a non serving + customer. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + YEAR_MONTH_TOO_OLD = 2 + NOT_INVOICED_CUSTOMER = 3 + BILLING_SETUP_NOT_APPROVED = 4 + BILLING_SETUP_NOT_ON_MONTHLY_INVOICING = 5 + NON_SERVING_CUSTOMER = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/keyword_plan_ad_group_error.py b/google/ads/googleads/v24/errors/types/keyword_plan_ad_group_error.py new file mode 100644 index 000000000..dcc229632 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/keyword_plan_ad_group_error.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanAdGroupErrorEnum", + }, +) + + +class KeywordPlanAdGroupErrorEnum(proto.Message): + r"""Container for enum describing possible errors from applying a + keyword plan ad group. + + """ + + class KeywordPlanAdGroupError(proto.Enum): + r"""Enum describing possible errors from applying a keyword plan + ad group. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_NAME (2): + The keyword plan ad group name is missing, + empty, longer than allowed limit or contains + invalid chars. + DUPLICATE_NAME (3): + The keyword plan ad group name is duplicate + to an existing keyword plan AdGroup name or + other keyword plan AdGroup name in the request. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_NAME = 2 + DUPLICATE_NAME = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/keyword_plan_ad_group_keyword_error.py b/google/ads/googleads/v24/errors/types/keyword_plan_ad_group_keyword_error.py new file mode 100644 index 000000000..14f898456 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/keyword_plan_ad_group_keyword_error.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanAdGroupKeywordErrorEnum", + }, +) + + +class KeywordPlanAdGroupKeywordErrorEnum(proto.Message): + r"""Container for enum describing possible errors from applying + an ad group keyword or a campaign keyword from a keyword plan. + + """ + + class KeywordPlanAdGroupKeywordError(proto.Enum): + r"""Enum describing possible errors from applying a keyword plan + ad group keyword or keyword plan campaign keyword. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_KEYWORD_MATCH_TYPE (2): + A keyword or negative keyword has invalid + match type. + DUPLICATE_KEYWORD (3): + A keyword or negative keyword with same text + and match type already exists. + KEYWORD_TEXT_TOO_LONG (4): + Keyword or negative keyword text exceeds the + allowed limit. + KEYWORD_HAS_INVALID_CHARS (5): + Keyword or negative keyword text has invalid + characters or symbols. + KEYWORD_HAS_TOO_MANY_WORDS (6): + Keyword or negative keyword text has too many + words. + INVALID_KEYWORD_TEXT (7): + Keyword or negative keyword has invalid text. + NEGATIVE_KEYWORD_HAS_CPC_BID (8): + Cpc Bid set for negative keyword. + NEW_BMM_KEYWORDS_NOT_ALLOWED (9): + New broad match modifier (BMM) + KpAdGroupKeywords are not allowed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_KEYWORD_MATCH_TYPE = 2 + DUPLICATE_KEYWORD = 3 + KEYWORD_TEXT_TOO_LONG = 4 + KEYWORD_HAS_INVALID_CHARS = 5 + KEYWORD_HAS_TOO_MANY_WORDS = 6 + INVALID_KEYWORD_TEXT = 7 + NEGATIVE_KEYWORD_HAS_CPC_BID = 8 + NEW_BMM_KEYWORDS_NOT_ALLOWED = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/keyword_plan_campaign_error.py b/google/ads/googleads/v24/errors/types/keyword_plan_campaign_error.py new file mode 100644 index 000000000..3618ffd66 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/keyword_plan_campaign_error.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanCampaignErrorEnum", + }, +) + + +class KeywordPlanCampaignErrorEnum(proto.Message): + r"""Container for enum describing possible errors from applying a + keyword plan campaign. + + """ + + class KeywordPlanCampaignError(proto.Enum): + r"""Enum describing possible errors from applying a keyword plan + campaign. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_NAME (2): + A keyword plan campaign name is missing, + empty, longer than allowed limit or contains + invalid chars. + INVALID_LANGUAGES (3): + A keyword plan campaign contains one or more + untargetable languages. + INVALID_GEOS (4): + A keyword plan campaign contains one or more + invalid geo targets. + DUPLICATE_NAME (5): + The keyword plan campaign name is duplicate + to an existing keyword plan campaign name or + other keyword plan campaign name in the request. + MAX_GEOS_EXCEEDED (6): + The number of geo targets in the keyword plan + campaign exceeds limits. + MAX_LANGUAGES_EXCEEDED (7): + The number of languages in the keyword plan + campaign exceeds limits. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_NAME = 2 + INVALID_LANGUAGES = 3 + INVALID_GEOS = 4 + DUPLICATE_NAME = 5 + MAX_GEOS_EXCEEDED = 6 + MAX_LANGUAGES_EXCEEDED = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/keyword_plan_campaign_keyword_error.py b/google/ads/googleads/v24/errors/types/keyword_plan_campaign_keyword_error.py new file mode 100644 index 000000000..9bfe6deb0 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/keyword_plan_campaign_keyword_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanCampaignKeywordErrorEnum", + }, +) + + +class KeywordPlanCampaignKeywordErrorEnum(proto.Message): + r"""Container for enum describing possible errors from applying a + keyword plan campaign keyword. + + """ + + class KeywordPlanCampaignKeywordError(proto.Enum): + r"""Enum describing possible errors from applying a keyword plan + campaign keyword. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CAMPAIGN_KEYWORD_IS_POSITIVE (8): + Keyword plan campaign keyword is positive. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CAMPAIGN_KEYWORD_IS_POSITIVE = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/keyword_plan_error.py b/google/ads/googleads/v24/errors/types/keyword_plan_error.py new file mode 100644 index 000000000..3c63598b2 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/keyword_plan_error.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanErrorEnum", + }, +) + + +class KeywordPlanErrorEnum(proto.Message): + r"""Container for enum describing possible errors from applying a + keyword plan resource (keyword plan, keyword plan campaign, + keyword plan ad group or keyword plan keyword) or + KeywordPlanService RPC. + + """ + + class KeywordPlanError(proto.Enum): + r"""Enum describing possible errors from applying a keyword plan. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + BID_MULTIPLIER_OUT_OF_RANGE (2): + The plan's bid multiplier value is outside + the valid range. + BID_TOO_HIGH (3): + The plan's bid value is too high. + BID_TOO_LOW (4): + The plan's bid value is too low. + BID_TOO_MANY_FRACTIONAL_DIGITS (5): + The plan's cpc bid is not a multiple of the + minimum billable unit. + DAILY_BUDGET_TOO_LOW (6): + The plan's daily budget value is too low. + DAILY_BUDGET_TOO_MANY_FRACTIONAL_DIGITS (7): + The plan's daily budget is not a multiple of + the minimum billable unit. + INVALID_VALUE (8): + The input has an invalid value. + KEYWORD_PLAN_HAS_NO_KEYWORDS (9): + The plan has no keyword. + KEYWORD_PLAN_NOT_ENABLED (10): + The plan is not enabled and API cannot + provide mutation, forecast or stats. + KEYWORD_PLAN_NOT_FOUND (11): + The requested plan cannot be found for + providing forecast or stats. + MISSING_BID (13): + The plan is missing a cpc bid. + MISSING_FORECAST_PERIOD (14): + The plan is missing required forecast_period field. + INVALID_FORECAST_DATE_RANGE (15): + The plan's forecast_period has invalid forecast date range. + INVALID_NAME (16): + The plan's name is invalid. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BID_MULTIPLIER_OUT_OF_RANGE = 2 + BID_TOO_HIGH = 3 + BID_TOO_LOW = 4 + BID_TOO_MANY_FRACTIONAL_DIGITS = 5 + DAILY_BUDGET_TOO_LOW = 6 + DAILY_BUDGET_TOO_MANY_FRACTIONAL_DIGITS = 7 + INVALID_VALUE = 8 + KEYWORD_PLAN_HAS_NO_KEYWORDS = 9 + KEYWORD_PLAN_NOT_ENABLED = 10 + KEYWORD_PLAN_NOT_FOUND = 11 + MISSING_BID = 13 + MISSING_FORECAST_PERIOD = 14 + INVALID_FORECAST_DATE_RANGE = 15 + INVALID_NAME = 16 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/keyword_plan_idea_error.py b/google/ads/googleads/v24/errors/types/keyword_plan_idea_error.py new file mode 100644 index 000000000..13ecad208 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/keyword_plan_idea_error.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanIdeaErrorEnum", + }, +) + + +class KeywordPlanIdeaErrorEnum(proto.Message): + r"""Container for enum describing possible errors from + KeywordPlanIdeaService. + + """ + + class KeywordPlanIdeaError(proto.Enum): + r"""Enum describing possible errors from KeywordPlanIdeaService. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + URL_CRAWL_ERROR (2): + Error when crawling the input URL. + INVALID_VALUE (3): + The input has an invalid value. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + URL_CRAWL_ERROR = 2 + INVALID_VALUE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/label_error.py b/google/ads/googleads/v24/errors/types/label_error.py new file mode 100644 index 000000000..802257c74 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/label_error.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "LabelErrorEnum", + }, +) + + +class LabelErrorEnum(proto.Message): + r"""Container for enum describing possible label errors.""" + + class LabelError(proto.Enum): + r"""Enum describing possible label errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CANNOT_APPLY_INACTIVE_LABEL (2): + An inactive label cannot be applied. + CANNOT_APPLY_LABEL_TO_DISABLED_AD_GROUP_CRITERION (3): + A label cannot be applied to a disabled ad + group criterion. + CANNOT_APPLY_LABEL_TO_NEGATIVE_AD_GROUP_CRITERION (4): + A label cannot be applied to a negative ad + group criterion. + EXCEEDED_LABEL_LIMIT_PER_TYPE (5): + Cannot apply more than 50 labels per + resource. + INVALID_RESOURCE_FOR_MANAGER_LABEL (6): + Labels from a manager account cannot be + applied to campaign, ad group, ad group ad, or + ad group criterion resources. + DUPLICATE_NAME (7): + Label names must be unique. + INVALID_LABEL_NAME (8): + Label names cannot be empty. + CANNOT_ATTACH_LABEL_TO_DRAFT (9): + Labels cannot be applied to a draft. + CANNOT_ATTACH_NON_MANAGER_LABEL_TO_CUSTOMER (10): + Labels not from a manager account cannot be + applied to the customer resource. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CANNOT_APPLY_INACTIVE_LABEL = 2 + CANNOT_APPLY_LABEL_TO_DISABLED_AD_GROUP_CRITERION = 3 + CANNOT_APPLY_LABEL_TO_NEGATIVE_AD_GROUP_CRITERION = 4 + EXCEEDED_LABEL_LIMIT_PER_TYPE = 5 + INVALID_RESOURCE_FOR_MANAGER_LABEL = 6 + DUPLICATE_NAME = 7 + INVALID_LABEL_NAME = 8 + CANNOT_ATTACH_LABEL_TO_DRAFT = 9 + CANNOT_ATTACH_NON_MANAGER_LABEL_TO_CUSTOMER = 10 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/language_code_error.py b/google/ads/googleads/v24/errors/types/language_code_error.py new file mode 100644 index 000000000..ed4f0cf9f --- /dev/null +++ b/google/ads/googleads/v24/errors/types/language_code_error.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "LanguageCodeErrorEnum", + }, +) + + +class LanguageCodeErrorEnum(proto.Message): + r"""Container for enum describing language code errors.""" + + class LanguageCodeError(proto.Enum): + r"""Enum describing language code errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + LANGUAGE_CODE_NOT_FOUND (2): + The input language code is not recognized. + INVALID_LANGUAGE_CODE (3): + The language code is not supported. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + LANGUAGE_CODE_NOT_FOUND = 2 + INVALID_LANGUAGE_CODE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/list_operation_error.py b/google/ads/googleads/v24/errors/types/list_operation_error.py new file mode 100644 index 000000000..908cf735e --- /dev/null +++ b/google/ads/googleads/v24/errors/types/list_operation_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ListOperationErrorEnum", + }, +) + + +class ListOperationErrorEnum(proto.Message): + r"""Container for enum describing possible list operation errors.""" + + class ListOperationError(proto.Enum): + r"""Enum describing possible list operation errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + REQUIRED_FIELD_MISSING (7): + Field required in value is missing. + DUPLICATE_VALUES (8): + Duplicate or identical value is sent in + multiple list operations. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + REQUIRED_FIELD_MISSING = 7 + DUPLICATE_VALUES = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/manager_link_error.py b/google/ads/googleads/v24/errors/types/manager_link_error.py new file mode 100644 index 000000000..923a9a3ef --- /dev/null +++ b/google/ads/googleads/v24/errors/types/manager_link_error.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ManagerLinkErrorEnum", + }, +) + + +class ManagerLinkErrorEnum(proto.Message): + r"""Container for enum describing possible ManagerLink errors.""" + + class ManagerLinkError(proto.Enum): + r"""Enum describing possible ManagerLink errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + ACCOUNTS_NOT_COMPATIBLE_FOR_LINKING (2): + The manager and client have incompatible + account types. + TOO_MANY_MANAGERS (3): + Client is already linked to too many + managers. + TOO_MANY_INVITES (4): + Manager has too many pending invitations. + ALREADY_INVITED_BY_THIS_MANAGER (5): + Client is already invited by this manager. + ALREADY_MANAGED_BY_THIS_MANAGER (6): + The client is already managed by this + manager. + ALREADY_MANAGED_IN_HIERARCHY (7): + Client is already managed in hierarchy. + DUPLICATE_CHILD_FOUND (8): + Manager and sub-manager to be linked have + duplicate client. + CLIENT_HAS_NO_ADMIN_USER (9): + Client has no active user that can access the + client account. + MAX_DEPTH_EXCEEDED (10): + Adding this link would exceed the maximum + hierarchy depth. + CYCLE_NOT_ALLOWED (11): + Adding this link will create a cycle. + TOO_MANY_ACCOUNTS (12): + Manager account has the maximum number of + linked clients. + TOO_MANY_ACCOUNTS_AT_MANAGER (13): + Parent manager account has the maximum number + of linked clients. + NON_OWNER_USER_CANNOT_MODIFY_LINK (14): + The account is not authorized owner. + SUSPENDED_ACCOUNT_CANNOT_ADD_CLIENTS (15): + Your manager account is suspended, and you + are no longer allowed to link to clients. + CLIENT_OUTSIDE_TREE (16): + You are not allowed to move a client to a + manager that is not under your current + hierarchy. + INVALID_STATUS_CHANGE (17): + The changed status for mutate link is + invalid. + INVALID_CHANGE (18): + The change for mutate link is invalid. + CUSTOMER_CANNOT_MANAGE_SELF (19): + You are not allowed to link a manager account + to itself. + CREATING_ENABLED_LINK_NOT_ALLOWED (20): + The link was created with status ACTIVE and + not PENDING. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ACCOUNTS_NOT_COMPATIBLE_FOR_LINKING = 2 + TOO_MANY_MANAGERS = 3 + TOO_MANY_INVITES = 4 + ALREADY_INVITED_BY_THIS_MANAGER = 5 + ALREADY_MANAGED_BY_THIS_MANAGER = 6 + ALREADY_MANAGED_IN_HIERARCHY = 7 + DUPLICATE_CHILD_FOUND = 8 + CLIENT_HAS_NO_ADMIN_USER = 9 + MAX_DEPTH_EXCEEDED = 10 + CYCLE_NOT_ALLOWED = 11 + TOO_MANY_ACCOUNTS = 12 + TOO_MANY_ACCOUNTS_AT_MANAGER = 13 + NON_OWNER_USER_CANNOT_MODIFY_LINK = 14 + SUSPENDED_ACCOUNT_CANNOT_ADD_CLIENTS = 15 + CLIENT_OUTSIDE_TREE = 16 + INVALID_STATUS_CHANGE = 17 + INVALID_CHANGE = 18 + CUSTOMER_CANNOT_MANAGE_SELF = 19 + CREATING_ENABLED_LINK_NOT_ALLOWED = 20 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/media_bundle_error.py b/google/ads/googleads/v24/errors/types/media_bundle_error.py new file mode 100644 index 000000000..af69503e4 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/media_bundle_error.py @@ -0,0 +1,124 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "MediaBundleErrorEnum", + }, +) + + +class MediaBundleErrorEnum(proto.Message): + r"""Container for enum describing possible media bundle errors.""" + + class MediaBundleError(proto.Enum): + r"""Enum describing possible media bundle errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + BAD_REQUEST (3): + There was a problem with the request. + DOUBLECLICK_BUNDLE_NOT_ALLOWED (4): + HTML5 ads using DoubleClick Studio created + ZIP files are not supported. + EXTERNAL_URL_NOT_ALLOWED (5): + Cannot reference URL external to the media + bundle. + FILE_TOO_LARGE (6): + Media bundle file is too large. + GOOGLE_WEB_DESIGNER_ZIP_FILE_NOT_PUBLISHED (7): + ZIP file from Google Web Designer is not + published. + INVALID_INPUT (8): + Input was invalid. + INVALID_MEDIA_BUNDLE (9): + There was a problem with the media bundle. + INVALID_MEDIA_BUNDLE_ENTRY (10): + There was a problem with one or more of the + media bundle entries. + INVALID_MIME_TYPE (11): + The media bundle contains a file with an + unknown mime type + INVALID_PATH (12): + The media bundle contain an invalid asset + path. + INVALID_URL_REFERENCE (13): + HTML5 ad is trying to reference an asset not + in .ZIP file + MEDIA_DATA_TOO_LARGE (14): + Media data is too large. + MISSING_PRIMARY_MEDIA_BUNDLE_ENTRY (15): + The media bundle contains no primary entry. + SERVER_ERROR (16): + There was an error on the server. + STORAGE_ERROR (17): + The image could not be stored. + SWIFFY_BUNDLE_NOT_ALLOWED (18): + Media bundle created with the Swiffy tool is + not allowed. + TOO_MANY_FILES (19): + The media bundle contains too many files. + UNEXPECTED_SIZE (20): + The media bundle is not of legal dimensions. + UNSUPPORTED_GOOGLE_WEB_DESIGNER_ENVIRONMENT (21): + Google Web Designer not created for "Google + Ads" environment. + UNSUPPORTED_HTML5_FEATURE (22): + Unsupported HTML5 feature in HTML5 asset. + URL_IN_MEDIA_BUNDLE_NOT_SSL_COMPLIANT (23): + URL in HTML5 entry is not ssl compliant. + CUSTOM_EXIT_NOT_ALLOWED (24): + Custom exits not allowed in HTML5 entry. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BAD_REQUEST = 3 + DOUBLECLICK_BUNDLE_NOT_ALLOWED = 4 + EXTERNAL_URL_NOT_ALLOWED = 5 + FILE_TOO_LARGE = 6 + GOOGLE_WEB_DESIGNER_ZIP_FILE_NOT_PUBLISHED = 7 + INVALID_INPUT = 8 + INVALID_MEDIA_BUNDLE = 9 + INVALID_MEDIA_BUNDLE_ENTRY = 10 + INVALID_MIME_TYPE = 11 + INVALID_PATH = 12 + INVALID_URL_REFERENCE = 13 + MEDIA_DATA_TOO_LARGE = 14 + MISSING_PRIMARY_MEDIA_BUNDLE_ENTRY = 15 + SERVER_ERROR = 16 + STORAGE_ERROR = 17 + SWIFFY_BUNDLE_NOT_ALLOWED = 18 + TOO_MANY_FILES = 19 + UNEXPECTED_SIZE = 20 + UNSUPPORTED_GOOGLE_WEB_DESIGNER_ENVIRONMENT = 21 + UNSUPPORTED_HTML5_FEATURE = 22 + URL_IN_MEDIA_BUNDLE_NOT_SSL_COMPLIANT = 23 + CUSTOM_EXIT_NOT_ALLOWED = 24 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/media_file_error.py b/google/ads/googleads/v24/errors/types/media_file_error.py new file mode 100644 index 000000000..53e38a906 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/media_file_error.py @@ -0,0 +1,127 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "MediaFileErrorEnum", + }, +) + + +class MediaFileErrorEnum(proto.Message): + r"""Container for enum describing possible media file errors.""" + + class MediaFileError(proto.Enum): + r"""Enum describing possible media file errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CANNOT_CREATE_STANDARD_ICON (2): + Cannot create a standard icon type. + CANNOT_SELECT_STANDARD_ICON_WITH_OTHER_TYPES (3): + May only select Standard Icons alone. + CANNOT_SPECIFY_MEDIA_FILE_ID_AND_DATA (4): + Image contains both a media file ID and data. + DUPLICATE_MEDIA (5): + A media file with given type and reference ID + already exists. + EMPTY_FIELD (6): + A required field was not specified or is an + empty string. + RESOURCE_REFERENCED_IN_MULTIPLE_OPS (7): + A media file may only be modified once per + call. + FIELD_NOT_SUPPORTED_FOR_MEDIA_SUB_TYPE (8): + Field is not supported for the media sub + type. + INVALID_MEDIA_FILE_ID (9): + The media file ID is invalid. + INVALID_MEDIA_SUB_TYPE (10): + The media subtype is invalid. + INVALID_MEDIA_FILE_TYPE (11): + The media file type is invalid. + INVALID_MIME_TYPE (12): + The mimetype is invalid. + INVALID_REFERENCE_ID (13): + The media reference ID is invalid. + INVALID_YOU_TUBE_ID (14): + The YouTube video ID is invalid. + MEDIA_FILE_FAILED_TRANSCODING (15): + Media file has failed transcoding + MEDIA_NOT_TRANSCODED (16): + Media file has not been transcoded. + MEDIA_TYPE_DOES_NOT_MATCH_MEDIA_FILE_TYPE (17): + The media type does not match the actual + media file's type. + NO_FIELDS_SPECIFIED (18): + None of the fields have been specified. + NULL_REFERENCE_ID_AND_MEDIA_ID (19): + One of reference ID or media file ID must be + specified. + TOO_LONG (20): + The string has too many characters. + UNSUPPORTED_TYPE (21): + The specified type is not supported. + YOU_TUBE_SERVICE_UNAVAILABLE (22): + YouTube is unavailable for requesting video + data. + YOU_TUBE_VIDEO_HAS_NON_POSITIVE_DURATION (23): + The YouTube video has a non positive + duration. + YOU_TUBE_VIDEO_NOT_FOUND (24): + The YouTube video ID is syntactically valid + but the video was not found. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CANNOT_CREATE_STANDARD_ICON = 2 + CANNOT_SELECT_STANDARD_ICON_WITH_OTHER_TYPES = 3 + CANNOT_SPECIFY_MEDIA_FILE_ID_AND_DATA = 4 + DUPLICATE_MEDIA = 5 + EMPTY_FIELD = 6 + RESOURCE_REFERENCED_IN_MULTIPLE_OPS = 7 + FIELD_NOT_SUPPORTED_FOR_MEDIA_SUB_TYPE = 8 + INVALID_MEDIA_FILE_ID = 9 + INVALID_MEDIA_SUB_TYPE = 10 + INVALID_MEDIA_FILE_TYPE = 11 + INVALID_MIME_TYPE = 12 + INVALID_REFERENCE_ID = 13 + INVALID_YOU_TUBE_ID = 14 + MEDIA_FILE_FAILED_TRANSCODING = 15 + MEDIA_NOT_TRANSCODED = 16 + MEDIA_TYPE_DOES_NOT_MATCH_MEDIA_FILE_TYPE = 17 + NO_FIELDS_SPECIFIED = 18 + NULL_REFERENCE_ID_AND_MEDIA_ID = 19 + TOO_LONG = 20 + UNSUPPORTED_TYPE = 21 + YOU_TUBE_SERVICE_UNAVAILABLE = 22 + YOU_TUBE_VIDEO_HAS_NON_POSITIVE_DURATION = 23 + YOU_TUBE_VIDEO_NOT_FOUND = 24 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/media_upload_error.py b/google/ads/googleads/v24/errors/types/media_upload_error.py new file mode 100644 index 000000000..04475fec1 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/media_upload_error.py @@ -0,0 +1,176 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "MediaUploadErrorEnum", + }, +) + + +class MediaUploadErrorEnum(proto.Message): + r"""Container for enum describing possible media uploading + errors. + + """ + + class MediaUploadError(proto.Enum): + r"""Enum describing possible media uploading errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + FILE_TOO_BIG (2): + The uploaded file is too big. + UNPARSEABLE_IMAGE (3): + Image data is unparseable. + ANIMATED_IMAGE_NOT_ALLOWED (4): + Animated images are not allowed. + FORMAT_NOT_ALLOWED (5): + The image or media bundle format is not + allowed. + EXTERNAL_URL_NOT_ALLOWED (6): + Cannot reference URL external to the media + bundle. + INVALID_URL_REFERENCE (7): + HTML5 ad is trying to reference an asset not + in .ZIP file. + MISSING_PRIMARY_MEDIA_BUNDLE_ENTRY (8): + The media bundle contains no primary entry. + ANIMATED_VISUAL_EFFECT (9): + Animation has disallowed visual effects. + ANIMATION_TOO_LONG (10): + Animation longer than the allowed 30 second + limit. + ASPECT_RATIO_NOT_ALLOWED (11): + The aspect ratio of the image does not match + the expected aspect ratios provided in the asset + spec. + AUDIO_NOT_ALLOWED_IN_MEDIA_BUNDLE (12): + Audio files are not allowed in bundle. + CMYK_JPEG_NOT_ALLOWED (13): + CMYK jpegs are not supported. + FLASH_NOT_ALLOWED (14): + Flash movies are not allowed. + FRAME_RATE_TOO_HIGH (15): + The frame rate of the video is higher than + the allowed 5fps. + GOOGLE_WEB_DESIGNER_ZIP_FILE_NOT_PUBLISHED (16): + ZIP file from Google Web Designer is not + published. + IMAGE_CONSTRAINTS_VIOLATED (17): + Image constraints are violated, but more details (like + DIMENSIONS_NOT_ALLOWED or ASPECT_RATIO_NOT_ALLOWED) can not + be provided. This happens when asset spec contains more than + one constraint and criteria of different constraints are + violated. + INVALID_MEDIA_BUNDLE (18): + Media bundle data is unrecognizable. + INVALID_MEDIA_BUNDLE_ENTRY (19): + There was a problem with one or more of the + media bundle entries. + INVALID_MIME_TYPE (20): + The asset has an invalid mime type. + INVALID_PATH (21): + The media bundle contains an invalid asset + path. + LAYOUT_PROBLEM (22): + Image has layout problem. + MALFORMED_URL (23): + An asset had a URL reference that is + malformed per RFC 1738 convention. + MEDIA_BUNDLE_NOT_ALLOWED (24): + The uploaded media bundle format is not + allowed. + MEDIA_BUNDLE_NOT_COMPATIBLE_TO_PRODUCT_TYPE (25): + The media bundle is not compatible with the + asset spec product type. (For example, Gmail, + dynamic remarketing, etc.) + MEDIA_BUNDLE_REJECTED_BY_MULTIPLE_ASSET_SPECS (26): + A bundle being uploaded that is incompatible + with multiple assets for different reasons. + TOO_MANY_FILES_IN_MEDIA_BUNDLE (27): + The media bundle contains too many files. + UNSUPPORTED_GOOGLE_WEB_DESIGNER_ENVIRONMENT (28): + Google Web Designer not created for "Google + Ads" environment. + UNSUPPORTED_HTML5_FEATURE (29): + Unsupported HTML5 feature in HTML5 asset. + URL_IN_MEDIA_BUNDLE_NOT_SSL_COMPLIANT (30): + URL in HTML5 entry is not SSL compliant. + VIDEO_FILE_NAME_TOO_LONG (31): + Video file name is longer than the 50 allowed + characters. + VIDEO_MULTIPLE_FILES_WITH_SAME_NAME (32): + Multiple videos with same name in a bundle. + VIDEO_NOT_ALLOWED_IN_MEDIA_BUNDLE (33): + Videos are not allowed in media bundle. + CANNOT_UPLOAD_MEDIA_TYPE_THROUGH_API (34): + This type of media cannot be uploaded through + the Google Ads API. + DIMENSIONS_NOT_ALLOWED (35): + The dimensions of the image are not allowed. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + FILE_TOO_BIG = 2 + UNPARSEABLE_IMAGE = 3 + ANIMATED_IMAGE_NOT_ALLOWED = 4 + FORMAT_NOT_ALLOWED = 5 + EXTERNAL_URL_NOT_ALLOWED = 6 + INVALID_URL_REFERENCE = 7 + MISSING_PRIMARY_MEDIA_BUNDLE_ENTRY = 8 + ANIMATED_VISUAL_EFFECT = 9 + ANIMATION_TOO_LONG = 10 + ASPECT_RATIO_NOT_ALLOWED = 11 + AUDIO_NOT_ALLOWED_IN_MEDIA_BUNDLE = 12 + CMYK_JPEG_NOT_ALLOWED = 13 + FLASH_NOT_ALLOWED = 14 + FRAME_RATE_TOO_HIGH = 15 + GOOGLE_WEB_DESIGNER_ZIP_FILE_NOT_PUBLISHED = 16 + IMAGE_CONSTRAINTS_VIOLATED = 17 + INVALID_MEDIA_BUNDLE = 18 + INVALID_MEDIA_BUNDLE_ENTRY = 19 + INVALID_MIME_TYPE = 20 + INVALID_PATH = 21 + LAYOUT_PROBLEM = 22 + MALFORMED_URL = 23 + MEDIA_BUNDLE_NOT_ALLOWED = 24 + MEDIA_BUNDLE_NOT_COMPATIBLE_TO_PRODUCT_TYPE = 25 + MEDIA_BUNDLE_REJECTED_BY_MULTIPLE_ASSET_SPECS = 26 + TOO_MANY_FILES_IN_MEDIA_BUNDLE = 27 + UNSUPPORTED_GOOGLE_WEB_DESIGNER_ENVIRONMENT = 28 + UNSUPPORTED_HTML5_FEATURE = 29 + URL_IN_MEDIA_BUNDLE_NOT_SSL_COMPLIANT = 30 + VIDEO_FILE_NAME_TOO_LONG = 31 + VIDEO_MULTIPLE_FILES_WITH_SAME_NAME = 32 + VIDEO_NOT_ALLOWED_IN_MEDIA_BUNDLE = 33 + CANNOT_UPLOAD_MEDIA_TYPE_THROUGH_API = 34 + DIMENSIONS_NOT_ALLOWED = 35 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/merchant_center_error.py b/google/ads/googleads/v24/errors/types/merchant_center_error.py new file mode 100644 index 000000000..ff7dd22fe --- /dev/null +++ b/google/ads/googleads/v24/errors/types/merchant_center_error.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "MerchantCenterErrorEnum", + }, +) + + +class MerchantCenterErrorEnum(proto.Message): + r"""Container for enum describing possible merchant center + errors. + + """ + + class MerchantCenterError(proto.Enum): + r"""Enum describing Merchant Center errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + MERCHANT_ID_CANNOT_BE_ACCESSED (2): + Merchant ID is either not found or not linked + to the Google Ads customer. + CUSTOMER_NOT_ALLOWED_FOR_SHOPPING_PERFORMANCE_MAX (3): + Customer not allowlisted for Shopping in + Performance Max Campaign. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MERCHANT_ID_CANNOT_BE_ACCESSED = 2 + CUSTOMER_NOT_ALLOWED_FOR_SHOPPING_PERFORMANCE_MAX = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/multiplier_error.py b/google/ads/googleads/v24/errors/types/multiplier_error.py new file mode 100644 index 000000000..836dbb229 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/multiplier_error.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "MultiplierErrorEnum", + }, +) + + +class MultiplierErrorEnum(proto.Message): + r"""Container for enum describing possible multiplier errors.""" + + class MultiplierError(proto.Enum): + r"""Enum describing possible multiplier errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + MULTIPLIER_TOO_HIGH (2): + Multiplier value is too high + MULTIPLIER_TOO_LOW (3): + Multiplier value is too low + TOO_MANY_FRACTIONAL_DIGITS (4): + Too many fractional digits + MULTIPLIER_NOT_ALLOWED_FOR_BIDDING_STRATEGY (5): + A multiplier cannot be set for this bidding + strategy + MULTIPLIER_NOT_ALLOWED_WHEN_BASE_BID_IS_MISSING (6): + A multiplier cannot be set when there is no + base bid (for example, content max cpc) + NO_MULTIPLIER_SPECIFIED (7): + A bid multiplier must be specified + MULTIPLIER_CAUSES_BID_TO_EXCEED_DAILY_BUDGET (8): + Multiplier causes bid to exceed daily budget + MULTIPLIER_CAUSES_BID_TO_EXCEED_MONTHLY_BUDGET (9): + Multiplier causes bid to exceed monthly + budget + MULTIPLIER_CAUSES_BID_TO_EXCEED_CUSTOM_BUDGET (10): + Multiplier causes bid to exceed custom budget + MULTIPLIER_CAUSES_BID_TO_EXCEED_MAX_ALLOWED_BID (11): + Multiplier causes bid to exceed maximum + allowed bid + BID_LESS_THAN_MIN_ALLOWED_BID_WITH_MULTIPLIER (12): + Multiplier causes bid to become less than the + minimum bid allowed + MULTIPLIER_AND_BIDDING_STRATEGY_TYPE_MISMATCH (13): + Multiplier type (cpc versus cpm) needs to + match campaign's bidding strategy + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MULTIPLIER_TOO_HIGH = 2 + MULTIPLIER_TOO_LOW = 3 + TOO_MANY_FRACTIONAL_DIGITS = 4 + MULTIPLIER_NOT_ALLOWED_FOR_BIDDING_STRATEGY = 5 + MULTIPLIER_NOT_ALLOWED_WHEN_BASE_BID_IS_MISSING = 6 + NO_MULTIPLIER_SPECIFIED = 7 + MULTIPLIER_CAUSES_BID_TO_EXCEED_DAILY_BUDGET = 8 + MULTIPLIER_CAUSES_BID_TO_EXCEED_MONTHLY_BUDGET = 9 + MULTIPLIER_CAUSES_BID_TO_EXCEED_CUSTOM_BUDGET = 10 + MULTIPLIER_CAUSES_BID_TO_EXCEED_MAX_ALLOWED_BID = 11 + BID_LESS_THAN_MIN_ALLOWED_BID_WITH_MULTIPLIER = 12 + MULTIPLIER_AND_BIDDING_STRATEGY_TYPE_MISMATCH = 13 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/mutate_error.py b/google/ads/googleads/v24/errors/types/mutate_error.py new file mode 100644 index 000000000..8700dd6e8 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/mutate_error.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "MutateErrorEnum", + }, +) + + +class MutateErrorEnum(proto.Message): + r"""Container for enum describing possible mutate errors.""" + + class MutateError(proto.Enum): + r"""Enum describing possible mutate errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + RESOURCE_NOT_FOUND (3): + Requested resource was not found. + ID_EXISTS_IN_MULTIPLE_MUTATES (7): + Cannot mutate the same resource twice in one + request. + INCONSISTENT_FIELD_VALUES (8): + The field's contents don't match another + field that represents the same data. + MUTATE_NOT_ALLOWED (9): + Mutates are not allowed for the requested + resource. + RESOURCE_NOT_IN_GOOGLE_ADS (10): + The resource isn't in Google Ads. It belongs + to another ads system. + RESOURCE_ALREADY_EXISTS (11): + The resource being created already exists. + RESOURCE_DOES_NOT_SUPPORT_VALIDATE_ONLY (12): + This resource cannot be used with "validate_only". + OPERATION_DOES_NOT_SUPPORT_PARTIAL_FAILURE (16): + This operation cannot be used with "partial_failure". + RESOURCE_READ_ONLY (13): + Attempt to write to read-only fields. + EU_POLITICAL_ADVERTISING_DECLARATION_REQUIRED (17): + Mutates are generally not allowed if the + customer contains non-exempt campaigns without + the EU political advertising declaration. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + RESOURCE_NOT_FOUND = 3 + ID_EXISTS_IN_MULTIPLE_MUTATES = 7 + INCONSISTENT_FIELD_VALUES = 8 + MUTATE_NOT_ALLOWED = 9 + RESOURCE_NOT_IN_GOOGLE_ADS = 10 + RESOURCE_ALREADY_EXISTS = 11 + RESOURCE_DOES_NOT_SUPPORT_VALIDATE_ONLY = 12 + OPERATION_DOES_NOT_SUPPORT_PARTIAL_FAILURE = 16 + RESOURCE_READ_ONLY = 13 + EU_POLITICAL_ADVERTISING_DECLARATION_REQUIRED = 17 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/new_resource_creation_error.py b/google/ads/googleads/v24/errors/types/new_resource_creation_error.py new file mode 100644 index 000000000..84bdb5b52 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/new_resource_creation_error.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "NewResourceCreationErrorEnum", + }, +) + + +class NewResourceCreationErrorEnum(proto.Message): + r"""Container for enum describing possible new resource creation + errors. + + """ + + class NewResourceCreationError(proto.Enum): + r"""Enum describing possible new resource creation errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CANNOT_SET_ID_FOR_CREATE (2): + Do not set the id field while creating new + resources. + DUPLICATE_TEMP_IDS (3): + Creating more than one resource with the same + temp ID is not allowed. + TEMP_ID_RESOURCE_HAD_ERRORS (4): + Parent resource with specified temp ID failed + validation, so no validation will be done for + this child resource. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CANNOT_SET_ID_FOR_CREATE = 2 + DUPLICATE_TEMP_IDS = 3 + TEMP_ID_RESOURCE_HAD_ERRORS = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/not_allowlisted_error.py b/google/ads/googleads/v24/errors/types/not_allowlisted_error.py new file mode 100644 index 000000000..1a81a4460 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/not_allowlisted_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "NotAllowlistedErrorEnum", + }, +) + + +class NotAllowlistedErrorEnum(proto.Message): + r"""Container for enum describing possible not allowlisted + errors. + + """ + + class NotAllowlistedError(proto.Enum): + r"""Enum describing possible not allowlisted errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CUSTOMER_NOT_ALLOWLISTED_FOR_THIS_FEATURE (2): + Customer is not allowlisted for accessing + this feature. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER_NOT_ALLOWLISTED_FOR_THIS_FEATURE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/not_empty_error.py b/google/ads/googleads/v24/errors/types/not_empty_error.py new file mode 100644 index 000000000..a77d7b199 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/not_empty_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "NotEmptyErrorEnum", + }, +) + + +class NotEmptyErrorEnum(proto.Message): + r"""Container for enum describing possible not empty errors.""" + + class NotEmptyError(proto.Enum): + r"""Enum describing possible not empty errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + EMPTY_LIST (2): + Empty list. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EMPTY_LIST = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/null_error.py b/google/ads/googleads/v24/errors/types/null_error.py new file mode 100644 index 000000000..ed2defea4 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/null_error.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "NullErrorEnum", + }, +) + + +class NullErrorEnum(proto.Message): + r"""Container for enum describing possible null errors.""" + + class NullError(proto.Enum): + r"""Enum describing possible null errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + NULL_CONTENT (2): + Specified list/container must not contain any + null elements + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NULL_CONTENT = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/offline_user_data_job_error.py b/google/ads/googleads/v24/errors/types/offline_user_data_job_error.py new file mode 100644 index 000000000..21d4ee170 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/offline_user_data_job_error.py @@ -0,0 +1,211 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "OfflineUserDataJobErrorEnum", + }, +) + + +class OfflineUserDataJobErrorEnum(proto.Message): + r"""Container for enum describing possible offline user data job + errors. + + """ + + class OfflineUserDataJobError(proto.Enum): + r"""Enum describing possible request errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_USER_LIST_ID (3): + The user list ID provided for the job is + invalid. + INVALID_USER_LIST_TYPE (4): + Type of the user list is not applicable for + the job. + NOT_ON_ALLOWLIST_FOR_USER_ID (33): + Customer is not allowisted for using user ID + in upload data. + INCOMPATIBLE_UPLOAD_KEY_TYPE (6): + Upload data is not compatible with the upload + key type of the associated user list. + MISSING_USER_IDENTIFIER (7): + The user identifier is missing valid data. + INVALID_MOBILE_ID_FORMAT (8): + The mobile ID is malformed. + TOO_MANY_USER_IDENTIFIERS (9): + Maximum number of user identifiers allowed + per request is 100,000 and per operation is 20. + NOT_ON_ALLOWLIST_FOR_STORE_SALES_DIRECT (31): + Customer is not on the allow-list for store + sales direct data. + NOT_ON_ALLOWLIST_FOR_UNIFIED_STORE_SALES (32): + Customer is not on the allow-list for unified + store sales data. + INVALID_PARTNER_ID (11): + The partner ID in store sales direct metadata + is invalid. + INVALID_ENCODING (12): + The data in user identifier should not be + encoded. + INVALID_COUNTRY_CODE (13): + The country code is invalid. + INCOMPATIBLE_USER_IDENTIFIER (14): + Incompatible user identifier when using third_party_user_id + for store sales direct first party data or not using + third_party_user_id for store sales third party data. + FUTURE_TRANSACTION_TIME (15): + A transaction time in the future is not + allowed. + INVALID_CONVERSION_ACTION (16): + The conversion_action specified in transaction_attributes is + used to report conversions to a conversion action configured + in Google Ads. This error indicates there is no such + conversion action in the account. + MOBILE_ID_NOT_SUPPORTED (17): + Mobile ID is not supported for store sales + direct data. + INVALID_OPERATION_ORDER (18): + When a remove-all operation is provided, it + has to be the first operation of the operation + list. + CONFLICTING_OPERATION (19): + Mixing creation and removal of offline data + in the same job is not allowed. + EXTERNAL_UPDATE_ID_ALREADY_EXISTS (21): + The external update ID already exists. + JOB_ALREADY_STARTED (22): + Once the upload job is started, new + operations cannot be added. + REMOVE_NOT_SUPPORTED (23): + Remove operation is not allowed for store + sales direct updates. + REMOVE_ALL_NOT_SUPPORTED (24): + Remove-all is not supported for certain + offline user data job types. + INVALID_SHA256_FORMAT (25): + The SHA256 encoded value is malformed. + CUSTOM_KEY_DISABLED (26): + The custom key specified is not enabled for + the unified store sales upload. + CUSTOM_KEY_NOT_PREDEFINED (27): + The custom key specified is not predefined + through the Google Ads UI. + CUSTOM_KEY_NOT_SET (29): + The custom key specified is not set in the + upload. + CUSTOMER_NOT_ACCEPTED_CUSTOMER_DATA_TERMS (30): + The customer has not accepted the customer + data terms in the conversion settings page. + ATTRIBUTES_NOT_APPLICABLE_FOR_CUSTOMER_MATCH_USER_LIST (34): + User attributes cannot be uploaded into a + user list. + LIFETIME_VALUE_BUCKET_NOT_IN_RANGE (35): + Lifetime bucket value must be a number from 0 + to 10; 0 is only accepted for remove operations + INCOMPATIBLE_USER_IDENTIFIER_FOR_ATTRIBUTES (36): + Identifiers not supported for Customer Match + attributes. User attributes can only be provided + with contact info (email, phone, address) user + identifiers. + FUTURE_TIME_NOT_ALLOWED (37): + A time in the future is not allowed. + LAST_PURCHASE_TIME_LESS_THAN_ACQUISITION_TIME (38): + Last purchase date time cannot be less than + acquisition date time. + CUSTOMER_IDENTIFIER_NOT_ALLOWED (39): + Only emails are accepted as user identifiers + for shopping loyalty match. {-- + api.dev/not-precedent: The identifier is not + limited to ids, but also include other user info + eg. phone numbers.} + INVALID_ITEM_ID (40): + Provided item ID is invalid. + FIRST_PURCHASE_TIME_GREATER_THAN_LAST_PURCHASE_TIME (42): + First purchase date time cannot be greater + than the last purchase date time. + INVALID_LIFECYCLE_STAGE (43): + Provided lifecycle stage is invalid. + INVALID_EVENT_VALUE (44): + The event value of the Customer Match user + attribute is invalid. + EVENT_ATTRIBUTE_ALL_FIELDS_ARE_REQUIRED (45): + All the fields are not present in the + EventAttribute of the Customer Match. + OPERATION_LEVEL_CONSENT_PROVIDED (48): + Consent was provided at the operation level + for an OfflineUserDataJobType that expects it at + the job level. The provided operation-level + consent will be ignored. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_USER_LIST_ID = 3 + INVALID_USER_LIST_TYPE = 4 + NOT_ON_ALLOWLIST_FOR_USER_ID = 33 + INCOMPATIBLE_UPLOAD_KEY_TYPE = 6 + MISSING_USER_IDENTIFIER = 7 + INVALID_MOBILE_ID_FORMAT = 8 + TOO_MANY_USER_IDENTIFIERS = 9 + NOT_ON_ALLOWLIST_FOR_STORE_SALES_DIRECT = 31 + NOT_ON_ALLOWLIST_FOR_UNIFIED_STORE_SALES = 32 + INVALID_PARTNER_ID = 11 + INVALID_ENCODING = 12 + INVALID_COUNTRY_CODE = 13 + INCOMPATIBLE_USER_IDENTIFIER = 14 + FUTURE_TRANSACTION_TIME = 15 + INVALID_CONVERSION_ACTION = 16 + MOBILE_ID_NOT_SUPPORTED = 17 + INVALID_OPERATION_ORDER = 18 + CONFLICTING_OPERATION = 19 + EXTERNAL_UPDATE_ID_ALREADY_EXISTS = 21 + JOB_ALREADY_STARTED = 22 + REMOVE_NOT_SUPPORTED = 23 + REMOVE_ALL_NOT_SUPPORTED = 24 + INVALID_SHA256_FORMAT = 25 + CUSTOM_KEY_DISABLED = 26 + CUSTOM_KEY_NOT_PREDEFINED = 27 + CUSTOM_KEY_NOT_SET = 29 + CUSTOMER_NOT_ACCEPTED_CUSTOMER_DATA_TERMS = 30 + ATTRIBUTES_NOT_APPLICABLE_FOR_CUSTOMER_MATCH_USER_LIST = 34 + LIFETIME_VALUE_BUCKET_NOT_IN_RANGE = 35 + INCOMPATIBLE_USER_IDENTIFIER_FOR_ATTRIBUTES = 36 + FUTURE_TIME_NOT_ALLOWED = 37 + LAST_PURCHASE_TIME_LESS_THAN_ACQUISITION_TIME = 38 + CUSTOMER_IDENTIFIER_NOT_ALLOWED = 39 + INVALID_ITEM_ID = 40 + FIRST_PURCHASE_TIME_GREATER_THAN_LAST_PURCHASE_TIME = 42 + INVALID_LIFECYCLE_STAGE = 43 + INVALID_EVENT_VALUE = 44 + EVENT_ATTRIBUTE_ALL_FIELDS_ARE_REQUIRED = 45 + OPERATION_LEVEL_CONSENT_PROVIDED = 48 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/operation_access_denied_error.py b/google/ads/googleads/v24/errors/types/operation_access_denied_error.py new file mode 100644 index 000000000..6c148ed75 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/operation_access_denied_error.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "OperationAccessDeniedErrorEnum", + }, +) + + +class OperationAccessDeniedErrorEnum(proto.Message): + r"""Container for enum describing possible operation access + denied errors. + + """ + + class OperationAccessDeniedError(proto.Enum): + r"""Enum describing possible operation access denied errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + ACTION_NOT_PERMITTED (2): + Unauthorized invocation of a service's method + (get, mutate, etc.) + CREATE_OPERATION_NOT_PERMITTED (3): + Unauthorized CREATE operation in invoking a + service's mutate method. + REMOVE_OPERATION_NOT_PERMITTED (4): + Unauthorized REMOVE operation in invoking a + service's mutate method. + UPDATE_OPERATION_NOT_PERMITTED (5): + Unauthorized UPDATE operation in invoking a + service's mutate method. + MUTATE_ACTION_NOT_PERMITTED_FOR_CLIENT (6): + A mutate action is not allowed on this + resource, from this client. + OPERATION_NOT_PERMITTED_FOR_CAMPAIGN_TYPE (7): + This operation is not permitted on this + campaign type + CREATE_AS_REMOVED_NOT_PERMITTED (8): + A CREATE operation may not set status to + REMOVED. + OPERATION_NOT_PERMITTED_FOR_REMOVED_RESOURCE (9): + This operation is not allowed because the + resource is removed. + OPERATION_NOT_PERMITTED_FOR_AD_GROUP_TYPE (10): + This operation is not permitted on this ad + group type. + MUTATE_NOT_PERMITTED_FOR_CUSTOMER (11): + The mutate is not allowed for this customer. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ACTION_NOT_PERMITTED = 2 + CREATE_OPERATION_NOT_PERMITTED = 3 + REMOVE_OPERATION_NOT_PERMITTED = 4 + UPDATE_OPERATION_NOT_PERMITTED = 5 + MUTATE_ACTION_NOT_PERMITTED_FOR_CLIENT = 6 + OPERATION_NOT_PERMITTED_FOR_CAMPAIGN_TYPE = 7 + CREATE_AS_REMOVED_NOT_PERMITTED = 8 + OPERATION_NOT_PERMITTED_FOR_REMOVED_RESOURCE = 9 + OPERATION_NOT_PERMITTED_FOR_AD_GROUP_TYPE = 10 + MUTATE_NOT_PERMITTED_FOR_CUSTOMER = 11 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/operator_error.py b/google/ads/googleads/v24/errors/types/operator_error.py new file mode 100644 index 000000000..5df0a36f5 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/operator_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "OperatorErrorEnum", + }, +) + + +class OperatorErrorEnum(proto.Message): + r"""Container for enum describing possible operator errors.""" + + class OperatorError(proto.Enum): + r"""Enum describing possible operator errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + OPERATOR_NOT_SUPPORTED (2): + Operator not supported. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + OPERATOR_NOT_SUPPORTED = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/partial_failure_error.py b/google/ads/googleads/v24/errors/types/partial_failure_error.py new file mode 100644 index 000000000..9cecdba74 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/partial_failure_error.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "PartialFailureErrorEnum", + }, +) + + +class PartialFailureErrorEnum(proto.Message): + r"""Container for enum describing possible partial failure + errors. + + """ + + class PartialFailureError(proto.Enum): + r"""Enum describing possible partial failure errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + PARTIAL_FAILURE_MODE_REQUIRED (2): + The partial failure field was false in the + request. This method requires this field be set + to true. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + PARTIAL_FAILURE_MODE_REQUIRED = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/payments_account_error.py b/google/ads/googleads/v24/errors/types/payments_account_error.py new file mode 100644 index 000000000..15ebb2f81 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/payments_account_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "PaymentsAccountErrorEnum", + }, +) + + +class PaymentsAccountErrorEnum(proto.Message): + r"""Container for enum describing possible errors in payments + account service. + + """ + + class PaymentsAccountError(proto.Enum): + r"""Enum describing possible errors in payments account service. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + NOT_SUPPORTED_FOR_MANAGER_CUSTOMER (2): + Manager customers are not supported for + payments account service. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NOT_SUPPORTED_FOR_MANAGER_CUSTOMER = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/policy_finding_error.py b/google/ads/googleads/v24/errors/types/policy_finding_error.py new file mode 100644 index 000000000..071f5fa08 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/policy_finding_error.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "PolicyFindingErrorEnum", + }, +) + + +class PolicyFindingErrorEnum(proto.Message): + r"""Container for enum describing possible policy finding errors.""" + + class PolicyFindingError(proto.Enum): + r"""Enum describing possible policy finding errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + POLICY_FINDING (2): + The resource has been disapproved since the + policy summary includes policy topics of type + PROHIBITED. + POLICY_TOPIC_NOT_FOUND (3): + The given policy topic does not exist. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + POLICY_FINDING = 2 + POLICY_TOPIC_NOT_FOUND = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/policy_validation_parameter_error.py b/google/ads/googleads/v24/errors/types/policy_validation_parameter_error.py new file mode 100644 index 000000000..68cb08df9 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/policy_validation_parameter_error.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "PolicyValidationParameterErrorEnum", + }, +) + + +class PolicyValidationParameterErrorEnum(proto.Message): + r"""Container for enum describing possible policy validation + parameter errors. + + """ + + class PolicyValidationParameterError(proto.Enum): + r"""Enum describing possible policy validation parameter errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + UNSUPPORTED_AD_TYPE_FOR_IGNORABLE_POLICY_TOPICS (2): + Ignorable policy topics are not supported for + the ad type. + UNSUPPORTED_AD_TYPE_FOR_EXEMPT_POLICY_VIOLATION_KEYS (3): + Exempt policy violation keys are not + supported for the ad type. + CANNOT_SET_BOTH_IGNORABLE_POLICY_TOPICS_AND_EXEMPT_POLICY_VIOLATION_KEYS (4): + Cannot set ignorable policy topics and exempt + policy violation keys in the same policy + violation parameter. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UNSUPPORTED_AD_TYPE_FOR_IGNORABLE_POLICY_TOPICS = 2 + UNSUPPORTED_AD_TYPE_FOR_EXEMPT_POLICY_VIOLATION_KEYS = 3 + CANNOT_SET_BOTH_IGNORABLE_POLICY_TOPICS_AND_EXEMPT_POLICY_VIOLATION_KEYS = ( + 4 + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/policy_violation_error.py b/google/ads/googleads/v24/errors/types/policy_violation_error.py new file mode 100644 index 000000000..0b4b20bd5 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/policy_violation_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "PolicyViolationErrorEnum", + }, +) + + +class PolicyViolationErrorEnum(proto.Message): + r"""Container for enum describing possible policy violation + errors. + + """ + + class PolicyViolationError(proto.Enum): + r"""Enum describing possible policy violation errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + POLICY_ERROR (2): + A policy was violated. See + PolicyViolationDetails for more detail. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + POLICY_ERROR = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/product_link_error.py b/google/ads/googleads/v24/errors/types/product_link_error.py new file mode 100644 index 000000000..6636ea1bb --- /dev/null +++ b/google/ads/googleads/v24/errors/types/product_link_error.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ProductLinkErrorEnum", + }, +) + + +class ProductLinkErrorEnum(proto.Message): + r"""Container for enum describing possible ProductLink errors.""" + + class ProductLinkError(proto.Enum): + r"""Enum describing possible ProductLink errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_OPERATION (2): + The requested operation is invalid. For + example, you are not allowed to remove a link + from a partner account. + CREATION_NOT_PERMITTED (3): + The creation request is not permitted. + INVITATION_EXISTS (4): + A link cannot be created because a pending + link already exists. + LINK_EXISTS (5): + A link cannot be created because an active + link already exists. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_OPERATION = 2 + CREATION_NOT_PERMITTED = 3 + INVITATION_EXISTS = 4 + LINK_EXISTS = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/product_link_invitation_error.py b/google/ads/googleads/v24/errors/types/product_link_invitation_error.py new file mode 100644 index 000000000..cf77cc9f7 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/product_link_invitation_error.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ProductLinkInvitationErrorEnum", + }, +) + + +class ProductLinkInvitationErrorEnum(proto.Message): + r"""Container for enum describing possible product link + invitation errors. + + """ + + class ProductLinkInvitationError(proto.Enum): + r"""Enum describing possible product link invitation errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in the + version. + INVALID_STATUS (2): + The invitation status is invalid. + PERMISSION_DENIED (3): + The customer doesn't have the permission to + perform this action + NO_INVITATION_REQUIRED (4): + An invitation could not be created, since the + user already has admin access to the invited + account. Use the ProductLinkService to directly + create an active link. + CUSTOMER_NOT_PERMITTED_TO_CREATE_INVITATION (5): + The customer is not permitted to create the + invitation. + INVALID_ADVERTISING_PARTNER_ALLOWED_DOMAIN (6): + The ``allowed_domain`` property for the advertising partner + is invalid. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_STATUS = 2 + PERMISSION_DENIED = 3 + NO_INVITATION_REQUIRED = 4 + CUSTOMER_NOT_PERMITTED_TO_CREATE_INVITATION = 5 + INVALID_ADVERTISING_PARTNER_ALLOWED_DOMAIN = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/query_error.py b/google/ads/googleads/v24/errors/types/query_error.py new file mode 100644 index 000000000..2d355ff2a --- /dev/null +++ b/google/ads/googleads/v24/errors/types/query_error.py @@ -0,0 +1,268 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "QueryErrorEnum", + }, +) + + +class QueryErrorEnum(proto.Message): + r"""Container for enum describing possible query errors.""" + + class QueryError(proto.Enum): + r"""Enum describing possible query errors. + + Values: + UNSPECIFIED (0): + Name unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + QUERY_ERROR (50): + Returned if all other query error reasons are + not applicable. + BAD_ENUM_CONSTANT (18): + A condition used in the query references an + invalid enum constant. + BAD_ESCAPE_SEQUENCE (7): + Query contains an invalid escape sequence. + BAD_FIELD_NAME (12): + Field name is invalid. + BAD_LIMIT_VALUE (15): + Limit value is invalid (for example, not a + number) + BAD_NUMBER (5): + Encountered number can not be parsed. + BAD_OPERATOR (3): + Invalid operator encountered. + BAD_PARAMETER_NAME (61): + Parameter unknown or not supported. + BAD_PARAMETER_VALUE (62): + Parameter have invalid value. + BAD_RESOURCE_TYPE_IN_FROM_CLAUSE (45): + Invalid resource type was specified in the + FROM clause. + BAD_SYMBOL (2): + Non-ASCII symbol encountered outside of + strings. + BAD_VALUE (4): + Value is invalid. + DATE_RANGE_TOO_WIDE (36): + Date filters fail to restrict date to a range + smaller than 31 days. Applicable if the query is + segmented by date. + DATE_RANGE_TOO_NARROW (60): + Filters on date/week/month/quarter have a + start date after end date. + EXPECTED_AND (30): + Expected AND between values with BETWEEN + operator. + EXPECTED_BY (14): + Expecting ORDER BY to have BY. + EXPECTED_DIMENSION_FIELD_IN_SELECT_CLAUSE (37): + There was no dimension field selected. + EXPECTED_FILTERS_ON_DATE_RANGE (55): + Missing filters on date related fields. + EXPECTED_FROM (44): + Missing FROM clause. + EXPECTED_LIST (41): + The operator used in the conditions requires + the value to be a list. + EXPECTED_REFERENCED_FIELD_IN_SELECT_CLAUSE (16): + Fields used in WHERE or ORDER BY clauses are + missing from the SELECT clause. + EXPECTED_SELECT (13): + SELECT is missing at the beginning of query. + EXPECTED_SINGLE_VALUE (42): + A list was passed as a value to a condition + whose operator expects a single value. + EXPECTED_VALUE_WITH_BETWEEN_OPERATOR (29): + Missing one or both values with BETWEEN + operator. + INVALID_DATE_FORMAT (38): + Invalid date format. Expected 'YYYY-MM-DD'. + MISALIGNED_DATE_FOR_FILTER (64): + Misaligned date value for the filter. The + date should be the start of a week/month/quarter + if the filtered field is + segments.week/segments.month/segments.quarter. + INVALID_STRING_VALUE (57): + Value passed was not a string when it should + have been. For example, it was a number or + unquoted literal. + INVALID_VALUE_WITH_BETWEEN_OPERATOR (26): + A String value passed to the BETWEEN operator + does not parse as a date. + INVALID_VALUE_WITH_DURING_OPERATOR (22): + The value passed to the DURING operator is + not a Date range literal + INVALID_VALUE_WITH_LIKE_OPERATOR (56): + An invalid value was passed to the LIKE + operator. + OPERATOR_FIELD_MISMATCH (35): + An operator was provided that is inapplicable + to the field being filtered. + PROHIBITED_EMPTY_LIST_IN_CONDITION (28): + A Condition was found with an empty list. + PROHIBITED_ENUM_CONSTANT (54): + A condition used in the query references an + unsupported enum constant. + PROHIBITED_FIELD_COMBINATION_IN_SELECT_CLAUSE (31): + Fields that are not allowed to be selected + together were included in the SELECT clause. + PROHIBITED_FIELD_IN_ORDER_BY_CLAUSE (40): + A field that is not orderable was included in + the ORDER BY clause. + PROHIBITED_FIELD_IN_SELECT_CLAUSE (23): + A field that is not selectable was included + in the SELECT clause. + PROHIBITED_FIELD_IN_WHERE_CLAUSE (24): + A field that is not filterable was included + in the WHERE clause. + PROHIBITED_RESOURCE_TYPE_IN_FROM_CLAUSE (43): + Resource type specified in the FROM clause is + not supported by this service. + PROHIBITED_RESOURCE_TYPE_IN_SELECT_CLAUSE (48): + A field that comes from an incompatible + resource was included in the SELECT clause. + PROHIBITED_RESOURCE_TYPE_IN_WHERE_CLAUSE (58): + A field that comes from an incompatible + resource was included in the WHERE clause. + PROHIBITED_METRIC_IN_SELECT_OR_WHERE_CLAUSE (49): + A metric incompatible with the main resource + or other selected segmenting resources was + included in the SELECT or WHERE clause. + PROHIBITED_SEGMENT_IN_SELECT_OR_WHERE_CLAUSE (51): + A segment incompatible with the main resource + or other selected segmenting resources was + included in the SELECT or WHERE clause. + PROHIBITED_SEGMENT_WITH_METRIC_IN_SELECT_OR_WHERE_CLAUSE (53): + A segment in the SELECT clause is + incompatible with a metric in the SELECT or + WHERE clause. + PROHIBITED_FIELD_OR_SEGMENT_WITH_METRIC (65): + A metric may not be selected with one of the + selected resource fields, or segmented by one of + the selected segment fields. + LIMIT_VALUE_TOO_LOW (25): + The value passed to the limit clause is too + low. + PROHIBITED_NEWLINE_IN_STRING (8): + Query has a string containing a newline + character. + PROHIBITED_VALUE_COMBINATION_IN_LIST (10): + List contains values of different types. + PROHIBITED_VALUE_COMBINATION_WITH_BETWEEN_OPERATOR (21): + The values passed to the BETWEEN operator are + not of the same type. + STRING_NOT_TERMINATED (6): + Query contains unterminated string. + TOO_MANY_SEGMENTS (34): + Too many segments are specified in SELECT + clause. + UNEXPECTED_END_OF_QUERY (9): + Query is incomplete and cannot be parsed. + UNEXPECTED_FROM_CLAUSE (47): + FROM clause cannot be specified in this + query. + UNRECOGNIZED_FIELD (32): + Query contains one or more unrecognized + fields. + UNEXPECTED_INPUT (11): + Query has an unexpected extra part. + REQUESTED_METRICS_FOR_MANAGER (59): + Metrics cannot be requested for a manager + account. To retrieve metrics, issue separate + requests against each client account under the + manager account. + FILTER_HAS_TOO_MANY_VALUES (63): + The number of values (right-hand-side + operands) in a filter exceeds the limit. + REQUIRED_SEGMENT_FIELD_MISSING (66): + Required segment field is missing. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + QUERY_ERROR = 50 + BAD_ENUM_CONSTANT = 18 + BAD_ESCAPE_SEQUENCE = 7 + BAD_FIELD_NAME = 12 + BAD_LIMIT_VALUE = 15 + BAD_NUMBER = 5 + BAD_OPERATOR = 3 + BAD_PARAMETER_NAME = 61 + BAD_PARAMETER_VALUE = 62 + BAD_RESOURCE_TYPE_IN_FROM_CLAUSE = 45 + BAD_SYMBOL = 2 + BAD_VALUE = 4 + DATE_RANGE_TOO_WIDE = 36 + DATE_RANGE_TOO_NARROW = 60 + EXPECTED_AND = 30 + EXPECTED_BY = 14 + EXPECTED_DIMENSION_FIELD_IN_SELECT_CLAUSE = 37 + EXPECTED_FILTERS_ON_DATE_RANGE = 55 + EXPECTED_FROM = 44 + EXPECTED_LIST = 41 + EXPECTED_REFERENCED_FIELD_IN_SELECT_CLAUSE = 16 + EXPECTED_SELECT = 13 + EXPECTED_SINGLE_VALUE = 42 + EXPECTED_VALUE_WITH_BETWEEN_OPERATOR = 29 + INVALID_DATE_FORMAT = 38 + MISALIGNED_DATE_FOR_FILTER = 64 + INVALID_STRING_VALUE = 57 + INVALID_VALUE_WITH_BETWEEN_OPERATOR = 26 + INVALID_VALUE_WITH_DURING_OPERATOR = 22 + INVALID_VALUE_WITH_LIKE_OPERATOR = 56 + OPERATOR_FIELD_MISMATCH = 35 + PROHIBITED_EMPTY_LIST_IN_CONDITION = 28 + PROHIBITED_ENUM_CONSTANT = 54 + PROHIBITED_FIELD_COMBINATION_IN_SELECT_CLAUSE = 31 + PROHIBITED_FIELD_IN_ORDER_BY_CLAUSE = 40 + PROHIBITED_FIELD_IN_SELECT_CLAUSE = 23 + PROHIBITED_FIELD_IN_WHERE_CLAUSE = 24 + PROHIBITED_RESOURCE_TYPE_IN_FROM_CLAUSE = 43 + PROHIBITED_RESOURCE_TYPE_IN_SELECT_CLAUSE = 48 + PROHIBITED_RESOURCE_TYPE_IN_WHERE_CLAUSE = 58 + PROHIBITED_METRIC_IN_SELECT_OR_WHERE_CLAUSE = 49 + PROHIBITED_SEGMENT_IN_SELECT_OR_WHERE_CLAUSE = 51 + PROHIBITED_SEGMENT_WITH_METRIC_IN_SELECT_OR_WHERE_CLAUSE = 53 + PROHIBITED_FIELD_OR_SEGMENT_WITH_METRIC = 65 + LIMIT_VALUE_TOO_LOW = 25 + PROHIBITED_NEWLINE_IN_STRING = 8 + PROHIBITED_VALUE_COMBINATION_IN_LIST = 10 + PROHIBITED_VALUE_COMBINATION_WITH_BETWEEN_OPERATOR = 21 + STRING_NOT_TERMINATED = 6 + TOO_MANY_SEGMENTS = 34 + UNEXPECTED_END_OF_QUERY = 9 + UNEXPECTED_FROM_CLAUSE = 47 + UNRECOGNIZED_FIELD = 32 + UNEXPECTED_INPUT = 11 + REQUESTED_METRICS_FOR_MANAGER = 59 + FILTER_HAS_TOO_MANY_VALUES = 63 + REQUIRED_SEGMENT_FIELD_MISSING = 66 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/quota_error.py b/google/ads/googleads/v24/errors/types/quota_error.py new file mode 100644 index 000000000..182e4208b --- /dev/null +++ b/google/ads/googleads/v24/errors/types/quota_error.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "QuotaErrorEnum", + }, +) + + +class QuotaErrorEnum(proto.Message): + r"""Container for enum describing possible quota errors.""" + + class QuotaError(proto.Enum): + r"""Enum describing possible quota errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + RESOURCE_EXHAUSTED (2): + Too many requests. + ACCESS_PROHIBITED (3): + Access is prohibited. + RESOURCE_TEMPORARILY_EXHAUSTED (4): + Too many requests in a short amount of time. + EXCESSIVE_SHORT_TERM_QUERY_RESOURCE_CONSUMPTION (5): + Too many expensive requests from query + pattern over a short amount of time. + EXCESSIVE_LONG_TERM_QUERY_RESOURCE_CONSUMPTION (6): + Too many expensive requests from query + pattern over an extended duration of time. + PAYMENTS_PROFILE_ACTIVATION_RATE_LIMIT_EXCEEDED (7): + To activate ad serving in a customer account, + it has to be linked with a payment profile (also + known as a Billing Customer Number, or BCN), + which is then billed for the costs incurred by + that customer account. This error will be thrown + if too many customer accounts are activated in a + short period of time for the same payment + profile. Once this rate limit is exceeded, the + customer should wait for a week before trying + again, or contact Google Ads customer support to + reset the rate limits. See + https://support.google.com/google-ads/answer/6372658 + to learn more about this limit. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + RESOURCE_EXHAUSTED = 2 + ACCESS_PROHIBITED = 3 + RESOURCE_TEMPORARILY_EXHAUSTED = 4 + EXCESSIVE_SHORT_TERM_QUERY_RESOURCE_CONSUMPTION = 5 + EXCESSIVE_LONG_TERM_QUERY_RESOURCE_CONSUMPTION = 6 + PAYMENTS_PROFILE_ACTIVATION_RATE_LIMIT_EXCEEDED = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/range_error.py b/google/ads/googleads/v24/errors/types/range_error.py new file mode 100644 index 000000000..da45eac84 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/range_error.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "RangeErrorEnum", + }, +) + + +class RangeErrorEnum(proto.Message): + r"""Container for enum describing possible range errors.""" + + class RangeError(proto.Enum): + r"""Enum describing possible range errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + TOO_LOW (2): + Too low. + TOO_HIGH (3): + Too high. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + TOO_LOW = 2 + TOO_HIGH = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/reach_plan_error.py b/google/ads/googleads/v24/errors/types/reach_plan_error.py new file mode 100644 index 000000000..741e3f91c --- /dev/null +++ b/google/ads/googleads/v24/errors/types/reach_plan_error.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ReachPlanErrorEnum", + }, +) + + +class ReachPlanErrorEnum(proto.Message): + r"""Container for enum describing possible errors returned from + the ReachPlanService. + + """ + + class ReachPlanError(proto.Enum): + r"""Enum describing possible errors from ReachPlanService. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + NOT_FORECASTABLE_MISSING_RATE (2): + Not forecastable due to missing rate card + data. + NOT_FORECASTABLE_NOT_ENOUGH_INVENTORY (3): + Not forecastable due to not enough inventory. + NOT_FORECASTABLE_ACCOUNT_NOT_ENABLED (4): + Not forecastable due to account not being + enabled. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NOT_FORECASTABLE_MISSING_RATE = 2 + NOT_FORECASTABLE_NOT_ENOUGH_INVENTORY = 3 + NOT_FORECASTABLE_ACCOUNT_NOT_ENABLED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/recommendation_error.py b/google/ads/googleads/v24/errors/types/recommendation_error.py new file mode 100644 index 000000000..8bef44861 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/recommendation_error.py @@ -0,0 +1,213 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "RecommendationErrorEnum", + }, +) + + +class RecommendationErrorEnum(proto.Message): + r"""Container for enum describing possible errors from applying a + recommendation. + + """ + + class RecommendationError(proto.Enum): + r"""Enum describing possible errors from applying a + recommendation. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + BUDGET_AMOUNT_TOO_SMALL (2): + The specified budget amount is too low for + example, lower than minimum currency unit or + lower than ad group minimum cost-per-click. + BUDGET_AMOUNT_TOO_LARGE (3): + The specified budget amount is too large. + INVALID_BUDGET_AMOUNT (4): + The specified budget amount is not a valid + amount, for example, not a multiple of minimum + currency unit. + POLICY_ERROR (5): + The specified keyword or ad violates ad + policy. + INVALID_BID_AMOUNT (6): + The specified bid amount is not valid, for + example, too many fractional digits, or negative + amount. + ADGROUP_KEYWORD_LIMIT (7): + The number of keywords in ad group have + reached the maximum allowed. + RECOMMENDATION_ALREADY_APPLIED (8): + The recommendation requested to apply has + already been applied. + RECOMMENDATION_INVALIDATED (9): + The recommendation requested to apply has + been invalidated. + TOO_MANY_OPERATIONS (10): + The number of operations in a single request + exceeds the maximum allowed. + NO_OPERATIONS (11): + There are no operations in the request. + DIFFERENT_TYPES_NOT_SUPPORTED (12): + Operations with multiple recommendation types + are not supported when partial failure mode is + not enabled. + DUPLICATE_RESOURCE_NAME (13): + Request contains multiple operations with the same + resource_name. + RECOMMENDATION_ALREADY_DISMISSED (14): + The recommendation requested to dismiss has + already been dismissed. + INVALID_APPLY_REQUEST (15): + The recommendation apply request was + malformed and invalid. + RECOMMENDATION_TYPE_APPLY_NOT_SUPPORTED (17): + The type of recommendation requested to apply + is not supported. + INVALID_MULTIPLIER (18): + The target multiplier specified is invalid. + ADVERTISING_CHANNEL_TYPE_GENERATE_NOT_SUPPORTED (19): + The passed in advertising_channel_type is not supported. + RECOMMENDATION_TYPE_GENERATE_NOT_SUPPORTED (20): + The passed in recommendation_type is not supported. + RECOMMENDATION_TYPES_CANNOT_BE_EMPTY (21): + One or more recommendation_types need to be passed into the + generate recommendations request. + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_BIDDING_INFO (22): + Bidding info is required for the CAMPAIGN_BUDGET + recommendation type. + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_BIDDING_STRATEGY_TYPE (23): + Bidding strategy type is required for the CAMPAIGN_BUDGET + recommendation type. + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_ASSET_GROUP_INFO (24): + Asset group info is required for the campaign + budget recommendation type. + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_ASSET_GROUP_INFO_WITH_FINAL_URL (25): + Asset group info with final url is required for the + CAMPAIGN_BUDGET recommendation type. + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_COUNTRY_CODES_FOR_SEARCH_CHANNEL (26): + Country codes are required for the CAMPAIGN_BUDGET + recommendation type for SEARCH channel. + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_INVALID_COUNTRY_CODE_FOR_SEARCH_CHANNEL (27): + Country code is invalid for the CAMPAIGN_BUDGET + recommendation type for SEARCH channel. + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_LANGUAGE_CODES_FOR_SEARCH_CHANNEL (28): + Language codes are required for the CAMPAIGN_BUDGET + recommendation type for SEARCH channel. + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_EITHER_POSITIVE_OR_NEGATIVE_LOCATION_IDS_FOR_SEARCH_CHANNEL (29): + Either positive or negative location ids are required for + the CAMPAIGN_BUDGET recommendation type for SEARCH channel. + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_AD_GROUP_INFO_FOR_SEARCH_CHANNEL (30): + Ad group info is required for the CAMPAIGN_BUDGET + recommendation type for SEARCH channel. + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_KEYWORDS_FOR_SEARCH_CHANNEL (31): + Keywords are required for the CAMPAIGN_BUDGET recommendation + type for SEARCH channel. + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_WITH_CHANNEL_TYPE_SEARCH_AND_BIDDING_STRATEGY_TYPE_TARGET_IMPRESSION_SHARE_REQUIRES_LOCATION (32): + Location is required for the CAMPAIGN_BUDGET recommendation + type for bidding strategy type TARGET_IMPRESSION_SHARE. + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_WITH_CHANNEL_TYPE_SEARCH_AND_BIDDING_STRATEGY_TYPE_TARGET_IMPRESSION_SHARE_REQUIRES_TARGET_IMPRESSION_SHARE_MICROS (33): + Target impression share micros are required for the + CAMPAIGN_BUDGET recommendation type for bidding strategy + type TARGET_IMPRESSION_SHARE. + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_TARGET_IMPRESSION_SHARE_MICROS_BETWEEN_1_AND_1000000 (34): + Target impression share micros are required to be between 1 + and 1000000 for the CAMPAIGN_BUDGET recommendation type for + bidding strategy type TARGET_IMPRESSION_SHARE. + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_WITH_CHANNEL_TYPE_SEARCH_AND_BIDDING_STRATEGY_TYPE_TARGET_IMPRESSION_SHARE_REQUIRES_TARGET_IMPRESSION_SHARE_INFO (35): + Target impression share info is required for the + CAMPAIGN_BUDGET recommendation type for bidding strategy + type TARGET_IMPRESSION_SHARE. + MERCHANT_CENTER_ACCOUNT_ID_NOT_SUPPORTED_ADVERTISING_CHANNEL_TYPE (36): + Merchant Center Account ID is only supported for + advertising_channel_type PERFORMANCE_MAX. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BUDGET_AMOUNT_TOO_SMALL = 2 + BUDGET_AMOUNT_TOO_LARGE = 3 + INVALID_BUDGET_AMOUNT = 4 + POLICY_ERROR = 5 + INVALID_BID_AMOUNT = 6 + ADGROUP_KEYWORD_LIMIT = 7 + RECOMMENDATION_ALREADY_APPLIED = 8 + RECOMMENDATION_INVALIDATED = 9 + TOO_MANY_OPERATIONS = 10 + NO_OPERATIONS = 11 + DIFFERENT_TYPES_NOT_SUPPORTED = 12 + DUPLICATE_RESOURCE_NAME = 13 + RECOMMENDATION_ALREADY_DISMISSED = 14 + INVALID_APPLY_REQUEST = 15 + RECOMMENDATION_TYPE_APPLY_NOT_SUPPORTED = 17 + INVALID_MULTIPLIER = 18 + ADVERTISING_CHANNEL_TYPE_GENERATE_NOT_SUPPORTED = 19 + RECOMMENDATION_TYPE_GENERATE_NOT_SUPPORTED = 20 + RECOMMENDATION_TYPES_CANNOT_BE_EMPTY = 21 + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_BIDDING_INFO = 22 + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_BIDDING_STRATEGY_TYPE = 23 + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_ASSET_GROUP_INFO = 24 + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_ASSET_GROUP_INFO_WITH_FINAL_URL = ( + 25 + ) + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_COUNTRY_CODES_FOR_SEARCH_CHANNEL = ( + 26 + ) + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_INVALID_COUNTRY_CODE_FOR_SEARCH_CHANNEL = ( + 27 + ) + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_LANGUAGE_CODES_FOR_SEARCH_CHANNEL = ( + 28 + ) + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_EITHER_POSITIVE_OR_NEGATIVE_LOCATION_IDS_FOR_SEARCH_CHANNEL = ( + 29 + ) + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_AD_GROUP_INFO_FOR_SEARCH_CHANNEL = ( + 30 + ) + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_REQUIRES_KEYWORDS_FOR_SEARCH_CHANNEL = ( + 31 + ) + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_WITH_CHANNEL_TYPE_SEARCH_AND_BIDDING_STRATEGY_TYPE_TARGET_IMPRESSION_SHARE_REQUIRES_LOCATION = ( + 32 + ) + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_WITH_CHANNEL_TYPE_SEARCH_AND_BIDDING_STRATEGY_TYPE_TARGET_IMPRESSION_SHARE_REQUIRES_TARGET_IMPRESSION_SHARE_MICROS = ( + 33 + ) + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_TARGET_IMPRESSION_SHARE_MICROS_BETWEEN_1_AND_1000000 = ( + 34 + ) + CAMPAIGN_BUDGET_RECOMMENDATION_TYPE_WITH_CHANNEL_TYPE_SEARCH_AND_BIDDING_STRATEGY_TYPE_TARGET_IMPRESSION_SHARE_REQUIRES_TARGET_IMPRESSION_SHARE_INFO = ( + 35 + ) + MERCHANT_CENTER_ACCOUNT_ID_NOT_SUPPORTED_ADVERTISING_CHANNEL_TYPE = 36 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/recommendation_subscription_error.py b/google/ads/googleads/v24/errors/types/recommendation_subscription_error.py new file mode 100644 index 000000000..3488e1cd5 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/recommendation_subscription_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "RecommendationSubscriptionErrorEnum", + }, +) + + +class RecommendationSubscriptionErrorEnum(proto.Message): + r"""Container for enum describing possible recommendation + subscription errors. + + """ + + class RecommendationSubscriptionError(proto.Enum): + r"""Enum describing possible recommendation subscription errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/region_code_error.py b/google/ads/googleads/v24/errors/types/region_code_error.py new file mode 100644 index 000000000..7c54d5c17 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/region_code_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "RegionCodeErrorEnum", + }, +) + + +class RegionCodeErrorEnum(proto.Message): + r"""Container for enum describing possible region code errors.""" + + class RegionCodeError(proto.Enum): + r"""Enum describing possible region code errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_REGION_CODE (2): + Invalid region code. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_REGION_CODE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/request_error.py b/google/ads/googleads/v24/errors/types/request_error.py new file mode 100644 index 000000000..15d892720 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/request_error.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "RequestErrorEnum", + }, +) + + +class RequestErrorEnum(proto.Message): + r"""Container for enum describing possible request errors.""" + + class RequestError(proto.Enum): + r"""Enum describing possible request errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + RESOURCE_NAME_MISSING (3): + Resource name is required for this request. + RESOURCE_NAME_MALFORMED (4): + Resource name provided is malformed. + BAD_RESOURCE_ID (17): + Resource name provided is malformed. + INVALID_CUSTOMER_ID (16): + Customer ID is invalid. + OPERATION_REQUIRED (5): + Mutate operation should have either create, + update, or remove specified. + RESOURCE_NOT_FOUND (6): + Requested resource not found. + INVALID_PAGE_TOKEN (7): + Next page token specified in user request is + invalid. + EXPIRED_PAGE_TOKEN (8): + Next page token specified in user request has + expired. + INVALID_PAGE_SIZE (22): + Page size specified in user request is + invalid. + PAGE_SIZE_NOT_SUPPORTED (40): + Setting the page size is not supported, and + will be unavailable in a future version. + REQUIRED_FIELD_MISSING (9): + Required field is missing. + IMMUTABLE_FIELD (11): + The field cannot be modified because it's + immutable. It's also possible that the field can + be modified using 'create' operation but not + 'update'. + TOO_MANY_MUTATE_OPERATIONS (13): + Received too many entries in request. + TOO_MANY_ACTION_OPERATIONS (41): + Received too many action operations in + request. + CANNOT_BE_EXECUTED_BY_MANAGER_ACCOUNT (14): + Request cannot be executed by a manager + account. + CANNOT_MODIFY_FOREIGN_FIELD (15): + Mutate request was attempting to modify a + readonly field. For instance, Budget fields can + be requested for Ad Group, but are read-only for + adGroups:mutate. + INVALID_ENUM_VALUE (18): + Enum value is not permitted. + DEVELOPER_TOKEN_PARAMETER_MISSING (19): + The developer-token parameter is required for + all requests. + LOGIN_CUSTOMER_ID_PARAMETER_MISSING (20): + The login-customer-id parameter is required + for this request. + VALIDATE_ONLY_REQUEST_HAS_PAGE_TOKEN (21): + page_token is set in the validate only request + CANNOT_RETURN_SUMMARY_ROW_FOR_REQUEST_WITHOUT_METRICS (29): + return_summary_row cannot be enabled if request did not + select any metrics field. + CANNOT_RETURN_SUMMARY_ROW_FOR_VALIDATE_ONLY_REQUESTS (30): + return_summary_row should not be enabled for validate only + requests. + INCONSISTENT_RETURN_SUMMARY_ROW_VALUE (31): + return_summary_row parameter value should be the same + between requests with page_token field set and their + original request. + TOTAL_RESULTS_COUNT_NOT_ORIGINALLY_REQUESTED (32): + The total results count cannot be returned if + it was not requested in the original request. + RPC_DEADLINE_TOO_SHORT (33): + Deadline specified by the client was too + short. + UNSUPPORTED_VERSION (38): + This API version has been sunset and is no + longer supported. + CLOUD_PROJECT_NOT_FOUND (39): + The Google Cloud project in the request was + not found. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + RESOURCE_NAME_MISSING = 3 + RESOURCE_NAME_MALFORMED = 4 + BAD_RESOURCE_ID = 17 + INVALID_CUSTOMER_ID = 16 + OPERATION_REQUIRED = 5 + RESOURCE_NOT_FOUND = 6 + INVALID_PAGE_TOKEN = 7 + EXPIRED_PAGE_TOKEN = 8 + INVALID_PAGE_SIZE = 22 + PAGE_SIZE_NOT_SUPPORTED = 40 + REQUIRED_FIELD_MISSING = 9 + IMMUTABLE_FIELD = 11 + TOO_MANY_MUTATE_OPERATIONS = 13 + TOO_MANY_ACTION_OPERATIONS = 41 + CANNOT_BE_EXECUTED_BY_MANAGER_ACCOUNT = 14 + CANNOT_MODIFY_FOREIGN_FIELD = 15 + INVALID_ENUM_VALUE = 18 + DEVELOPER_TOKEN_PARAMETER_MISSING = 19 + LOGIN_CUSTOMER_ID_PARAMETER_MISSING = 20 + VALIDATE_ONLY_REQUEST_HAS_PAGE_TOKEN = 21 + CANNOT_RETURN_SUMMARY_ROW_FOR_REQUEST_WITHOUT_METRICS = 29 + CANNOT_RETURN_SUMMARY_ROW_FOR_VALIDATE_ONLY_REQUESTS = 30 + INCONSISTENT_RETURN_SUMMARY_ROW_VALUE = 31 + TOTAL_RESULTS_COUNT_NOT_ORIGINALLY_REQUESTED = 32 + RPC_DEADLINE_TOO_SHORT = 33 + UNSUPPORTED_VERSION = 38 + CLOUD_PROJECT_NOT_FOUND = 39 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/resource_access_denied_error.py b/google/ads/googleads/v24/errors/types/resource_access_denied_error.py new file mode 100644 index 000000000..c92876dc0 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/resource_access_denied_error.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ResourceAccessDeniedErrorEnum", + }, +) + + +class ResourceAccessDeniedErrorEnum(proto.Message): + r"""Container for enum describing possible resource access denied + errors. + + """ + + class ResourceAccessDeniedError(proto.Enum): + r"""Enum describing possible resource access denied errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + WRITE_ACCESS_DENIED (3): + User did not have write access. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + WRITE_ACCESS_DENIED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/resource_count_limit_exceeded_error.py b/google/ads/googleads/v24/errors/types/resource_count_limit_exceeded_error.py new file mode 100644 index 000000000..a81a8de7f --- /dev/null +++ b/google/ads/googleads/v24/errors/types/resource_count_limit_exceeded_error.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ResourceCountLimitExceededErrorEnum", + }, +) + + +class ResourceCountLimitExceededErrorEnum(proto.Message): + r"""Container for enum describing possible resource count limit + exceeded errors. + + """ + + class ResourceCountLimitExceededError(proto.Enum): + r"""Enum describing possible resource count limit exceeded + errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + ACCOUNT_LIMIT (2): + Indicates that this request would exceed the + number of allowed resources for the Google Ads + account. The exact resource type and limit being + checked can be inferred from accountLimitType. + CAMPAIGN_LIMIT (3): + Indicates that this request would exceed the + number of allowed resources in a Campaign. The + exact resource type and limit being checked can + be inferred from accountLimitType, and the + numeric id of the Campaign involved is given by + enclosingId. + ADGROUP_LIMIT (4): + Indicates that this request would exceed the + number of allowed resources in an ad group. The + exact resource type and limit being checked can + be inferred from accountLimitType, and the + numeric id of the ad group involved is given by + enclosingId. + AD_GROUP_AD_LIMIT (5): + Indicates that this request would exceed the + number of allowed resources in an ad group ad. + The exact resource type and limit being checked + can be inferred from accountLimitType, and the + enclosingId contains the ad group id followed by + the ad id, separated by a single comma (,). + AD_GROUP_CRITERION_LIMIT (6): + Indicates that this request would exceed the + number of allowed resources in an ad group + criterion. The exact resource type and limit + being checked can be inferred from + accountLimitType, and the enclosingId contains + the ad group id followed by the criterion id, + separated by a single comma (,). + SHARED_SET_LIMIT (7): + Indicates that this request would exceed the + number of allowed resources in this shared set. + The exact resource type and limit being checked + can be inferred from accountLimitType, and the + numeric id of the shared set involved is given + by enclosingId. + MATCHING_FUNCTION_LIMIT (8): + Exceeds a limit related to a matching + function. + RESPONSE_ROW_LIMIT_EXCEEDED (9): + The response for this request would exceed + the maximum number of rows that can be returned. + RESOURCE_LIMIT (10): + This request would exceed a limit on the + number of allowed resources. The details of + which type of limit was exceeded will eventually + be returned in ErrorDetails. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ACCOUNT_LIMIT = 2 + CAMPAIGN_LIMIT = 3 + ADGROUP_LIMIT = 4 + AD_GROUP_AD_LIMIT = 5 + AD_GROUP_CRITERION_LIMIT = 6 + SHARED_SET_LIMIT = 7 + MATCHING_FUNCTION_LIMIT = 8 + RESPONSE_ROW_LIMIT_EXCEEDED = 9 + RESOURCE_LIMIT = 10 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/search_term_insight_error.py b/google/ads/googleads/v24/errors/types/search_term_insight_error.py new file mode 100644 index 000000000..682c04c48 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/search_term_insight_error.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "SearchTermInsightErrorEnum", + }, +) + + +class SearchTermInsightErrorEnum(proto.Message): + r"""Container for enum describing possible search term insight + errors. + + """ + + class SearchTermInsightError(proto.Enum): + r"""Enum describing possible search term insight errors. + + Values: + UNSPECIFIED (0): + Name unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + FILTERING_NOT_ALLOWED_WITH_SEGMENTS (2): + Search term insights cannot be filtered by + metrics when segmenting. + LIMIT_NOT_ALLOWED_WITH_SEGMENTS (3): + Search term insights cannot have a LIMIT when + segmenting. + MISSING_FIELD_IN_SELECT_CLAUSE (4): + A selected field requires another field to be + selected with it. + REQUIRES_FILTER_BY_SINGLE_RESOURCE (5): + A selected field/resource requires filtering + by a single resource. + SORTING_NOT_ALLOWED_WITH_SEGMENTS (6): + Search term insights cannot be sorted when + segmenting. + SUMMARY_ROW_NOT_ALLOWED_WITH_SEGMENTS (7): + Search term insights cannot have a summary + row when segmenting. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + FILTERING_NOT_ALLOWED_WITH_SEGMENTS = 2 + LIMIT_NOT_ALLOWED_WITH_SEGMENTS = 3 + MISSING_FIELD_IN_SELECT_CLAUSE = 4 + REQUIRES_FILTER_BY_SINGLE_RESOURCE = 5 + SORTING_NOT_ALLOWED_WITH_SEGMENTS = 6 + SUMMARY_ROW_NOT_ALLOWED_WITH_SEGMENTS = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/setting_error.py b/google/ads/googleads/v24/errors/types/setting_error.py new file mode 100644 index 000000000..7f26cf009 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/setting_error.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "SettingErrorEnum", + }, +) + + +class SettingErrorEnum(proto.Message): + r"""Container for enum describing possible setting errors.""" + + class SettingError(proto.Enum): + r"""Enum describing possible setting errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + SETTING_TYPE_IS_NOT_AVAILABLE (3): + The campaign setting is not available for + this Google Ads account. + SETTING_TYPE_IS_NOT_COMPATIBLE_WITH_CAMPAIGN (4): + The setting is not compatible with the + campaign. + TARGETING_SETTING_CONTAINS_INVALID_CRITERION_TYPE_GROUP (5): + The supplied TargetingSetting contains an + invalid CriterionTypeGroup. See + CriterionTypeGroup documentation for + CriterionTypeGroups allowed in Campaign or + AdGroup TargetingSettings. + TARGETING_SETTING_DEMOGRAPHIC_CRITERION_TYPE_GROUPS_MUST_BE_SET_TO_TARGET_ALL (6): + TargetingSetting must not explicitly set any of the + Demographic CriterionTypeGroups (AGE_RANGE, GENDER, PARENT, + INCOME_RANGE) to false (it's okay to not set them at all, in + which case the system will set them to true automatically). + TARGETING_SETTING_CANNOT_CHANGE_TARGET_ALL_TO_FALSE_FOR_DEMOGRAPHIC_CRITERION_TYPE_GROUP (7): + TargetingSetting cannot change any of the Demographic + CriterionTypeGroups (AGE_RANGE, GENDER, PARENT, + INCOME_RANGE) from true to false. + DYNAMIC_SEARCH_ADS_SETTING_AT_LEAST_ONE_FEED_ID_MUST_BE_PRESENT (8): + At least one feed id should be present. + DYNAMIC_SEARCH_ADS_SETTING_CONTAINS_INVALID_DOMAIN_NAME (9): + The supplied DynamicSearchAdsSetting contains + an invalid domain name. + DYNAMIC_SEARCH_ADS_SETTING_CONTAINS_SUBDOMAIN_NAME (10): + The supplied DynamicSearchAdsSetting contains + a subdomain name. + DYNAMIC_SEARCH_ADS_SETTING_CONTAINS_INVALID_LANGUAGE_CODE (11): + The supplied DynamicSearchAdsSetting contains + an invalid language code. + TARGET_ALL_IS_NOT_ALLOWED_FOR_PLACEMENT_IN_SEARCH_CAMPAIGN (12): + TargetingSettings in search campaigns should + not have CriterionTypeGroup.PLACEMENT set to + targetAll. + SETTING_VALUE_NOT_COMPATIBLE_WITH_CAMPAIGN (20): + The setting value is not compatible with the + campaign type. + BID_ONLY_IS_NOT_ALLOWED_TO_BE_MODIFIED_WITH_CUSTOMER_MATCH_TARGETING (21): + Switching from observation setting to + targeting setting is not allowed for Customer + Match lists. See + https://support.google.com/google-ads/answer/6299717. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + SETTING_TYPE_IS_NOT_AVAILABLE = 3 + SETTING_TYPE_IS_NOT_COMPATIBLE_WITH_CAMPAIGN = 4 + TARGETING_SETTING_CONTAINS_INVALID_CRITERION_TYPE_GROUP = 5 + TARGETING_SETTING_DEMOGRAPHIC_CRITERION_TYPE_GROUPS_MUST_BE_SET_TO_TARGET_ALL = ( + 6 + ) + TARGETING_SETTING_CANNOT_CHANGE_TARGET_ALL_TO_FALSE_FOR_DEMOGRAPHIC_CRITERION_TYPE_GROUP = ( + 7 + ) + DYNAMIC_SEARCH_ADS_SETTING_AT_LEAST_ONE_FEED_ID_MUST_BE_PRESENT = 8 + DYNAMIC_SEARCH_ADS_SETTING_CONTAINS_INVALID_DOMAIN_NAME = 9 + DYNAMIC_SEARCH_ADS_SETTING_CONTAINS_SUBDOMAIN_NAME = 10 + DYNAMIC_SEARCH_ADS_SETTING_CONTAINS_INVALID_LANGUAGE_CODE = 11 + TARGET_ALL_IS_NOT_ALLOWED_FOR_PLACEMENT_IN_SEARCH_CAMPAIGN = 12 + SETTING_VALUE_NOT_COMPATIBLE_WITH_CAMPAIGN = 20 + BID_ONLY_IS_NOT_ALLOWED_TO_BE_MODIFIED_WITH_CUSTOMER_MATCH_TARGETING = ( + 21 + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/shareable_preview_error.py b/google/ads/googleads/v24/errors/types/shareable_preview_error.py new file mode 100644 index 000000000..0140ab5f7 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/shareable_preview_error.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ShareablePreviewErrorEnum", + }, +) + + +class ShareablePreviewErrorEnum(proto.Message): + r"""Container for enum describing possible shareable preview + errors. + + """ + + class ShareablePreviewError(proto.Enum): + r"""Enum describing possible shareable preview errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + UNSUPPORTED_AD_TYPE (4): + Unsupported ad type for the given preview + type. + TOO_MANY_RESOURCES_IN_REQUEST (6): + The combined number of asset groups and ad + group ads exceeds the maximum of 10. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UNSUPPORTED_AD_TYPE = 4 + TOO_MANY_RESOURCES_IN_REQUEST = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/shared_criterion_error.py b/google/ads/googleads/v24/errors/types/shared_criterion_error.py new file mode 100644 index 000000000..3ba4e5f75 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/shared_criterion_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "SharedCriterionErrorEnum", + }, +) + + +class SharedCriterionErrorEnum(proto.Message): + r"""Container for enum describing possible shared criterion + errors. + + """ + + class SharedCriterionError(proto.Enum): + r"""Enum describing possible shared criterion errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CRITERION_TYPE_NOT_ALLOWED_FOR_SHARED_SET_TYPE (2): + The criterion is not appropriate for the + shared set type. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CRITERION_TYPE_NOT_ALLOWED_FOR_SHARED_SET_TYPE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/shared_set_error.py b/google/ads/googleads/v24/errors/types/shared_set_error.py new file mode 100644 index 000000000..b80bfadb1 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/shared_set_error.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "SharedSetErrorEnum", + }, +) + + +class SharedSetErrorEnum(proto.Message): + r"""Container for enum describing possible shared set errors.""" + + class SharedSetError(proto.Enum): + r"""Enum describing possible shared set errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CUSTOMER_CANNOT_CREATE_SHARED_SET_OF_THIS_TYPE (2): + The customer cannot create this type of + shared set. + DUPLICATE_NAME (3): + A shared set with this name already exists. + SHARED_SET_REMOVED (4): + Removed shared sets cannot be mutated. + SHARED_SET_IN_USE (5): + The shared set cannot be removed because it + is in use. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER_CANNOT_CREATE_SHARED_SET_OF_THIS_TYPE = 2 + DUPLICATE_NAME = 3 + SHARED_SET_REMOVED = 4 + SHARED_SET_IN_USE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/shopping_product_error.py b/google/ads/googleads/v24/errors/types/shopping_product_error.py new file mode 100644 index 000000000..33a1f3f22 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/shopping_product_error.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ShoppingProductErrorEnum", + }, +) + + +class ShoppingProductErrorEnum(proto.Message): + r"""Container for enum describing possible errors querying + shopping product. + + """ + + class ShoppingProductError(proto.Enum): + r"""Enum describing possible errors querying shopping product. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + MISSING_CAMPAIGN_FILTER (2): + A filter on the ``campaign`` resource name is missing. + MISSING_AD_GROUP_FILTER (3): + A filter on the ``ad_group`` resource name is missing. + UNSUPPORTED_DATE_SEGMENTATION (4): + Date segmentation is not supported. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MISSING_CAMPAIGN_FILTER = 2 + MISSING_AD_GROUP_FILTER = 3 + UNSUPPORTED_DATE_SEGMENTATION = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/size_limit_error.py b/google/ads/googleads/v24/errors/types/size_limit_error.py new file mode 100644 index 000000000..645d6ae65 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/size_limit_error.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "SizeLimitErrorEnum", + }, +) + + +class SizeLimitErrorEnum(proto.Message): + r"""Container for enum describing possible size limit errors.""" + + class SizeLimitError(proto.Enum): + r"""Enum describing possible size limit errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + REQUEST_SIZE_LIMIT_EXCEEDED (2): + The number of entries in the request exceeds + the system limit, or the contents of the + operations exceed transaction limits due to + their size or complexity. Try reducing the + number of entries per request. + RESPONSE_SIZE_LIMIT_EXCEEDED (3): + The number of entries in the response exceeds + the system limit. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + REQUEST_SIZE_LIMIT_EXCEEDED = 2 + RESPONSE_SIZE_LIMIT_EXCEEDED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/smart_campaign_error.py b/google/ads/googleads/v24/errors/types/smart_campaign_error.py new file mode 100644 index 000000000..7d811de0e --- /dev/null +++ b/google/ads/googleads/v24/errors/types/smart_campaign_error.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "SmartCampaignErrorEnum", + }, +) + + +class SmartCampaignErrorEnum(proto.Message): + r"""Container for enum describing possible Smart campaign errors.""" + + class SmartCampaignError(proto.Enum): + r"""Enum describing possible Smart campaign errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_BUSINESS_LOCATION_ID (2): + The business location id is invalid. + INVALID_CAMPAIGN (3): + The SmartCampaignSetting resource is only + applicable for campaigns with advertising + channel type SMART. + BUSINESS_NAME_OR_BUSINESS_LOCATION_ID_MISSING (4): + The business name or business location id is + required. + REQUIRED_SUGGESTION_FIELD_MISSING (5): + A Smart campaign suggestion request field is + required. + GEO_TARGETS_REQUIRED (6): + A location list or proximity is required. + CANNOT_DETERMINE_SUGGESTION_LOCALE (7): + The locale could not be determined. + FINAL_URL_NOT_CRAWLABLE (8): + The final URL could not be crawled. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_BUSINESS_LOCATION_ID = 2 + INVALID_CAMPAIGN = 3 + BUSINESS_NAME_OR_BUSINESS_LOCATION_ID_MISSING = 4 + REQUIRED_SUGGESTION_FIELD_MISSING = 5 + GEO_TARGETS_REQUIRED = 6 + CANNOT_DETERMINE_SUGGESTION_LOCALE = 7 + FINAL_URL_NOT_CRAWLABLE = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/string_format_error.py b/google/ads/googleads/v24/errors/types/string_format_error.py new file mode 100644 index 000000000..09af68b2a --- /dev/null +++ b/google/ads/googleads/v24/errors/types/string_format_error.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "StringFormatErrorEnum", + }, +) + + +class StringFormatErrorEnum(proto.Message): + r"""Container for enum describing possible string format errors.""" + + class StringFormatError(proto.Enum): + r"""Enum describing possible string format errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + ILLEGAL_CHARS (2): + The input string value contains disallowed + characters. + INVALID_FORMAT (3): + The input string value is invalid for the + associated field. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ILLEGAL_CHARS = 2 + INVALID_FORMAT = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/string_length_error.py b/google/ads/googleads/v24/errors/types/string_length_error.py new file mode 100644 index 000000000..82ba95a61 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/string_length_error.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "StringLengthErrorEnum", + }, +) + + +class StringLengthErrorEnum(proto.Message): + r"""Container for enum describing possible string length errors.""" + + class StringLengthError(proto.Enum): + r"""Enum describing possible string length errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + EMPTY (4): + The specified field should have a least one + non-whitespace character in it. + TOO_SHORT (2): + Too short. + TOO_LONG (3): + Too long. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EMPTY = 4 + TOO_SHORT = 2 + TOO_LONG = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/third_party_app_analytics_link_error.py b/google/ads/googleads/v24/errors/types/third_party_app_analytics_link_error.py new file mode 100644 index 000000000..8681d0bb5 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/third_party_app_analytics_link_error.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "ThirdPartyAppAnalyticsLinkErrorEnum", + }, +) + + +class ThirdPartyAppAnalyticsLinkErrorEnum(proto.Message): + r"""Container for enum describing possible third party app + analytics link errors. + + """ + + class ThirdPartyAppAnalyticsLinkError(proto.Enum): + r"""Enum describing possible third party app analytics link + errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_ANALYTICS_PROVIDER_ID (2): + The provided analytics provider ID is + invalid. + INVALID_MOBILE_APP_ID (3): + The provided mobile app ID is invalid. + MOBILE_APP_IS_NOT_ENABLED (4): + The mobile app corresponding to the provided + app ID is not active/enabled. + CANNOT_REGENERATE_SHAREABLE_LINK_ID_FOR_REMOVED_LINK (5): + Regenerating shareable link ID is only + allowed on active links + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_ANALYTICS_PROVIDER_ID = 2 + INVALID_MOBILE_APP_ID = 3 + MOBILE_APP_IS_NOT_ENABLED = 4 + CANNOT_REGENERATE_SHAREABLE_LINK_ID_FOR_REMOVED_LINK = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/time_zone_error.py b/google/ads/googleads/v24/errors/types/time_zone_error.py new file mode 100644 index 000000000..80430c58f --- /dev/null +++ b/google/ads/googleads/v24/errors/types/time_zone_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "TimeZoneErrorEnum", + }, +) + + +class TimeZoneErrorEnum(proto.Message): + r"""Container for enum describing possible time zone errors.""" + + class TimeZoneError(proto.Enum): + r"""Enum describing possible currency code errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_TIME_ZONE (5): + Time zone is not valid. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_TIME_ZONE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/url_field_error.py b/google/ads/googleads/v24/errors/types/url_field_error.py new file mode 100644 index 000000000..5da440d69 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/url_field_error.py @@ -0,0 +1,254 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "UrlFieldErrorEnum", + }, +) + + +class UrlFieldErrorEnum(proto.Message): + r"""Container for enum describing possible url field errors.""" + + class UrlFieldError(proto.Enum): + r"""Enum describing possible url field errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + INVALID_TRACKING_URL_TEMPLATE (2): + The tracking url template is invalid. + INVALID_TAG_IN_TRACKING_URL_TEMPLATE (3): + The tracking url template contains invalid + tag. + MISSING_TRACKING_URL_TEMPLATE_TAG (4): + The tracking url template must contain at + least one tag (for example, {lpurl}), This + applies only to tracking url template associated + with website ads or product ads. + MISSING_PROTOCOL_IN_TRACKING_URL_TEMPLATE (5): + The tracking url template must start with a + valid protocol (or lpurl tag). + INVALID_PROTOCOL_IN_TRACKING_URL_TEMPLATE (6): + The tracking url template starts with an + invalid protocol. + MALFORMED_TRACKING_URL_TEMPLATE (7): + The tracking url template contains illegal + characters. + MISSING_HOST_IN_TRACKING_URL_TEMPLATE (8): + The tracking url template must contain a host + name (or lpurl tag). + INVALID_TLD_IN_TRACKING_URL_TEMPLATE (9): + The tracking url template has an invalid or + missing top level domain extension. + REDUNDANT_NESTED_TRACKING_URL_TEMPLATE_TAG (10): + The tracking url template contains nested + occurrences of the same conditional tag (for + example, {ifmobile:{ifmobile:x}}). + INVALID_FINAL_URL (11): + The final url is invalid. + INVALID_TAG_IN_FINAL_URL (12): + The final url contains invalid tag. + REDUNDANT_NESTED_FINAL_URL_TAG (13): + The final url contains nested occurrences of + the same conditional tag (for example, + {ifmobile:{ifmobile:x}}). + MISSING_PROTOCOL_IN_FINAL_URL (14): + The final url must start with a valid + protocol. + INVALID_PROTOCOL_IN_FINAL_URL (15): + The final url starts with an invalid + protocol. + MALFORMED_FINAL_URL (16): + The final url contains illegal characters. + MISSING_HOST_IN_FINAL_URL (17): + The final url must contain a host name. + INVALID_TLD_IN_FINAL_URL (18): + The tracking url template has an invalid or + missing top level domain extension. + INVALID_FINAL_MOBILE_URL (19): + The final mobile url is invalid. + INVALID_TAG_IN_FINAL_MOBILE_URL (20): + The final mobile url contains invalid tag. + REDUNDANT_NESTED_FINAL_MOBILE_URL_TAG (21): + The final mobile url contains nested + occurrences of the same conditional tag (for + example, {ifmobile:{ifmobile:x}}). + MISSING_PROTOCOL_IN_FINAL_MOBILE_URL (22): + The final mobile url must start with a valid + protocol. + INVALID_PROTOCOL_IN_FINAL_MOBILE_URL (23): + The final mobile url starts with an invalid + protocol. + MALFORMED_FINAL_MOBILE_URL (24): + The final mobile url contains illegal + characters. + MISSING_HOST_IN_FINAL_MOBILE_URL (25): + The final mobile url must contain a host + name. + INVALID_TLD_IN_FINAL_MOBILE_URL (26): + The tracking url template has an invalid or + missing top level domain extension. + INVALID_FINAL_APP_URL (27): + The final app url is invalid. + INVALID_TAG_IN_FINAL_APP_URL (28): + The final app url contains invalid tag. + REDUNDANT_NESTED_FINAL_APP_URL_TAG (29): + The final app url contains nested occurrences + of the same conditional tag (for example, + {ifmobile:{ifmobile:x}}). + MULTIPLE_APP_URLS_FOR_OSTYPE (30): + More than one app url found for the same OS + type. + INVALID_OSTYPE (31): + The OS type given for an app url is not + valid. + INVALID_PROTOCOL_FOR_APP_URL (32): + The protocol given for an app url is not + valid. (For example, "android-app://") + INVALID_PACKAGE_ID_FOR_APP_URL (33): + The package id (app id) given for an app url + is not valid. + URL_CUSTOM_PARAMETERS_COUNT_EXCEEDS_LIMIT (34): + The number of url custom parameters for an + resource exceeds the maximum limit allowed. + INVALID_CHARACTERS_IN_URL_CUSTOM_PARAMETER_KEY (39): + An invalid character appears in the parameter + key. + INVALID_CHARACTERS_IN_URL_CUSTOM_PARAMETER_VALUE (40): + An invalid character appears in the parameter + value. + INVALID_TAG_IN_URL_CUSTOM_PARAMETER_VALUE (41): + The url custom parameter value fails url tag + validation. + REDUNDANT_NESTED_URL_CUSTOM_PARAMETER_TAG (42): + The custom parameter contains nested + occurrences of the same conditional tag (for + example, {ifmobile:{ifmobile:x}}). + MISSING_PROTOCOL (43): + The protocol (http:// or https://) is + missing. + INVALID_PROTOCOL (52): + Unsupported protocol in URL. Only http and + https are supported. + INVALID_URL (44): + The url is invalid. + DESTINATION_URL_DEPRECATED (45): + Destination Url is deprecated. + INVALID_TAG_IN_URL (46): + The url contains invalid tag. + MISSING_URL_TAG (47): + The url must contain at least one tag (for + example, {lpurl}). + DUPLICATE_URL_ID (48): + Duplicate url id. + INVALID_URL_ID (49): + Invalid url id. + FINAL_URL_SUFFIX_MALFORMED (50): + The final url suffix cannot begin with '?' or + '&' characters and must be a valid query string. + INVALID_TAG_IN_FINAL_URL_SUFFIX (51): + The final url suffix cannot contain {lpurl} + related or {ignore} tags. + INVALID_TOP_LEVEL_DOMAIN (53): + The top level domain is invalid, for example, + not a public top level domain listed in + publicsuffix.org. + MALFORMED_TOP_LEVEL_DOMAIN (54): + Malformed top level domain in URL. + MALFORMED_URL (55): + Malformed URL. + MISSING_HOST (56): + No host found in URL. + NULL_CUSTOM_PARAMETER_VALUE (57): + Custom parameter value cannot be null. + VALUE_TRACK_PARAMETER_NOT_SUPPORTED (58): + Track parameter is not supported. + UNSUPPORTED_APP_STORE (59): + The app store connected to the url is not + supported. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_TRACKING_URL_TEMPLATE = 2 + INVALID_TAG_IN_TRACKING_URL_TEMPLATE = 3 + MISSING_TRACKING_URL_TEMPLATE_TAG = 4 + MISSING_PROTOCOL_IN_TRACKING_URL_TEMPLATE = 5 + INVALID_PROTOCOL_IN_TRACKING_URL_TEMPLATE = 6 + MALFORMED_TRACKING_URL_TEMPLATE = 7 + MISSING_HOST_IN_TRACKING_URL_TEMPLATE = 8 + INVALID_TLD_IN_TRACKING_URL_TEMPLATE = 9 + REDUNDANT_NESTED_TRACKING_URL_TEMPLATE_TAG = 10 + INVALID_FINAL_URL = 11 + INVALID_TAG_IN_FINAL_URL = 12 + REDUNDANT_NESTED_FINAL_URL_TAG = 13 + MISSING_PROTOCOL_IN_FINAL_URL = 14 + INVALID_PROTOCOL_IN_FINAL_URL = 15 + MALFORMED_FINAL_URL = 16 + MISSING_HOST_IN_FINAL_URL = 17 + INVALID_TLD_IN_FINAL_URL = 18 + INVALID_FINAL_MOBILE_URL = 19 + INVALID_TAG_IN_FINAL_MOBILE_URL = 20 + REDUNDANT_NESTED_FINAL_MOBILE_URL_TAG = 21 + MISSING_PROTOCOL_IN_FINAL_MOBILE_URL = 22 + INVALID_PROTOCOL_IN_FINAL_MOBILE_URL = 23 + MALFORMED_FINAL_MOBILE_URL = 24 + MISSING_HOST_IN_FINAL_MOBILE_URL = 25 + INVALID_TLD_IN_FINAL_MOBILE_URL = 26 + INVALID_FINAL_APP_URL = 27 + INVALID_TAG_IN_FINAL_APP_URL = 28 + REDUNDANT_NESTED_FINAL_APP_URL_TAG = 29 + MULTIPLE_APP_URLS_FOR_OSTYPE = 30 + INVALID_OSTYPE = 31 + INVALID_PROTOCOL_FOR_APP_URL = 32 + INVALID_PACKAGE_ID_FOR_APP_URL = 33 + URL_CUSTOM_PARAMETERS_COUNT_EXCEEDS_LIMIT = 34 + INVALID_CHARACTERS_IN_URL_CUSTOM_PARAMETER_KEY = 39 + INVALID_CHARACTERS_IN_URL_CUSTOM_PARAMETER_VALUE = 40 + INVALID_TAG_IN_URL_CUSTOM_PARAMETER_VALUE = 41 + REDUNDANT_NESTED_URL_CUSTOM_PARAMETER_TAG = 42 + MISSING_PROTOCOL = 43 + INVALID_PROTOCOL = 52 + INVALID_URL = 44 + DESTINATION_URL_DEPRECATED = 45 + INVALID_TAG_IN_URL = 46 + MISSING_URL_TAG = 47 + DUPLICATE_URL_ID = 48 + INVALID_URL_ID = 49 + FINAL_URL_SUFFIX_MALFORMED = 50 + INVALID_TAG_IN_FINAL_URL_SUFFIX = 51 + INVALID_TOP_LEVEL_DOMAIN = 53 + MALFORMED_TOP_LEVEL_DOMAIN = 54 + MALFORMED_URL = 55 + MISSING_HOST = 56 + NULL_CUSTOM_PARAMETER_VALUE = 57 + VALUE_TRACK_PARAMETER_NOT_SUPPORTED = 58 + UNSUPPORTED_APP_STORE = 59 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/user_data_error.py b/google/ads/googleads/v24/errors/types/user_data_error.py new file mode 100644 index 000000000..774766aa4 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/user_data_error.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "UserDataErrorEnum", + }, +) + + +class UserDataErrorEnum(proto.Message): + r"""Container for enum describing possible user data errors.""" + + class UserDataError(proto.Enum): + r"""Enum describing possible request errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + OPERATIONS_FOR_CUSTOMER_MATCH_NOT_ALLOWED (2): + Customer is not allowed to perform operations + related to Customer Match. + TOO_MANY_USER_IDENTIFIERS (3): + Maximum number of user identifiers allowed + for each request is 100 and for each operation + is 20. + USER_LIST_NOT_APPLICABLE (4): + Current user list is not applicable for the + given customer. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + OPERATIONS_FOR_CUSTOMER_MATCH_NOT_ALLOWED = 2 + TOO_MANY_USER_IDENTIFIERS = 3 + USER_LIST_NOT_APPLICABLE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/user_list_customer_type_error.py b/google/ads/googleads/v24/errors/types/user_list_customer_type_error.py new file mode 100644 index 000000000..ed52b7636 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/user_list_customer_type_error.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "UserListCustomerTypeErrorEnum", + }, +) + + +class UserListCustomerTypeErrorEnum(proto.Message): + r"""Container for enum describing possible user list customer + type errors. + + """ + + class UserListCustomerTypeError(proto.Enum): + r"""Enum describing possible user list customer type errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + CONFLICTING_CUSTOMER_TYPES (2): + Cannot add the conflicting customer types to + the same user list. Conflicting labels: + + 1. Purchasers - Converted Leads + 2. Purchasers - Qualified Leads + 3. Purchasers - Cart Abandoners + 4. Qualified Leads - Converted Leads + 5. Disengaged customers - Converted Leads + 6. Disengaged customers - Qualified Leads + 7. Disengaged customers - Cart Abandoners + 8. Loyalty Tier X Members - Loyalty Tier Y + Members + NO_ACCESS_TO_USER_LIST (3): + The account does not have access to the user + list. + USERLIST_NOT_ELIGIBLE (4): + The given user list is not eligible for applying customer + types. The user list must belong to one of the following + types: CRM_BASED, RULE_BASED, ADVERTISER_DATA_MODEL_BASED, + GCN. + CONVERSION_TRACKING_NOT_ENABLED_OR_NOT_MCC_MANAGER_ACCOUNT (5): + To edit the user list customer type, + conversion tracking must be enabled in your + account. If cross-tracking is enabled, your + account must be a MCC manager account to modify + user list customer types. More info at + https://support.google.com/google-ads/answer/3030657 + TOO_MANY_USER_LISTS_FOR_THE_CUSTOMER_TYPE (6): + Too many user lists for the customer type. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CONFLICTING_CUSTOMER_TYPES = 2 + NO_ACCESS_TO_USER_LIST = 3 + USERLIST_NOT_ELIGIBLE = 4 + CONVERSION_TRACKING_NOT_ENABLED_OR_NOT_MCC_MANAGER_ACCOUNT = 5 + TOO_MANY_USER_LISTS_FOR_THE_CUSTOMER_TYPE = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/user_list_error.py b/google/ads/googleads/v24/errors/types/user_list_error.py new file mode 100644 index 000000000..dbe6228e8 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/user_list_error.py @@ -0,0 +1,213 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "UserListErrorEnum", + }, +) + + +class UserListErrorEnum(proto.Message): + r"""Container for enum describing possible user list errors.""" + + class UserListError(proto.Enum): + r"""Enum describing possible user list errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + EXTERNAL_REMARKETING_USER_LIST_MUTATE_NOT_SUPPORTED (2): + Creating and updating external remarketing + user lists is not supported. + CONCRETE_TYPE_REQUIRED (3): + Concrete type of user list is required. + CONVERSION_TYPE_ID_REQUIRED (4): + Creating/updating user list conversion types + requires specifying the conversion type Id. + DUPLICATE_CONVERSION_TYPES (5): + Remarketing user list cannot have duplicate + conversion types. + INVALID_CONVERSION_TYPE (6): + Conversion type is invalid/unknown. + INVALID_DESCRIPTION (7): + User list description is empty or invalid. + INVALID_NAME (8): + User list name is empty or invalid. + INVALID_TYPE (9): + Type of the UserList does not match. + CAN_NOT_ADD_LOGICAL_LIST_AS_LOGICAL_LIST_OPERAND (10): + Embedded logical user lists are not allowed. + INVALID_USER_LIST_LOGICAL_RULE_OPERAND (11): + User list rule operand is invalid. + NAME_ALREADY_USED (12): + Name is already being used for another user + list for the account. + NEW_CONVERSION_TYPE_NAME_REQUIRED (13): + Name is required when creating a new + conversion type. + CONVERSION_TYPE_NAME_ALREADY_USED (14): + The given conversion type name has been used. + OWNERSHIP_REQUIRED_FOR_SET (15): + Only an owner account may edit a user list. + USER_LIST_MUTATE_NOT_SUPPORTED (16): + Creating user list without setting type in oneof user_list + field, or creating/updating read-only user list types is not + allowed. + INVALID_RULE (17): + Rule is invalid. + INVALID_DATE_RANGE (27): + The specified date range is empty. + CAN_NOT_MUTATE_SENSITIVE_USERLIST (28): + A UserList which is privacy sensitive or + legal rejected cannot be mutated by external + users. + MAX_NUM_RULEBASED_USERLISTS (29): + Maximum number of rulebased user lists a + customer can have. + CANNOT_MODIFY_BILLABLE_RECORD_COUNT (30): + BasicUserList's billable record field cannot + be modified once it is set. + APP_ID_NOT_SET (31): + crm_based_user_list.app_id field must be set when + upload_key_type is MOBILE_ADVERTISING_ID. + USERLIST_NAME_IS_RESERVED_FOR_SYSTEM_LIST (32): + Name of the user list is reserved for system + generated lists and cannot be used. + ADVERTISER_NOT_ON_ALLOWLIST_FOR_USING_UPLOADED_DATA (37): + Advertiser needs to be on the allow-list to + use remarketing lists created from advertiser + uploaded data (for example, Customer Match + lists). + RULE_TYPE_IS_NOT_SUPPORTED (34): + The provided rule_type is not supported for the user list. + CAN_NOT_ADD_A_SIMILAR_USERLIST_AS_LOGICAL_LIST_OPERAND (35): + Similar user list cannot be used as a logical + user list operand. + CAN_NOT_MIX_CRM_BASED_IN_LOGICAL_LIST_WITH_OTHER_LISTS (36): + Logical user list should not have a mix of + CRM based user list and other types of lists in + its rules. + APP_ID_NOT_ALLOWED (39): + crm_based_user_list.app_id field can only be set when + upload_key_type is MOBILE_ADVERTISING_ID. + CANNOT_MUTATE_SYSTEM_LIST (40): + Google system generated user lists cannot be + mutated. + MOBILE_APP_IS_SENSITIVE (41): + The mobile app associated with the + remarketing list is sensitive. + SEED_LIST_DOES_NOT_EXIST (42): + One or more given seed lists do not exist. + INVALID_SEED_LIST_ACCESS_REASON (43): + One or more given seed lists are not + accessible to the current user. + INVALID_SEED_LIST_TYPE (44): + One or more given seed lists have an + unsupported type. + INVALID_COUNTRY_CODES (45): + One or more invalid country codes are added + to Lookalike UserList. + DUPLICATE_LOOKALIKE (46): + Cannot create a Lookalike UserList which is a + duplicate of an existing Lookalike. + PARTNER_AUDIENCE_SOURCE_NOT_SUPPORTED_FOR_USER_LIST_TYPE (47): + The partner audience source is not supported + for the user list type. + COMMERCE_PARTNER_NOT_ALLOWED (48): + The commerce partner is only supported for + COMMERCE_AUDIENCE. + PARTNER_AUDIENCE_INFO_NOT_SUPPORTED_FOR_USER_LIST_TYPE (49): + The partner audience info is not supported + for the user list type. + PARTNER_MANAGER_ACCOUNT_DISALLOWED (50): + Manager account is not allowed to create this + UserList. + PARTNER_NOT_ALLOWLISTED_FOR_THIRD_PARTY_PARTNER_DATA (51): + This UserList can only be created by + allowlisted partners. + ADVERTISER_TOS_NOT_ACCEPTED (52): + The advertiser must accept the Terms of + Service to create this UserList. + ADVERTISER_PARTNER_LINK_MISSING (53): + The advertiser must have an active link to + the partner to create this UserList. + ADVERTISER_NOT_ALLOWLISTED_FOR_THIRD_PARTY_PARTNER_DATA (54): + This UserList can only be created for + allowlisted advertisers. + ACCOUNT_SETTING_TYPE_NOT_ALLOWED (55): + This UserList is not allowed for this account + type. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + EXTERNAL_REMARKETING_USER_LIST_MUTATE_NOT_SUPPORTED = 2 + CONCRETE_TYPE_REQUIRED = 3 + CONVERSION_TYPE_ID_REQUIRED = 4 + DUPLICATE_CONVERSION_TYPES = 5 + INVALID_CONVERSION_TYPE = 6 + INVALID_DESCRIPTION = 7 + INVALID_NAME = 8 + INVALID_TYPE = 9 + CAN_NOT_ADD_LOGICAL_LIST_AS_LOGICAL_LIST_OPERAND = 10 + INVALID_USER_LIST_LOGICAL_RULE_OPERAND = 11 + NAME_ALREADY_USED = 12 + NEW_CONVERSION_TYPE_NAME_REQUIRED = 13 + CONVERSION_TYPE_NAME_ALREADY_USED = 14 + OWNERSHIP_REQUIRED_FOR_SET = 15 + USER_LIST_MUTATE_NOT_SUPPORTED = 16 + INVALID_RULE = 17 + INVALID_DATE_RANGE = 27 + CAN_NOT_MUTATE_SENSITIVE_USERLIST = 28 + MAX_NUM_RULEBASED_USERLISTS = 29 + CANNOT_MODIFY_BILLABLE_RECORD_COUNT = 30 + APP_ID_NOT_SET = 31 + USERLIST_NAME_IS_RESERVED_FOR_SYSTEM_LIST = 32 + ADVERTISER_NOT_ON_ALLOWLIST_FOR_USING_UPLOADED_DATA = 37 + RULE_TYPE_IS_NOT_SUPPORTED = 34 + CAN_NOT_ADD_A_SIMILAR_USERLIST_AS_LOGICAL_LIST_OPERAND = 35 + CAN_NOT_MIX_CRM_BASED_IN_LOGICAL_LIST_WITH_OTHER_LISTS = 36 + APP_ID_NOT_ALLOWED = 39 + CANNOT_MUTATE_SYSTEM_LIST = 40 + MOBILE_APP_IS_SENSITIVE = 41 + SEED_LIST_DOES_NOT_EXIST = 42 + INVALID_SEED_LIST_ACCESS_REASON = 43 + INVALID_SEED_LIST_TYPE = 44 + INVALID_COUNTRY_CODES = 45 + DUPLICATE_LOOKALIKE = 46 + PARTNER_AUDIENCE_SOURCE_NOT_SUPPORTED_FOR_USER_LIST_TYPE = 47 + COMMERCE_PARTNER_NOT_ALLOWED = 48 + PARTNER_AUDIENCE_INFO_NOT_SUPPORTED_FOR_USER_LIST_TYPE = 49 + PARTNER_MANAGER_ACCOUNT_DISALLOWED = 50 + PARTNER_NOT_ALLOWLISTED_FOR_THIRD_PARTY_PARTNER_DATA = 51 + ADVERTISER_TOS_NOT_ACCEPTED = 52 + ADVERTISER_PARTNER_LINK_MISSING = 53 + ADVERTISER_NOT_ALLOWLISTED_FOR_THIRD_PARTY_PARTNER_DATA = 54 + ACCOUNT_SETTING_TYPE_NOT_ALLOWED = 55 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/video_campaign_error.py b/google/ads/googleads/v24/errors/types/video_campaign_error.py new file mode 100644 index 000000000..ea83cf89f --- /dev/null +++ b/google/ads/googleads/v24/errors/types/video_campaign_error.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "VideoCampaignErrorEnum", + }, +) + + +class VideoCampaignErrorEnum(proto.Message): + r"""Container for enum describing possible video campaign errors.""" + + class VideoCampaignError(proto.Enum): + r"""Enum describing possible video campaign errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + MUTATE_REQUIRES_RESERVATION (2): + Cannot modify the video campaign without + reservation. See + https://support.google.com/google-ads/answer/9547606. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + MUTATE_REQUIRES_RESERVATION = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/video_reservation_error.py b/google/ads/googleads/v24/errors/types/video_reservation_error.py new file mode 100644 index 000000000..7f1e09b8b --- /dev/null +++ b/google/ads/googleads/v24/errors/types/video_reservation_error.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "VideoReservationErrorEnum", + }, +) + + +class VideoReservationErrorEnum(proto.Message): + r"""Container for enum describing possible video reservation + errors. + + """ + + class VideoReservationError(proto.Enum): + r"""Enum describing possible video reservation errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + NEW_QUOTE_REQUIRED (2): + The quote has expired. + CAMPAIGN_END_TIME_TOO_DISTANT (3): + The campaign's end date has to be less than + 120 days from now. + BUDGET_TOO_SMALL (4): + The campaign budget is too small. To get a + quote, increase the budget. + CAMPAIGN_DURATION_TOO_SHORT (5): + The campaign must run for more than 24 hours. + CAMPAIGN_NOT_ENABLED (6): + The campaign must be enabled before booking. + NOT_ENOUGH_AVAILABLE_INVENTORY (7): + There aren't enough impressions available for + the campaigns settings and targeting. Broaden + the targeting or lower the budget of the + campaign to get a quote. + TARGETING_TOO_NARROW (8): + There aren't enough impressions available for + the campaign settings and targeting. + UNSUPPORTED_AD_GROUP_TYPE (9): + The type of the enabled ad group of this + campaign isn't supported. + UNSUPPORTED_BID_MODIFIER (10): + Bid modifiers other than 0% or -100% aren't + supported. + CANNOT_CHANGE_PRICING_MODEL (11): + The type of placement was changed. YouTube + Select lineups can only be paired with other + YouTube Select lineups. + INCOMPATIBLE_TARGETING (12): + More than one lineup was selected. Only one + lineup per campaign can be targeted. + UNSUPPORTED_FEATURE (13): + Some options in this campaign aren't + supported. + MISSING_ELECTION_CERTIFICATE (14): + The customer must be verified by Google to + run election ads in the targeted country. + CAMPAIGN_ENDED (15): + This campaign has ended. Select a campaign + that hasn't reached its end date. + UNSUPPORTED_BUDGET_PERIOD (16): + Daily budget isn't available for fixed CPM + campaigns. To use fixed CPM, enter a campaign + total budget. + EXACTLY_ONE_ENABLED_ADGROUP_REQUIRED (17): + The campaign must have exactly one enabled ad + group for reservation. + FREQUENCY_CAP_TOO_NARROW (18): + The frequency cap is lower than the minimum + allowed for an enabled campaign. Update the + frequency cap to either a daily cap or a weekly + cap with at least 3 impressions per week. + TARGETED_PACK_NEEDS_DEAL (19): + The targeted country requires either a deal + or a market rate. + DEAL_CURRENCY_MISMATCH (20): + The account is set to a currency that doesn't + match the currency of the rate card for the + targeted video lineups. + CANNOT_HOLD_CONTRACT (21): + Quote holds are unavailable for this campaign + configuration. + CUSTOMER_NOT_ENABLED (22): + The account is suspended. Contact support for + more info. + CUSTOMER_NOT_ALLOWED (23): + The customer doesn't have permission to + request a quote. Contact the account owner for + more info. + INVALID_ACCOUNT_TYPE (24): + This account type can't request quotes. Use a + different account or contact support for more + info. + ACCOUNT_IS_MANAGER (25): + Google Account Managers can't request quotes + for reservation campaigns. + SEASONAL_LINEUP_BOOKING_WINDOW_NOT_OPEN (26): + The booking window for this lineup is not + open yet. + SEASONAL_LINEUP_END_DATE_OFF_SEASON (27): + The campaign end date is later than the + allowable end date for this lineup. To continue + booking, choose an earlier end date. + SEASONAL_LINEUP_GEO_TARGETING_TOO_NARROW (28): + There aren't enough impressions available for + the campaign settings and targeting. Broaden the + location targeting to get a quote. + NO_MARKET_RATE_CARD_OR_BASE_RATE (29): + The market rate for the targeted product + isn't available. + STALE_QUOTE (30): + The quote is stale, get a new quote and try + again. + LINEUP_NOT_ALLOWED (31): + Some of the targeted video lineups aren't + available for reservation campaigns. + UNSUPPORTED_BIDDING_STRATEGY (32): + This bidding strategy is not supported for + reservation. + UNSUPPORTED_POSITIVE_GEO_TARGET_TYPE (33): + The campaign settings contain a positive geo + target type which is not allowed, for example + Audio ads support PRESENCE only. + VALIDATE_ONLY_REQUIRED (34): + Only validate_only requests are supported. + TOO_MANY_CAMPAIGNS (35): + Too many campaigns in request. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NEW_QUOTE_REQUIRED = 2 + CAMPAIGN_END_TIME_TOO_DISTANT = 3 + BUDGET_TOO_SMALL = 4 + CAMPAIGN_DURATION_TOO_SHORT = 5 + CAMPAIGN_NOT_ENABLED = 6 + NOT_ENOUGH_AVAILABLE_INVENTORY = 7 + TARGETING_TOO_NARROW = 8 + UNSUPPORTED_AD_GROUP_TYPE = 9 + UNSUPPORTED_BID_MODIFIER = 10 + CANNOT_CHANGE_PRICING_MODEL = 11 + INCOMPATIBLE_TARGETING = 12 + UNSUPPORTED_FEATURE = 13 + MISSING_ELECTION_CERTIFICATE = 14 + CAMPAIGN_ENDED = 15 + UNSUPPORTED_BUDGET_PERIOD = 16 + EXACTLY_ONE_ENABLED_ADGROUP_REQUIRED = 17 + FREQUENCY_CAP_TOO_NARROW = 18 + TARGETED_PACK_NEEDS_DEAL = 19 + DEAL_CURRENCY_MISMATCH = 20 + CANNOT_HOLD_CONTRACT = 21 + CUSTOMER_NOT_ENABLED = 22 + CUSTOMER_NOT_ALLOWED = 23 + INVALID_ACCOUNT_TYPE = 24 + ACCOUNT_IS_MANAGER = 25 + SEASONAL_LINEUP_BOOKING_WINDOW_NOT_OPEN = 26 + SEASONAL_LINEUP_END_DATE_OFF_SEASON = 27 + SEASONAL_LINEUP_GEO_TARGETING_TOO_NARROW = 28 + NO_MARKET_RATE_CARD_OR_BASE_RATE = 29 + STALE_QUOTE = 30 + LINEUP_NOT_ALLOWED = 31 + UNSUPPORTED_BIDDING_STRATEGY = 32 + UNSUPPORTED_POSITIVE_GEO_TARGET_TYPE = 33 + VALIDATE_ONLY_REQUIRED = 34 + TOO_MANY_CAMPAIGNS = 35 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/errors/types/youtube_video_registration_error.py b/google/ads/googleads/v24/errors/types/youtube_video_registration_error.py new file mode 100644 index 000000000..e85a1b388 --- /dev/null +++ b/google/ads/googleads/v24/errors/types/youtube_video_registration_error.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.errors", + marshal="google.ads.googleads.v24", + manifest={ + "YoutubeVideoRegistrationErrorEnum", + }, +) + + +class YoutubeVideoRegistrationErrorEnum(proto.Message): + r"""Container for enum describing YouTube video registration + errors. + + """ + + class YoutubeVideoRegistrationError(proto.Enum): + r"""Enum describing YouTube video registration errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + VIDEO_NOT_FOUND (2): + Video to be registered wasn't found. + VIDEO_NOT_ACCESSIBLE (3): + Video to be registered is not accessible (for + example, private). + VIDEO_NOT_ELIGIBLE (4): + Video to be registered is not eligible (for + example, mature content). + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + VIDEO_NOT_FOUND = 2 + VIDEO_NOT_ACCESSIBLE = 3 + VIDEO_NOT_ELIGIBLE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/gapic_metadata.json b/google/ads/googleads/v24/gapic_metadata.json new file mode 100644 index 000000000..649544355 --- /dev/null +++ b/google/ads/googleads/v24/gapic_metadata.json @@ -0,0 +1,3263 @@ + { + "comment": "This file maps proto services/RPCs to the corresponding library clients/methods", + "language": "python", + "libraryPackage": "google.ads.googleads.v24", + "protoPackage": "google.ads.googleads.v24", + "schema": "1.0", + "services": { + "AccountBudgetProposalService": { + "clients": { + "grpc": { + "libraryClient": "AccountBudgetProposalServiceClient", + "rpcs": { + "MutateAccountBudgetProposal": { + "methods": [ + "mutate_account_budget_proposal" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AccountBudgetProposalServiceAsyncClient", + "rpcs": { + "MutateAccountBudgetProposal": { + "methods": [ + "mutate_account_budget_proposal" + ] + } + } + } + } + }, + "AccountLinkService": { + "clients": { + "grpc": { + "libraryClient": "AccountLinkServiceClient", + "rpcs": { + "CreateAccountLink": { + "methods": [ + "create_account_link" + ] + }, + "MutateAccountLink": { + "methods": [ + "mutate_account_link" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AccountLinkServiceAsyncClient", + "rpcs": { + "CreateAccountLink": { + "methods": [ + "create_account_link" + ] + }, + "MutateAccountLink": { + "methods": [ + "mutate_account_link" + ] + } + } + } + } + }, + "AdGroupAdLabelService": { + "clients": { + "grpc": { + "libraryClient": "AdGroupAdLabelServiceClient", + "rpcs": { + "MutateAdGroupAdLabels": { + "methods": [ + "mutate_ad_group_ad_labels" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AdGroupAdLabelServiceAsyncClient", + "rpcs": { + "MutateAdGroupAdLabels": { + "methods": [ + "mutate_ad_group_ad_labels" + ] + } + } + } + } + }, + "AdGroupAdService": { + "clients": { + "grpc": { + "libraryClient": "AdGroupAdServiceClient", + "rpcs": { + "MutateAdGroupAds": { + "methods": [ + "mutate_ad_group_ads" + ] + }, + "RemoveAutomaticallyCreatedAssets": { + "methods": [ + "remove_automatically_created_assets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AdGroupAdServiceAsyncClient", + "rpcs": { + "MutateAdGroupAds": { + "methods": [ + "mutate_ad_group_ads" + ] + }, + "RemoveAutomaticallyCreatedAssets": { + "methods": [ + "remove_automatically_created_assets" + ] + } + } + } + } + }, + "AdGroupAssetService": { + "clients": { + "grpc": { + "libraryClient": "AdGroupAssetServiceClient", + "rpcs": { + "MutateAdGroupAssets": { + "methods": [ + "mutate_ad_group_assets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AdGroupAssetServiceAsyncClient", + "rpcs": { + "MutateAdGroupAssets": { + "methods": [ + "mutate_ad_group_assets" + ] + } + } + } + } + }, + "AdGroupAssetSetService": { + "clients": { + "grpc": { + "libraryClient": "AdGroupAssetSetServiceClient", + "rpcs": { + "MutateAdGroupAssetSets": { + "methods": [ + "mutate_ad_group_asset_sets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AdGroupAssetSetServiceAsyncClient", + "rpcs": { + "MutateAdGroupAssetSets": { + "methods": [ + "mutate_ad_group_asset_sets" + ] + } + } + } + } + }, + "AdGroupBidModifierService": { + "clients": { + "grpc": { + "libraryClient": "AdGroupBidModifierServiceClient", + "rpcs": { + "MutateAdGroupBidModifiers": { + "methods": [ + "mutate_ad_group_bid_modifiers" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AdGroupBidModifierServiceAsyncClient", + "rpcs": { + "MutateAdGroupBidModifiers": { + "methods": [ + "mutate_ad_group_bid_modifiers" + ] + } + } + } + } + }, + "AdGroupCriterionCustomizerService": { + "clients": { + "grpc": { + "libraryClient": "AdGroupCriterionCustomizerServiceClient", + "rpcs": { + "MutateAdGroupCriterionCustomizers": { + "methods": [ + "mutate_ad_group_criterion_customizers" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AdGroupCriterionCustomizerServiceAsyncClient", + "rpcs": { + "MutateAdGroupCriterionCustomizers": { + "methods": [ + "mutate_ad_group_criterion_customizers" + ] + } + } + } + } + }, + "AdGroupCriterionLabelService": { + "clients": { + "grpc": { + "libraryClient": "AdGroupCriterionLabelServiceClient", + "rpcs": { + "MutateAdGroupCriterionLabels": { + "methods": [ + "mutate_ad_group_criterion_labels" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AdGroupCriterionLabelServiceAsyncClient", + "rpcs": { + "MutateAdGroupCriterionLabels": { + "methods": [ + "mutate_ad_group_criterion_labels" + ] + } + } + } + } + }, + "AdGroupCriterionService": { + "clients": { + "grpc": { + "libraryClient": "AdGroupCriterionServiceClient", + "rpcs": { + "MutateAdGroupCriteria": { + "methods": [ + "mutate_ad_group_criteria" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AdGroupCriterionServiceAsyncClient", + "rpcs": { + "MutateAdGroupCriteria": { + "methods": [ + "mutate_ad_group_criteria" + ] + } + } + } + } + }, + "AdGroupCustomizerService": { + "clients": { + "grpc": { + "libraryClient": "AdGroupCustomizerServiceClient", + "rpcs": { + "MutateAdGroupCustomizers": { + "methods": [ + "mutate_ad_group_customizers" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AdGroupCustomizerServiceAsyncClient", + "rpcs": { + "MutateAdGroupCustomizers": { + "methods": [ + "mutate_ad_group_customizers" + ] + } + } + } + } + }, + "AdGroupLabelService": { + "clients": { + "grpc": { + "libraryClient": "AdGroupLabelServiceClient", + "rpcs": { + "MutateAdGroupLabels": { + "methods": [ + "mutate_ad_group_labels" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AdGroupLabelServiceAsyncClient", + "rpcs": { + "MutateAdGroupLabels": { + "methods": [ + "mutate_ad_group_labels" + ] + } + } + } + } + }, + "AdGroupService": { + "clients": { + "grpc": { + "libraryClient": "AdGroupServiceClient", + "rpcs": { + "MutateAdGroups": { + "methods": [ + "mutate_ad_groups" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AdGroupServiceAsyncClient", + "rpcs": { + "MutateAdGroups": { + "methods": [ + "mutate_ad_groups" + ] + } + } + } + } + }, + "AdParameterService": { + "clients": { + "grpc": { + "libraryClient": "AdParameterServiceClient", + "rpcs": { + "MutateAdParameters": { + "methods": [ + "mutate_ad_parameters" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AdParameterServiceAsyncClient", + "rpcs": { + "MutateAdParameters": { + "methods": [ + "mutate_ad_parameters" + ] + } + } + } + } + }, + "AdService": { + "clients": { + "grpc": { + "libraryClient": "AdServiceClient", + "rpcs": { + "MutateAds": { + "methods": [ + "mutate_ads" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AdServiceAsyncClient", + "rpcs": { + "MutateAds": { + "methods": [ + "mutate_ads" + ] + } + } + } + } + }, + "AssetGenerationService": { + "clients": { + "grpc": { + "libraryClient": "AssetGenerationServiceClient", + "rpcs": { + "GenerateImages": { + "methods": [ + "generate_images" + ] + }, + "GenerateText": { + "methods": [ + "generate_text" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AssetGenerationServiceAsyncClient", + "rpcs": { + "GenerateImages": { + "methods": [ + "generate_images" + ] + }, + "GenerateText": { + "methods": [ + "generate_text" + ] + } + } + } + } + }, + "AssetGroupAssetService": { + "clients": { + "grpc": { + "libraryClient": "AssetGroupAssetServiceClient", + "rpcs": { + "MutateAssetGroupAssets": { + "methods": [ + "mutate_asset_group_assets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AssetGroupAssetServiceAsyncClient", + "rpcs": { + "MutateAssetGroupAssets": { + "methods": [ + "mutate_asset_group_assets" + ] + } + } + } + } + }, + "AssetGroupListingGroupFilterService": { + "clients": { + "grpc": { + "libraryClient": "AssetGroupListingGroupFilterServiceClient", + "rpcs": { + "MutateAssetGroupListingGroupFilters": { + "methods": [ + "mutate_asset_group_listing_group_filters" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AssetGroupListingGroupFilterServiceAsyncClient", + "rpcs": { + "MutateAssetGroupListingGroupFilters": { + "methods": [ + "mutate_asset_group_listing_group_filters" + ] + } + } + } + } + }, + "AssetGroupService": { + "clients": { + "grpc": { + "libraryClient": "AssetGroupServiceClient", + "rpcs": { + "MutateAssetGroups": { + "methods": [ + "mutate_asset_groups" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AssetGroupServiceAsyncClient", + "rpcs": { + "MutateAssetGroups": { + "methods": [ + "mutate_asset_groups" + ] + } + } + } + } + }, + "AssetGroupSignalService": { + "clients": { + "grpc": { + "libraryClient": "AssetGroupSignalServiceClient", + "rpcs": { + "MutateAssetGroupSignals": { + "methods": [ + "mutate_asset_group_signals" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AssetGroupSignalServiceAsyncClient", + "rpcs": { + "MutateAssetGroupSignals": { + "methods": [ + "mutate_asset_group_signals" + ] + } + } + } + } + }, + "AssetService": { + "clients": { + "grpc": { + "libraryClient": "AssetServiceClient", + "rpcs": { + "MutateAssets": { + "methods": [ + "mutate_assets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AssetServiceAsyncClient", + "rpcs": { + "MutateAssets": { + "methods": [ + "mutate_assets" + ] + } + } + } + } + }, + "AssetSetAssetService": { + "clients": { + "grpc": { + "libraryClient": "AssetSetAssetServiceClient", + "rpcs": { + "MutateAssetSetAssets": { + "methods": [ + "mutate_asset_set_assets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AssetSetAssetServiceAsyncClient", + "rpcs": { + "MutateAssetSetAssets": { + "methods": [ + "mutate_asset_set_assets" + ] + } + } + } + } + }, + "AssetSetService": { + "clients": { + "grpc": { + "libraryClient": "AssetSetServiceClient", + "rpcs": { + "MutateAssetSets": { + "methods": [ + "mutate_asset_sets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AssetSetServiceAsyncClient", + "rpcs": { + "MutateAssetSets": { + "methods": [ + "mutate_asset_sets" + ] + } + } + } + } + }, + "AudienceInsightsService": { + "clients": { + "grpc": { + "libraryClient": "AudienceInsightsServiceClient", + "rpcs": { + "GenerateAudienceCompositionInsights": { + "methods": [ + "generate_audience_composition_insights" + ] + }, + "GenerateAudienceDefinition": { + "methods": [ + "generate_audience_definition" + ] + }, + "GenerateAudienceOverlapInsights": { + "methods": [ + "generate_audience_overlap_insights" + ] + }, + "GenerateInsightsFinderReport": { + "methods": [ + "generate_insights_finder_report" + ] + }, + "GenerateSuggestedTargetingInsights": { + "methods": [ + "generate_suggested_targeting_insights" + ] + }, + "GenerateTargetingSuggestionMetrics": { + "methods": [ + "generate_targeting_suggestion_metrics" + ] + }, + "ListAudienceInsightsAttributes": { + "methods": [ + "list_audience_insights_attributes" + ] + }, + "ListInsightsEligibleDates": { + "methods": [ + "list_insights_eligible_dates" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AudienceInsightsServiceAsyncClient", + "rpcs": { + "GenerateAudienceCompositionInsights": { + "methods": [ + "generate_audience_composition_insights" + ] + }, + "GenerateAudienceDefinition": { + "methods": [ + "generate_audience_definition" + ] + }, + "GenerateAudienceOverlapInsights": { + "methods": [ + "generate_audience_overlap_insights" + ] + }, + "GenerateInsightsFinderReport": { + "methods": [ + "generate_insights_finder_report" + ] + }, + "GenerateSuggestedTargetingInsights": { + "methods": [ + "generate_suggested_targeting_insights" + ] + }, + "GenerateTargetingSuggestionMetrics": { + "methods": [ + "generate_targeting_suggestion_metrics" + ] + }, + "ListAudienceInsightsAttributes": { + "methods": [ + "list_audience_insights_attributes" + ] + }, + "ListInsightsEligibleDates": { + "methods": [ + "list_insights_eligible_dates" + ] + } + } + } + } + }, + "AudienceService": { + "clients": { + "grpc": { + "libraryClient": "AudienceServiceClient", + "rpcs": { + "MutateAudiences": { + "methods": [ + "mutate_audiences" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AudienceServiceAsyncClient", + "rpcs": { + "MutateAudiences": { + "methods": [ + "mutate_audiences" + ] + } + } + } + } + }, + "AutomaticallyCreatedAssetRemovalService": { + "clients": { + "grpc": { + "libraryClient": "AutomaticallyCreatedAssetRemovalServiceClient", + "rpcs": { + "RemoveCampaignAutomaticallyCreatedAsset": { + "methods": [ + "remove_campaign_automatically_created_asset" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AutomaticallyCreatedAssetRemovalServiceAsyncClient", + "rpcs": { + "RemoveCampaignAutomaticallyCreatedAsset": { + "methods": [ + "remove_campaign_automatically_created_asset" + ] + } + } + } + } + }, + "BatchJobService": { + "clients": { + "grpc": { + "libraryClient": "BatchJobServiceClient", + "rpcs": { + "AddBatchJobOperations": { + "methods": [ + "add_batch_job_operations" + ] + }, + "ListBatchJobResults": { + "methods": [ + "list_batch_job_results" + ] + }, + "MutateBatchJob": { + "methods": [ + "mutate_batch_job" + ] + }, + "RunBatchJob": { + "methods": [ + "run_batch_job" + ] + } + } + }, + "grpc-async": { + "libraryClient": "BatchJobServiceAsyncClient", + "rpcs": { + "AddBatchJobOperations": { + "methods": [ + "add_batch_job_operations" + ] + }, + "ListBatchJobResults": { + "methods": [ + "list_batch_job_results" + ] + }, + "MutateBatchJob": { + "methods": [ + "mutate_batch_job" + ] + }, + "RunBatchJob": { + "methods": [ + "run_batch_job" + ] + } + } + } + } + }, + "BenchmarksService": { + "clients": { + "grpc": { + "libraryClient": "BenchmarksServiceClient", + "rpcs": { + "GenerateBenchmarksMetrics": { + "methods": [ + "generate_benchmarks_metrics" + ] + }, + "ListBenchmarksAvailableDates": { + "methods": [ + "list_benchmarks_available_dates" + ] + }, + "ListBenchmarksLocations": { + "methods": [ + "list_benchmarks_locations" + ] + }, + "ListBenchmarksProducts": { + "methods": [ + "list_benchmarks_products" + ] + }, + "ListBenchmarksSources": { + "methods": [ + "list_benchmarks_sources" + ] + } + } + }, + "grpc-async": { + "libraryClient": "BenchmarksServiceAsyncClient", + "rpcs": { + "GenerateBenchmarksMetrics": { + "methods": [ + "generate_benchmarks_metrics" + ] + }, + "ListBenchmarksAvailableDates": { + "methods": [ + "list_benchmarks_available_dates" + ] + }, + "ListBenchmarksLocations": { + "methods": [ + "list_benchmarks_locations" + ] + }, + "ListBenchmarksProducts": { + "methods": [ + "list_benchmarks_products" + ] + }, + "ListBenchmarksSources": { + "methods": [ + "list_benchmarks_sources" + ] + } + } + } + } + }, + "BiddingDataExclusionService": { + "clients": { + "grpc": { + "libraryClient": "BiddingDataExclusionServiceClient", + "rpcs": { + "MutateBiddingDataExclusions": { + "methods": [ + "mutate_bidding_data_exclusions" + ] + } + } + }, + "grpc-async": { + "libraryClient": "BiddingDataExclusionServiceAsyncClient", + "rpcs": { + "MutateBiddingDataExclusions": { + "methods": [ + "mutate_bidding_data_exclusions" + ] + } + } + } + } + }, + "BiddingSeasonalityAdjustmentService": { + "clients": { + "grpc": { + "libraryClient": "BiddingSeasonalityAdjustmentServiceClient", + "rpcs": { + "MutateBiddingSeasonalityAdjustments": { + "methods": [ + "mutate_bidding_seasonality_adjustments" + ] + } + } + }, + "grpc-async": { + "libraryClient": "BiddingSeasonalityAdjustmentServiceAsyncClient", + "rpcs": { + "MutateBiddingSeasonalityAdjustments": { + "methods": [ + "mutate_bidding_seasonality_adjustments" + ] + } + } + } + } + }, + "BiddingStrategyService": { + "clients": { + "grpc": { + "libraryClient": "BiddingStrategyServiceClient", + "rpcs": { + "MutateBiddingStrategies": { + "methods": [ + "mutate_bidding_strategies" + ] + } + } + }, + "grpc-async": { + "libraryClient": "BiddingStrategyServiceAsyncClient", + "rpcs": { + "MutateBiddingStrategies": { + "methods": [ + "mutate_bidding_strategies" + ] + } + } + } + } + }, + "BillingSetupService": { + "clients": { + "grpc": { + "libraryClient": "BillingSetupServiceClient", + "rpcs": { + "MutateBillingSetup": { + "methods": [ + "mutate_billing_setup" + ] + } + } + }, + "grpc-async": { + "libraryClient": "BillingSetupServiceAsyncClient", + "rpcs": { + "MutateBillingSetup": { + "methods": [ + "mutate_billing_setup" + ] + } + } + } + } + }, + "BrandSuggestionService": { + "clients": { + "grpc": { + "libraryClient": "BrandSuggestionServiceClient", + "rpcs": { + "SuggestBrands": { + "methods": [ + "suggest_brands" + ] + } + } + }, + "grpc-async": { + "libraryClient": "BrandSuggestionServiceAsyncClient", + "rpcs": { + "SuggestBrands": { + "methods": [ + "suggest_brands" + ] + } + } + } + } + }, + "CampaignAssetService": { + "clients": { + "grpc": { + "libraryClient": "CampaignAssetServiceClient", + "rpcs": { + "MutateCampaignAssets": { + "methods": [ + "mutate_campaign_assets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CampaignAssetServiceAsyncClient", + "rpcs": { + "MutateCampaignAssets": { + "methods": [ + "mutate_campaign_assets" + ] + } + } + } + } + }, + "CampaignAssetSetService": { + "clients": { + "grpc": { + "libraryClient": "CampaignAssetSetServiceClient", + "rpcs": { + "MutateCampaignAssetSets": { + "methods": [ + "mutate_campaign_asset_sets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CampaignAssetSetServiceAsyncClient", + "rpcs": { + "MutateCampaignAssetSets": { + "methods": [ + "mutate_campaign_asset_sets" + ] + } + } + } + } + }, + "CampaignBidModifierService": { + "clients": { + "grpc": { + "libraryClient": "CampaignBidModifierServiceClient", + "rpcs": { + "MutateCampaignBidModifiers": { + "methods": [ + "mutate_campaign_bid_modifiers" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CampaignBidModifierServiceAsyncClient", + "rpcs": { + "MutateCampaignBidModifiers": { + "methods": [ + "mutate_campaign_bid_modifiers" + ] + } + } + } + } + }, + "CampaignBudgetService": { + "clients": { + "grpc": { + "libraryClient": "CampaignBudgetServiceClient", + "rpcs": { + "MutateCampaignBudgets": { + "methods": [ + "mutate_campaign_budgets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CampaignBudgetServiceAsyncClient", + "rpcs": { + "MutateCampaignBudgets": { + "methods": [ + "mutate_campaign_budgets" + ] + } + } + } + } + }, + "CampaignConversionGoalService": { + "clients": { + "grpc": { + "libraryClient": "CampaignConversionGoalServiceClient", + "rpcs": { + "MutateCampaignConversionGoals": { + "methods": [ + "mutate_campaign_conversion_goals" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CampaignConversionGoalServiceAsyncClient", + "rpcs": { + "MutateCampaignConversionGoals": { + "methods": [ + "mutate_campaign_conversion_goals" + ] + } + } + } + } + }, + "CampaignCriterionService": { + "clients": { + "grpc": { + "libraryClient": "CampaignCriterionServiceClient", + "rpcs": { + "MutateCampaignCriteria": { + "methods": [ + "mutate_campaign_criteria" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CampaignCriterionServiceAsyncClient", + "rpcs": { + "MutateCampaignCriteria": { + "methods": [ + "mutate_campaign_criteria" + ] + } + } + } + } + }, + "CampaignCustomizerService": { + "clients": { + "grpc": { + "libraryClient": "CampaignCustomizerServiceClient", + "rpcs": { + "MutateCampaignCustomizers": { + "methods": [ + "mutate_campaign_customizers" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CampaignCustomizerServiceAsyncClient", + "rpcs": { + "MutateCampaignCustomizers": { + "methods": [ + "mutate_campaign_customizers" + ] + } + } + } + } + }, + "CampaignDraftService": { + "clients": { + "grpc": { + "libraryClient": "CampaignDraftServiceClient", + "rpcs": { + "ListCampaignDraftAsyncErrors": { + "methods": [ + "list_campaign_draft_async_errors" + ] + }, + "MutateCampaignDrafts": { + "methods": [ + "mutate_campaign_drafts" + ] + }, + "PromoteCampaignDraft": { + "methods": [ + "promote_campaign_draft" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CampaignDraftServiceAsyncClient", + "rpcs": { + "ListCampaignDraftAsyncErrors": { + "methods": [ + "list_campaign_draft_async_errors" + ] + }, + "MutateCampaignDrafts": { + "methods": [ + "mutate_campaign_drafts" + ] + }, + "PromoteCampaignDraft": { + "methods": [ + "promote_campaign_draft" + ] + } + } + } + } + }, + "CampaignGoalConfigService": { + "clients": { + "grpc": { + "libraryClient": "CampaignGoalConfigServiceClient", + "rpcs": { + "MutateCampaignGoalConfigs": { + "methods": [ + "mutate_campaign_goal_configs" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CampaignGoalConfigServiceAsyncClient", + "rpcs": { + "MutateCampaignGoalConfigs": { + "methods": [ + "mutate_campaign_goal_configs" + ] + } + } + } + } + }, + "CampaignGroupService": { + "clients": { + "grpc": { + "libraryClient": "CampaignGroupServiceClient", + "rpcs": { + "MutateCampaignGroups": { + "methods": [ + "mutate_campaign_groups" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CampaignGroupServiceAsyncClient", + "rpcs": { + "MutateCampaignGroups": { + "methods": [ + "mutate_campaign_groups" + ] + } + } + } + } + }, + "CampaignLabelService": { + "clients": { + "grpc": { + "libraryClient": "CampaignLabelServiceClient", + "rpcs": { + "MutateCampaignLabels": { + "methods": [ + "mutate_campaign_labels" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CampaignLabelServiceAsyncClient", + "rpcs": { + "MutateCampaignLabels": { + "methods": [ + "mutate_campaign_labels" + ] + } + } + } + } + }, + "CampaignLifecycleGoalService": { + "clients": { + "grpc": { + "libraryClient": "CampaignLifecycleGoalServiceClient", + "rpcs": { + "ConfigureCampaignLifecycleGoals": { + "methods": [ + "configure_campaign_lifecycle_goals" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CampaignLifecycleGoalServiceAsyncClient", + "rpcs": { + "ConfigureCampaignLifecycleGoals": { + "methods": [ + "configure_campaign_lifecycle_goals" + ] + } + } + } + } + }, + "CampaignService": { + "clients": { + "grpc": { + "libraryClient": "CampaignServiceClient", + "rpcs": { + "EnablePMaxBrandGuidelines": { + "methods": [ + "enable_p_max_brand_guidelines" + ] + }, + "MutateCampaigns": { + "methods": [ + "mutate_campaigns" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CampaignServiceAsyncClient", + "rpcs": { + "EnablePMaxBrandGuidelines": { + "methods": [ + "enable_p_max_brand_guidelines" + ] + }, + "MutateCampaigns": { + "methods": [ + "mutate_campaigns" + ] + } + } + } + } + }, + "CampaignSharedSetService": { + "clients": { + "grpc": { + "libraryClient": "CampaignSharedSetServiceClient", + "rpcs": { + "MutateCampaignSharedSets": { + "methods": [ + "mutate_campaign_shared_sets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CampaignSharedSetServiceAsyncClient", + "rpcs": { + "MutateCampaignSharedSets": { + "methods": [ + "mutate_campaign_shared_sets" + ] + } + } + } + } + }, + "ContentCreatorInsightsService": { + "clients": { + "grpc": { + "libraryClient": "ContentCreatorInsightsServiceClient", + "rpcs": { + "GenerateCreatorInsights": { + "methods": [ + "generate_creator_insights" + ] + }, + "GenerateTrendingInsights": { + "methods": [ + "generate_trending_insights" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ContentCreatorInsightsServiceAsyncClient", + "rpcs": { + "GenerateCreatorInsights": { + "methods": [ + "generate_creator_insights" + ] + }, + "GenerateTrendingInsights": { + "methods": [ + "generate_trending_insights" + ] + } + } + } + } + }, + "ConversionActionService": { + "clients": { + "grpc": { + "libraryClient": "ConversionActionServiceClient", + "rpcs": { + "MutateConversionActions": { + "methods": [ + "mutate_conversion_actions" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ConversionActionServiceAsyncClient", + "rpcs": { + "MutateConversionActions": { + "methods": [ + "mutate_conversion_actions" + ] + } + } + } + } + }, + "ConversionAdjustmentUploadService": { + "clients": { + "grpc": { + "libraryClient": "ConversionAdjustmentUploadServiceClient", + "rpcs": { + "UploadConversionAdjustments": { + "methods": [ + "upload_conversion_adjustments" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ConversionAdjustmentUploadServiceAsyncClient", + "rpcs": { + "UploadConversionAdjustments": { + "methods": [ + "upload_conversion_adjustments" + ] + } + } + } + } + }, + "ConversionCustomVariableService": { + "clients": { + "grpc": { + "libraryClient": "ConversionCustomVariableServiceClient", + "rpcs": { + "MutateConversionCustomVariables": { + "methods": [ + "mutate_conversion_custom_variables" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ConversionCustomVariableServiceAsyncClient", + "rpcs": { + "MutateConversionCustomVariables": { + "methods": [ + "mutate_conversion_custom_variables" + ] + } + } + } + } + }, + "ConversionGoalCampaignConfigService": { + "clients": { + "grpc": { + "libraryClient": "ConversionGoalCampaignConfigServiceClient", + "rpcs": { + "MutateConversionGoalCampaignConfigs": { + "methods": [ + "mutate_conversion_goal_campaign_configs" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ConversionGoalCampaignConfigServiceAsyncClient", + "rpcs": { + "MutateConversionGoalCampaignConfigs": { + "methods": [ + "mutate_conversion_goal_campaign_configs" + ] + } + } + } + } + }, + "ConversionUploadService": { + "clients": { + "grpc": { + "libraryClient": "ConversionUploadServiceClient", + "rpcs": { + "UploadCallConversions": { + "methods": [ + "upload_call_conversions" + ] + }, + "UploadClickConversions": { + "methods": [ + "upload_click_conversions" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ConversionUploadServiceAsyncClient", + "rpcs": { + "UploadCallConversions": { + "methods": [ + "upload_call_conversions" + ] + }, + "UploadClickConversions": { + "methods": [ + "upload_click_conversions" + ] + } + } + } + } + }, + "ConversionValueRuleService": { + "clients": { + "grpc": { + "libraryClient": "ConversionValueRuleServiceClient", + "rpcs": { + "MutateConversionValueRules": { + "methods": [ + "mutate_conversion_value_rules" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ConversionValueRuleServiceAsyncClient", + "rpcs": { + "MutateConversionValueRules": { + "methods": [ + "mutate_conversion_value_rules" + ] + } + } + } + } + }, + "ConversionValueRuleSetService": { + "clients": { + "grpc": { + "libraryClient": "ConversionValueRuleSetServiceClient", + "rpcs": { + "MutateConversionValueRuleSets": { + "methods": [ + "mutate_conversion_value_rule_sets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ConversionValueRuleSetServiceAsyncClient", + "rpcs": { + "MutateConversionValueRuleSets": { + "methods": [ + "mutate_conversion_value_rule_sets" + ] + } + } + } + } + }, + "CustomAudienceService": { + "clients": { + "grpc": { + "libraryClient": "CustomAudienceServiceClient", + "rpcs": { + "MutateCustomAudiences": { + "methods": [ + "mutate_custom_audiences" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomAudienceServiceAsyncClient", + "rpcs": { + "MutateCustomAudiences": { + "methods": [ + "mutate_custom_audiences" + ] + } + } + } + } + }, + "CustomConversionGoalService": { + "clients": { + "grpc": { + "libraryClient": "CustomConversionGoalServiceClient", + "rpcs": { + "MutateCustomConversionGoals": { + "methods": [ + "mutate_custom_conversion_goals" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomConversionGoalServiceAsyncClient", + "rpcs": { + "MutateCustomConversionGoals": { + "methods": [ + "mutate_custom_conversion_goals" + ] + } + } + } + } + }, + "CustomInterestService": { + "clients": { + "grpc": { + "libraryClient": "CustomInterestServiceClient", + "rpcs": { + "MutateCustomInterests": { + "methods": [ + "mutate_custom_interests" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomInterestServiceAsyncClient", + "rpcs": { + "MutateCustomInterests": { + "methods": [ + "mutate_custom_interests" + ] + } + } + } + } + }, + "CustomerAssetService": { + "clients": { + "grpc": { + "libraryClient": "CustomerAssetServiceClient", + "rpcs": { + "MutateCustomerAssets": { + "methods": [ + "mutate_customer_assets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomerAssetServiceAsyncClient", + "rpcs": { + "MutateCustomerAssets": { + "methods": [ + "mutate_customer_assets" + ] + } + } + } + } + }, + "CustomerAssetSetService": { + "clients": { + "grpc": { + "libraryClient": "CustomerAssetSetServiceClient", + "rpcs": { + "MutateCustomerAssetSets": { + "methods": [ + "mutate_customer_asset_sets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomerAssetSetServiceAsyncClient", + "rpcs": { + "MutateCustomerAssetSets": { + "methods": [ + "mutate_customer_asset_sets" + ] + } + } + } + } + }, + "CustomerClientLinkService": { + "clients": { + "grpc": { + "libraryClient": "CustomerClientLinkServiceClient", + "rpcs": { + "MutateCustomerClientLink": { + "methods": [ + "mutate_customer_client_link" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomerClientLinkServiceAsyncClient", + "rpcs": { + "MutateCustomerClientLink": { + "methods": [ + "mutate_customer_client_link" + ] + } + } + } + } + }, + "CustomerConversionGoalService": { + "clients": { + "grpc": { + "libraryClient": "CustomerConversionGoalServiceClient", + "rpcs": { + "MutateCustomerConversionGoals": { + "methods": [ + "mutate_customer_conversion_goals" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomerConversionGoalServiceAsyncClient", + "rpcs": { + "MutateCustomerConversionGoals": { + "methods": [ + "mutate_customer_conversion_goals" + ] + } + } + } + } + }, + "CustomerCustomizerService": { + "clients": { + "grpc": { + "libraryClient": "CustomerCustomizerServiceClient", + "rpcs": { + "MutateCustomerCustomizers": { + "methods": [ + "mutate_customer_customizers" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomerCustomizerServiceAsyncClient", + "rpcs": { + "MutateCustomerCustomizers": { + "methods": [ + "mutate_customer_customizers" + ] + } + } + } + } + }, + "CustomerLabelService": { + "clients": { + "grpc": { + "libraryClient": "CustomerLabelServiceClient", + "rpcs": { + "MutateCustomerLabels": { + "methods": [ + "mutate_customer_labels" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomerLabelServiceAsyncClient", + "rpcs": { + "MutateCustomerLabels": { + "methods": [ + "mutate_customer_labels" + ] + } + } + } + } + }, + "CustomerLifecycleGoalService": { + "clients": { + "grpc": { + "libraryClient": "CustomerLifecycleGoalServiceClient", + "rpcs": { + "ConfigureCustomerLifecycleGoals": { + "methods": [ + "configure_customer_lifecycle_goals" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomerLifecycleGoalServiceAsyncClient", + "rpcs": { + "ConfigureCustomerLifecycleGoals": { + "methods": [ + "configure_customer_lifecycle_goals" + ] + } + } + } + } + }, + "CustomerManagerLinkService": { + "clients": { + "grpc": { + "libraryClient": "CustomerManagerLinkServiceClient", + "rpcs": { + "MoveManagerLink": { + "methods": [ + "move_manager_link" + ] + }, + "MutateCustomerManagerLink": { + "methods": [ + "mutate_customer_manager_link" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomerManagerLinkServiceAsyncClient", + "rpcs": { + "MoveManagerLink": { + "methods": [ + "move_manager_link" + ] + }, + "MutateCustomerManagerLink": { + "methods": [ + "mutate_customer_manager_link" + ] + } + } + } + } + }, + "CustomerNegativeCriterionService": { + "clients": { + "grpc": { + "libraryClient": "CustomerNegativeCriterionServiceClient", + "rpcs": { + "MutateCustomerNegativeCriteria": { + "methods": [ + "mutate_customer_negative_criteria" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomerNegativeCriterionServiceAsyncClient", + "rpcs": { + "MutateCustomerNegativeCriteria": { + "methods": [ + "mutate_customer_negative_criteria" + ] + } + } + } + } + }, + "CustomerService": { + "clients": { + "grpc": { + "libraryClient": "CustomerServiceClient", + "rpcs": { + "CreateCustomerClient": { + "methods": [ + "create_customer_client" + ] + }, + "ListAccessibleCustomers": { + "methods": [ + "list_accessible_customers" + ] + }, + "MutateCustomer": { + "methods": [ + "mutate_customer" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomerServiceAsyncClient", + "rpcs": { + "CreateCustomerClient": { + "methods": [ + "create_customer_client" + ] + }, + "ListAccessibleCustomers": { + "methods": [ + "list_accessible_customers" + ] + }, + "MutateCustomer": { + "methods": [ + "mutate_customer" + ] + } + } + } + } + }, + "CustomerSkAdNetworkConversionValueSchemaService": { + "clients": { + "grpc": { + "libraryClient": "CustomerSkAdNetworkConversionValueSchemaServiceClient", + "rpcs": { + "MutateCustomerSkAdNetworkConversionValueSchema": { + "methods": [ + "mutate_customer_sk_ad_network_conversion_value_schema" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomerSkAdNetworkConversionValueSchemaServiceAsyncClient", + "rpcs": { + "MutateCustomerSkAdNetworkConversionValueSchema": { + "methods": [ + "mutate_customer_sk_ad_network_conversion_value_schema" + ] + } + } + } + } + }, + "CustomerUserAccessInvitationService": { + "clients": { + "grpc": { + "libraryClient": "CustomerUserAccessInvitationServiceClient", + "rpcs": { + "MutateCustomerUserAccessInvitation": { + "methods": [ + "mutate_customer_user_access_invitation" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomerUserAccessInvitationServiceAsyncClient", + "rpcs": { + "MutateCustomerUserAccessInvitation": { + "methods": [ + "mutate_customer_user_access_invitation" + ] + } + } + } + } + }, + "CustomerUserAccessService": { + "clients": { + "grpc": { + "libraryClient": "CustomerUserAccessServiceClient", + "rpcs": { + "MutateCustomerUserAccess": { + "methods": [ + "mutate_customer_user_access" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomerUserAccessServiceAsyncClient", + "rpcs": { + "MutateCustomerUserAccess": { + "methods": [ + "mutate_customer_user_access" + ] + } + } + } + } + }, + "CustomizerAttributeService": { + "clients": { + "grpc": { + "libraryClient": "CustomizerAttributeServiceClient", + "rpcs": { + "MutateCustomizerAttributes": { + "methods": [ + "mutate_customizer_attributes" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CustomizerAttributeServiceAsyncClient", + "rpcs": { + "MutateCustomizerAttributes": { + "methods": [ + "mutate_customizer_attributes" + ] + } + } + } + } + }, + "DataLinkService": { + "clients": { + "grpc": { + "libraryClient": "DataLinkServiceClient", + "rpcs": { + "CreateDataLink": { + "methods": [ + "create_data_link" + ] + }, + "RemoveDataLink": { + "methods": [ + "remove_data_link" + ] + }, + "UpdateDataLink": { + "methods": [ + "update_data_link" + ] + } + } + }, + "grpc-async": { + "libraryClient": "DataLinkServiceAsyncClient", + "rpcs": { + "CreateDataLink": { + "methods": [ + "create_data_link" + ] + }, + "RemoveDataLink": { + "methods": [ + "remove_data_link" + ] + }, + "UpdateDataLink": { + "methods": [ + "update_data_link" + ] + } + } + } + } + }, + "ExperimentArmService": { + "clients": { + "grpc": { + "libraryClient": "ExperimentArmServiceClient", + "rpcs": { + "MutateExperimentArms": { + "methods": [ + "mutate_experiment_arms" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ExperimentArmServiceAsyncClient", + "rpcs": { + "MutateExperimentArms": { + "methods": [ + "mutate_experiment_arms" + ] + } + } + } + } + }, + "ExperimentService": { + "clients": { + "grpc": { + "libraryClient": "ExperimentServiceClient", + "rpcs": { + "EndExperiment": { + "methods": [ + "end_experiment" + ] + }, + "GraduateExperiment": { + "methods": [ + "graduate_experiment" + ] + }, + "ListExperimentAsyncErrors": { + "methods": [ + "list_experiment_async_errors" + ] + }, + "MutateExperiments": { + "methods": [ + "mutate_experiments" + ] + }, + "PromoteExperiment": { + "methods": [ + "promote_experiment" + ] + }, + "ScheduleExperiment": { + "methods": [ + "schedule_experiment" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ExperimentServiceAsyncClient", + "rpcs": { + "EndExperiment": { + "methods": [ + "end_experiment" + ] + }, + "GraduateExperiment": { + "methods": [ + "graduate_experiment" + ] + }, + "ListExperimentAsyncErrors": { + "methods": [ + "list_experiment_async_errors" + ] + }, + "MutateExperiments": { + "methods": [ + "mutate_experiments" + ] + }, + "PromoteExperiment": { + "methods": [ + "promote_experiment" + ] + }, + "ScheduleExperiment": { + "methods": [ + "schedule_experiment" + ] + } + } + } + } + }, + "GeoTargetConstantService": { + "clients": { + "grpc": { + "libraryClient": "GeoTargetConstantServiceClient", + "rpcs": { + "SuggestGeoTargetConstants": { + "methods": [ + "suggest_geo_target_constants" + ] + } + } + }, + "grpc-async": { + "libraryClient": "GeoTargetConstantServiceAsyncClient", + "rpcs": { + "SuggestGeoTargetConstants": { + "methods": [ + "suggest_geo_target_constants" + ] + } + } + } + } + }, + "GoalService": { + "clients": { + "grpc": { + "libraryClient": "GoalServiceClient", + "rpcs": { + "MutateGoals": { + "methods": [ + "mutate_goals" + ] + } + } + }, + "grpc-async": { + "libraryClient": "GoalServiceAsyncClient", + "rpcs": { + "MutateGoals": { + "methods": [ + "mutate_goals" + ] + } + } + } + } + }, + "GoogleAdsFieldService": { + "clients": { + "grpc": { + "libraryClient": "GoogleAdsFieldServiceClient", + "rpcs": { + "GetGoogleAdsField": { + "methods": [ + "get_google_ads_field" + ] + }, + "SearchGoogleAdsFields": { + "methods": [ + "search_google_ads_fields" + ] + } + } + }, + "grpc-async": { + "libraryClient": "GoogleAdsFieldServiceAsyncClient", + "rpcs": { + "GetGoogleAdsField": { + "methods": [ + "get_google_ads_field" + ] + }, + "SearchGoogleAdsFields": { + "methods": [ + "search_google_ads_fields" + ] + } + } + } + } + }, + "GoogleAdsService": { + "clients": { + "grpc": { + "libraryClient": "GoogleAdsServiceClient", + "rpcs": { + "Mutate": { + "methods": [ + "mutate" + ] + }, + "Search": { + "methods": [ + "search" + ] + }, + "SearchStream": { + "methods": [ + "search_stream" + ] + } + } + }, + "grpc-async": { + "libraryClient": "GoogleAdsServiceAsyncClient", + "rpcs": { + "Mutate": { + "methods": [ + "mutate" + ] + }, + "Search": { + "methods": [ + "search" + ] + }, + "SearchStream": { + "methods": [ + "search_stream" + ] + } + } + } + } + }, + "IdentityVerificationService": { + "clients": { + "grpc": { + "libraryClient": "IdentityVerificationServiceClient", + "rpcs": { + "GetIdentityVerification": { + "methods": [ + "get_identity_verification" + ] + }, + "StartIdentityVerification": { + "methods": [ + "start_identity_verification" + ] + } + } + }, + "grpc-async": { + "libraryClient": "IdentityVerificationServiceAsyncClient", + "rpcs": { + "GetIdentityVerification": { + "methods": [ + "get_identity_verification" + ] + }, + "StartIdentityVerification": { + "methods": [ + "start_identity_verification" + ] + } + } + } + } + }, + "IncentiveService": { + "clients": { + "grpc": { + "libraryClient": "IncentiveServiceClient", + "rpcs": { + "ApplyIncentive": { + "methods": [ + "apply_incentive" + ] + }, + "FetchIncentive": { + "methods": [ + "fetch_incentive" + ] + } + } + }, + "grpc-async": { + "libraryClient": "IncentiveServiceAsyncClient", + "rpcs": { + "ApplyIncentive": { + "methods": [ + "apply_incentive" + ] + }, + "FetchIncentive": { + "methods": [ + "fetch_incentive" + ] + } + } + } + } + }, + "InvoiceService": { + "clients": { + "grpc": { + "libraryClient": "InvoiceServiceClient", + "rpcs": { + "ListInvoices": { + "methods": [ + "list_invoices" + ] + } + } + }, + "grpc-async": { + "libraryClient": "InvoiceServiceAsyncClient", + "rpcs": { + "ListInvoices": { + "methods": [ + "list_invoices" + ] + } + } + } + } + }, + "KeywordPlanAdGroupKeywordService": { + "clients": { + "grpc": { + "libraryClient": "KeywordPlanAdGroupKeywordServiceClient", + "rpcs": { + "MutateKeywordPlanAdGroupKeywords": { + "methods": [ + "mutate_keyword_plan_ad_group_keywords" + ] + } + } + }, + "grpc-async": { + "libraryClient": "KeywordPlanAdGroupKeywordServiceAsyncClient", + "rpcs": { + "MutateKeywordPlanAdGroupKeywords": { + "methods": [ + "mutate_keyword_plan_ad_group_keywords" + ] + } + } + } + } + }, + "KeywordPlanAdGroupService": { + "clients": { + "grpc": { + "libraryClient": "KeywordPlanAdGroupServiceClient", + "rpcs": { + "MutateKeywordPlanAdGroups": { + "methods": [ + "mutate_keyword_plan_ad_groups" + ] + } + } + }, + "grpc-async": { + "libraryClient": "KeywordPlanAdGroupServiceAsyncClient", + "rpcs": { + "MutateKeywordPlanAdGroups": { + "methods": [ + "mutate_keyword_plan_ad_groups" + ] + } + } + } + } + }, + "KeywordPlanCampaignKeywordService": { + "clients": { + "grpc": { + "libraryClient": "KeywordPlanCampaignKeywordServiceClient", + "rpcs": { + "MutateKeywordPlanCampaignKeywords": { + "methods": [ + "mutate_keyword_plan_campaign_keywords" + ] + } + } + }, + "grpc-async": { + "libraryClient": "KeywordPlanCampaignKeywordServiceAsyncClient", + "rpcs": { + "MutateKeywordPlanCampaignKeywords": { + "methods": [ + "mutate_keyword_plan_campaign_keywords" + ] + } + } + } + } + }, + "KeywordPlanCampaignService": { + "clients": { + "grpc": { + "libraryClient": "KeywordPlanCampaignServiceClient", + "rpcs": { + "MutateKeywordPlanCampaigns": { + "methods": [ + "mutate_keyword_plan_campaigns" + ] + } + } + }, + "grpc-async": { + "libraryClient": "KeywordPlanCampaignServiceAsyncClient", + "rpcs": { + "MutateKeywordPlanCampaigns": { + "methods": [ + "mutate_keyword_plan_campaigns" + ] + } + } + } + } + }, + "KeywordPlanIdeaService": { + "clients": { + "grpc": { + "libraryClient": "KeywordPlanIdeaServiceClient", + "rpcs": { + "GenerateAdGroupThemes": { + "methods": [ + "generate_ad_group_themes" + ] + }, + "GenerateKeywordForecastMetrics": { + "methods": [ + "generate_keyword_forecast_metrics" + ] + }, + "GenerateKeywordHistoricalMetrics": { + "methods": [ + "generate_keyword_historical_metrics" + ] + }, + "GenerateKeywordIdeas": { + "methods": [ + "generate_keyword_ideas" + ] + } + } + }, + "grpc-async": { + "libraryClient": "KeywordPlanIdeaServiceAsyncClient", + "rpcs": { + "GenerateAdGroupThemes": { + "methods": [ + "generate_ad_group_themes" + ] + }, + "GenerateKeywordForecastMetrics": { + "methods": [ + "generate_keyword_forecast_metrics" + ] + }, + "GenerateKeywordHistoricalMetrics": { + "methods": [ + "generate_keyword_historical_metrics" + ] + }, + "GenerateKeywordIdeas": { + "methods": [ + "generate_keyword_ideas" + ] + } + } + } + } + }, + "KeywordPlanService": { + "clients": { + "grpc": { + "libraryClient": "KeywordPlanServiceClient", + "rpcs": { + "MutateKeywordPlans": { + "methods": [ + "mutate_keyword_plans" + ] + } + } + }, + "grpc-async": { + "libraryClient": "KeywordPlanServiceAsyncClient", + "rpcs": { + "MutateKeywordPlans": { + "methods": [ + "mutate_keyword_plans" + ] + } + } + } + } + }, + "KeywordThemeConstantService": { + "clients": { + "grpc": { + "libraryClient": "KeywordThemeConstantServiceClient", + "rpcs": { + "SuggestKeywordThemeConstants": { + "methods": [ + "suggest_keyword_theme_constants" + ] + } + } + }, + "grpc-async": { + "libraryClient": "KeywordThemeConstantServiceAsyncClient", + "rpcs": { + "SuggestKeywordThemeConstants": { + "methods": [ + "suggest_keyword_theme_constants" + ] + } + } + } + } + }, + "LabelService": { + "clients": { + "grpc": { + "libraryClient": "LabelServiceClient", + "rpcs": { + "MutateLabels": { + "methods": [ + "mutate_labels" + ] + } + } + }, + "grpc-async": { + "libraryClient": "LabelServiceAsyncClient", + "rpcs": { + "MutateLabels": { + "methods": [ + "mutate_labels" + ] + } + } + } + } + }, + "LocalServicesLeadService": { + "clients": { + "grpc": { + "libraryClient": "LocalServicesLeadServiceClient", + "rpcs": { + "AppendLeadConversation": { + "methods": [ + "append_lead_conversation" + ] + }, + "ProvideLeadFeedback": { + "methods": [ + "provide_lead_feedback" + ] + } + } + }, + "grpc-async": { + "libraryClient": "LocalServicesLeadServiceAsyncClient", + "rpcs": { + "AppendLeadConversation": { + "methods": [ + "append_lead_conversation" + ] + }, + "ProvideLeadFeedback": { + "methods": [ + "provide_lead_feedback" + ] + } + } + } + } + }, + "OfflineUserDataJobService": { + "clients": { + "grpc": { + "libraryClient": "OfflineUserDataJobServiceClient", + "rpcs": { + "AddOfflineUserDataJobOperations": { + "methods": [ + "add_offline_user_data_job_operations" + ] + }, + "CreateOfflineUserDataJob": { + "methods": [ + "create_offline_user_data_job" + ] + }, + "RunOfflineUserDataJob": { + "methods": [ + "run_offline_user_data_job" + ] + } + } + }, + "grpc-async": { + "libraryClient": "OfflineUserDataJobServiceAsyncClient", + "rpcs": { + "AddOfflineUserDataJobOperations": { + "methods": [ + "add_offline_user_data_job_operations" + ] + }, + "CreateOfflineUserDataJob": { + "methods": [ + "create_offline_user_data_job" + ] + }, + "RunOfflineUserDataJob": { + "methods": [ + "run_offline_user_data_job" + ] + } + } + } + } + }, + "PaymentsAccountService": { + "clients": { + "grpc": { + "libraryClient": "PaymentsAccountServiceClient", + "rpcs": { + "ListPaymentsAccounts": { + "methods": [ + "list_payments_accounts" + ] + } + } + }, + "grpc-async": { + "libraryClient": "PaymentsAccountServiceAsyncClient", + "rpcs": { + "ListPaymentsAccounts": { + "methods": [ + "list_payments_accounts" + ] + } + } + } + } + }, + "ProductLinkInvitationService": { + "clients": { + "grpc": { + "libraryClient": "ProductLinkInvitationServiceClient", + "rpcs": { + "CreateProductLinkInvitation": { + "methods": [ + "create_product_link_invitation" + ] + }, + "RemoveProductLinkInvitation": { + "methods": [ + "remove_product_link_invitation" + ] + }, + "UpdateProductLinkInvitation": { + "methods": [ + "update_product_link_invitation" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ProductLinkInvitationServiceAsyncClient", + "rpcs": { + "CreateProductLinkInvitation": { + "methods": [ + "create_product_link_invitation" + ] + }, + "RemoveProductLinkInvitation": { + "methods": [ + "remove_product_link_invitation" + ] + }, + "UpdateProductLinkInvitation": { + "methods": [ + "update_product_link_invitation" + ] + } + } + } + } + }, + "ProductLinkService": { + "clients": { + "grpc": { + "libraryClient": "ProductLinkServiceClient", + "rpcs": { + "CreateProductLink": { + "methods": [ + "create_product_link" + ] + }, + "RemoveProductLink": { + "methods": [ + "remove_product_link" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ProductLinkServiceAsyncClient", + "rpcs": { + "CreateProductLink": { + "methods": [ + "create_product_link" + ] + }, + "RemoveProductLink": { + "methods": [ + "remove_product_link" + ] + } + } + } + } + }, + "ReachPlanService": { + "clients": { + "grpc": { + "libraryClient": "ReachPlanServiceClient", + "rpcs": { + "GenerateConversionRates": { + "methods": [ + "generate_conversion_rates" + ] + }, + "GenerateReachForecast": { + "methods": [ + "generate_reach_forecast" + ] + }, + "ListPlannableLocations": { + "methods": [ + "list_plannable_locations" + ] + }, + "ListPlannableProducts": { + "methods": [ + "list_plannable_products" + ] + }, + "ListPlannableUserInterests": { + "methods": [ + "list_plannable_user_interests" + ] + }, + "ListPlannableUserLists": { + "methods": [ + "list_plannable_user_lists" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ReachPlanServiceAsyncClient", + "rpcs": { + "GenerateConversionRates": { + "methods": [ + "generate_conversion_rates" + ] + }, + "GenerateReachForecast": { + "methods": [ + "generate_reach_forecast" + ] + }, + "ListPlannableLocations": { + "methods": [ + "list_plannable_locations" + ] + }, + "ListPlannableProducts": { + "methods": [ + "list_plannable_products" + ] + }, + "ListPlannableUserInterests": { + "methods": [ + "list_plannable_user_interests" + ] + }, + "ListPlannableUserLists": { + "methods": [ + "list_plannable_user_lists" + ] + } + } + } + } + }, + "RecommendationService": { + "clients": { + "grpc": { + "libraryClient": "RecommendationServiceClient", + "rpcs": { + "ApplyRecommendation": { + "methods": [ + "apply_recommendation" + ] + }, + "DismissRecommendation": { + "methods": [ + "dismiss_recommendation" + ] + }, + "GenerateRecommendations": { + "methods": [ + "generate_recommendations" + ] + } + } + }, + "grpc-async": { + "libraryClient": "RecommendationServiceAsyncClient", + "rpcs": { + "ApplyRecommendation": { + "methods": [ + "apply_recommendation" + ] + }, + "DismissRecommendation": { + "methods": [ + "dismiss_recommendation" + ] + }, + "GenerateRecommendations": { + "methods": [ + "generate_recommendations" + ] + } + } + } + } + }, + "RecommendationSubscriptionService": { + "clients": { + "grpc": { + "libraryClient": "RecommendationSubscriptionServiceClient", + "rpcs": { + "MutateRecommendationSubscription": { + "methods": [ + "mutate_recommendation_subscription" + ] + } + } + }, + "grpc-async": { + "libraryClient": "RecommendationSubscriptionServiceAsyncClient", + "rpcs": { + "MutateRecommendationSubscription": { + "methods": [ + "mutate_recommendation_subscription" + ] + } + } + } + } + }, + "RemarketingActionService": { + "clients": { + "grpc": { + "libraryClient": "RemarketingActionServiceClient", + "rpcs": { + "MutateRemarketingActions": { + "methods": [ + "mutate_remarketing_actions" + ] + } + } + }, + "grpc-async": { + "libraryClient": "RemarketingActionServiceAsyncClient", + "rpcs": { + "MutateRemarketingActions": { + "methods": [ + "mutate_remarketing_actions" + ] + } + } + } + } + }, + "ReservationService": { + "clients": { + "grpc": { + "libraryClient": "ReservationServiceClient", + "rpcs": { + "BookCampaigns": { + "methods": [ + "book_campaigns" + ] + }, + "QuoteCampaigns": { + "methods": [ + "quote_campaigns" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ReservationServiceAsyncClient", + "rpcs": { + "BookCampaigns": { + "methods": [ + "book_campaigns" + ] + }, + "QuoteCampaigns": { + "methods": [ + "quote_campaigns" + ] + } + } + } + } + }, + "ShareablePreviewService": { + "clients": { + "grpc": { + "libraryClient": "ShareablePreviewServiceClient", + "rpcs": { + "GenerateShareablePreviews": { + "methods": [ + "generate_shareable_previews" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ShareablePreviewServiceAsyncClient", + "rpcs": { + "GenerateShareablePreviews": { + "methods": [ + "generate_shareable_previews" + ] + } + } + } + } + }, + "SharedCriterionService": { + "clients": { + "grpc": { + "libraryClient": "SharedCriterionServiceClient", + "rpcs": { + "MutateSharedCriteria": { + "methods": [ + "mutate_shared_criteria" + ] + } + } + }, + "grpc-async": { + "libraryClient": "SharedCriterionServiceAsyncClient", + "rpcs": { + "MutateSharedCriteria": { + "methods": [ + "mutate_shared_criteria" + ] + } + } + } + } + }, + "SharedSetService": { + "clients": { + "grpc": { + "libraryClient": "SharedSetServiceClient", + "rpcs": { + "MutateSharedSets": { + "methods": [ + "mutate_shared_sets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "SharedSetServiceAsyncClient", + "rpcs": { + "MutateSharedSets": { + "methods": [ + "mutate_shared_sets" + ] + } + } + } + } + }, + "SmartCampaignSettingService": { + "clients": { + "grpc": { + "libraryClient": "SmartCampaignSettingServiceClient", + "rpcs": { + "GetSmartCampaignStatus": { + "methods": [ + "get_smart_campaign_status" + ] + }, + "MutateSmartCampaignSettings": { + "methods": [ + "mutate_smart_campaign_settings" + ] + } + } + }, + "grpc-async": { + "libraryClient": "SmartCampaignSettingServiceAsyncClient", + "rpcs": { + "GetSmartCampaignStatus": { + "methods": [ + "get_smart_campaign_status" + ] + }, + "MutateSmartCampaignSettings": { + "methods": [ + "mutate_smart_campaign_settings" + ] + } + } + } + } + }, + "SmartCampaignSuggestService": { + "clients": { + "grpc": { + "libraryClient": "SmartCampaignSuggestServiceClient", + "rpcs": { + "SuggestKeywordThemes": { + "methods": [ + "suggest_keyword_themes" + ] + }, + "SuggestSmartCampaignAd": { + "methods": [ + "suggest_smart_campaign_ad" + ] + }, + "SuggestSmartCampaignBudgetOptions": { + "methods": [ + "suggest_smart_campaign_budget_options" + ] + } + } + }, + "grpc-async": { + "libraryClient": "SmartCampaignSuggestServiceAsyncClient", + "rpcs": { + "SuggestKeywordThemes": { + "methods": [ + "suggest_keyword_themes" + ] + }, + "SuggestSmartCampaignAd": { + "methods": [ + "suggest_smart_campaign_ad" + ] + }, + "SuggestSmartCampaignBudgetOptions": { + "methods": [ + "suggest_smart_campaign_budget_options" + ] + } + } + } + } + }, + "ThirdPartyAppAnalyticsLinkService": { + "clients": { + "grpc": { + "libraryClient": "ThirdPartyAppAnalyticsLinkServiceClient", + "rpcs": { + "RegenerateShareableLinkId": { + "methods": [ + "regenerate_shareable_link_id" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ThirdPartyAppAnalyticsLinkServiceAsyncClient", + "rpcs": { + "RegenerateShareableLinkId": { + "methods": [ + "regenerate_shareable_link_id" + ] + } + } + } + } + }, + "TravelAssetSuggestionService": { + "clients": { + "grpc": { + "libraryClient": "TravelAssetSuggestionServiceClient", + "rpcs": { + "SuggestTravelAssets": { + "methods": [ + "suggest_travel_assets" + ] + } + } + }, + "grpc-async": { + "libraryClient": "TravelAssetSuggestionServiceAsyncClient", + "rpcs": { + "SuggestTravelAssets": { + "methods": [ + "suggest_travel_assets" + ] + } + } + } + } + }, + "UserDataService": { + "clients": { + "grpc": { + "libraryClient": "UserDataServiceClient", + "rpcs": { + "UploadUserData": { + "methods": [ + "upload_user_data" + ] + } + } + }, + "grpc-async": { + "libraryClient": "UserDataServiceAsyncClient", + "rpcs": { + "UploadUserData": { + "methods": [ + "upload_user_data" + ] + } + } + } + } + }, + "UserListCustomerTypeService": { + "clients": { + "grpc": { + "libraryClient": "UserListCustomerTypeServiceClient", + "rpcs": { + "MutateUserListCustomerTypes": { + "methods": [ + "mutate_user_list_customer_types" + ] + } + } + }, + "grpc-async": { + "libraryClient": "UserListCustomerTypeServiceAsyncClient", + "rpcs": { + "MutateUserListCustomerTypes": { + "methods": [ + "mutate_user_list_customer_types" + ] + } + } + } + } + }, + "UserListService": { + "clients": { + "grpc": { + "libraryClient": "UserListServiceClient", + "rpcs": { + "MutateUserLists": { + "methods": [ + "mutate_user_lists" + ] + } + } + }, + "grpc-async": { + "libraryClient": "UserListServiceAsyncClient", + "rpcs": { + "MutateUserLists": { + "methods": [ + "mutate_user_lists" + ] + } + } + } + } + }, + "YouTubeVideoUploadService": { + "clients": { + "grpc": { + "libraryClient": "YouTubeVideoUploadServiceClient", + "rpcs": { + "CreateYouTubeVideoUpload": { + "methods": [ + "create_you_tube_video_upload" + ] + }, + "RemoveYouTubeVideoUpload": { + "methods": [ + "remove_you_tube_video_upload" + ] + }, + "UpdateYouTubeVideoUpload": { + "methods": [ + "update_you_tube_video_upload" + ] + } + } + }, + "grpc-async": { + "libraryClient": "YouTubeVideoUploadServiceAsyncClient", + "rpcs": { + "CreateYouTubeVideoUpload": { + "methods": [ + "create_you_tube_video_upload" + ] + }, + "RemoveYouTubeVideoUpload": { + "methods": [ + "remove_you_tube_video_upload" + ] + }, + "UpdateYouTubeVideoUpload": { + "methods": [ + "update_you_tube_video_upload" + ] + } + } + } + } + } + } +} diff --git a/google/ads/googleads/v24/gapic_version.py b/google/ads/googleads/v24/gapic_version.py new file mode 100644 index 000000000..20a9cd975 --- /dev/null +++ b/google/ads/googleads/v24/gapic_version.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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. +# +__version__ = "0.0.0" # {x-release-please-version} diff --git a/google/ads/googleads/v24/py.typed b/google/ads/googleads/v24/py.typed new file mode 100644 index 000000000..39dfeaa1d --- /dev/null +++ b/google/ads/googleads/v24/py.typed @@ -0,0 +1,2 @@ +# Marker file for PEP 561. +# The google-ads package uses inline types. diff --git a/google/ads/googleads/v24/resources/__init__.py b/google/ads/googleads/v24/resources/__init__.py new file mode 100644 index 000000000..93bf17bc9 --- /dev/null +++ b/google/ads/googleads/v24/resources/__init__.py @@ -0,0 +1,677 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 google.ads.googleads.v24 import gapic_version as package_version + +import google.api_core as api_core +import sys + +__version__ = package_version.__version__ + +if sys.version_info >= (3, 8): # pragma: NO COVER + from importlib import metadata +else: # pragma: NO COVER + # TODO(https://github.com/googleapis/python-api-core/issues/835): Remove + # this code path once we drop support for Python 3.7 + import importlib_metadata as metadata + + +from .types.accessible_bidding_strategy import AccessibleBiddingStrategy +from .types.account_budget import AccountBudget +from .types.account_budget_proposal import AccountBudgetProposal +from .types.account_link import AccountLink +from .types.account_link import ThirdPartyAppAnalyticsLinkIdentifier +from .types.ad import Ad +from .types.ad_group import AdGroup +from .types.ad_group_ad import AdGroupAd +from .types.ad_group_ad import AdGroupAdAssetAutomationSetting +from .types.ad_group_ad import AdGroupAdPolicySummary +from .types.ad_group_ad_asset_combination_view import ( + AdGroupAdAssetCombinationView, +) +from .types.ad_group_ad_asset_view import AdGroupAdAssetPolicySummary +from .types.ad_group_ad_asset_view import AdGroupAdAssetView +from .types.ad_group_ad_label import AdGroupAdLabel +from .types.ad_group_asset import AdGroupAsset +from .types.ad_group_asset_set import AdGroupAssetSet +from .types.ad_group_audience_view import AdGroupAudienceView +from .types.ad_group_bid_modifier import AdGroupBidModifier +from .types.ad_group_criterion import AdGroupCriterion +from .types.ad_group_criterion_customizer import AdGroupCriterionCustomizer +from .types.ad_group_criterion_label import AdGroupCriterionLabel +from .types.ad_group_criterion_simulation import AdGroupCriterionSimulation +from .types.ad_group_customizer import AdGroupCustomizer +from .types.ad_group_label import AdGroupLabel +from .types.ad_group_simulation import AdGroupSimulation +from .types.ad_parameter import AdParameter +from .types.ad_schedule_view import AdScheduleView +from .types.age_range_view import AgeRangeView +from .types.ai_max_search_term_ad_combination_view import ( + AiMaxSearchTermAdCombinationView, +) +from .types.android_privacy_shared_key_google_ad_group import ( + AndroidPrivacySharedKeyGoogleAdGroup, +) +from .types.android_privacy_shared_key_google_campaign import ( + AndroidPrivacySharedKeyGoogleCampaign, +) +from .types.android_privacy_shared_key_google_network_type import ( + AndroidPrivacySharedKeyGoogleNetworkType, +) +from .types.app_top_combination_view import AdGroupCreativeAssetCombinationData +from .types.app_top_combination_view import AppTopCombinationView +from .types.applied_incentive import AppliedIncentive +from .types.asset import Asset +from .types.asset import AssetFieldTypePolicySummary +from .types.asset import AssetPolicySummary +from .types.asset_field_type_view import AssetFieldTypeView +from .types.asset_group import AdStrengthActionItem +from .types.asset_group import AssetCoverage +from .types.asset_group import AssetGroup +from .types.asset_group_asset import AssetGroupAsset +from .types.asset_group_listing_group_filter import AssetGroupListingGroupFilter +from .types.asset_group_listing_group_filter import ListingGroupFilterDimension +from .types.asset_group_listing_group_filter import ( + ListingGroupFilterDimensionPath, +) +from .types.asset_group_product_group_view import AssetGroupProductGroupView +from .types.asset_group_signal import AssetGroupSignal +from .types.asset_group_top_combination_view import ( + AssetGroupAssetCombinationData, +) +from .types.asset_group_top_combination_view import AssetGroupTopCombinationView +from .types.asset_set import AssetSet +from .types.asset_set_asset import AssetSetAsset +from .types.asset_set_type_view import AssetSetTypeView +from .types.audience import Audience +from .types.batch_job import BatchJob +from .types.bidding_data_exclusion import BiddingDataExclusion +from .types.bidding_seasonality_adjustment import BiddingSeasonalityAdjustment +from .types.bidding_strategy import BiddingStrategy +from .types.bidding_strategy_simulation import BiddingStrategySimulation +from .types.billing_setup import BillingSetup +from .types.call_view import CallView +from .types.campaign import Campaign +from .types.campaign_aggregate_asset_view import CampaignAggregateAssetView +from .types.campaign_asset import CampaignAsset +from .types.campaign_asset_set import CampaignAssetSet +from .types.campaign_audience_view import CampaignAudienceView +from .types.campaign_bid_modifier import CampaignBidModifier +from .types.campaign_budget import CampaignBudget +from .types.campaign_conversion_goal import CampaignConversionGoal +from .types.campaign_criterion import CampaignCriterion +from .types.campaign_customizer import CampaignCustomizer +from .types.campaign_draft import CampaignDraft +from .types.campaign_goal_config import CampaignGoalConfig +from .types.campaign_group import CampaignGroup +from .types.campaign_label import CampaignLabel +from .types.campaign_lifecycle_goal import CampaignLifecycleGoal +from .types.campaign_lifecycle_goal import CustomerAcquisitionGoalSettings +from .types.campaign_search_term_insight import CampaignSearchTermInsight +from .types.campaign_search_term_view import CampaignSearchTermView +from .types.campaign_shared_set import CampaignSharedSet +from .types.campaign_simulation import CampaignSimulation +from .types.carrier_constant import CarrierConstant +from .types.cart_data_sales_view import CartDataSalesView +from .types.change_event import ChangeEvent +from .types.change_status import ChangeStatus +from .types.channel_aggregate_asset_view import ChannelAggregateAssetView +from .types.click_view import ClickView +from .types.combined_audience import CombinedAudience +from .types.content_criterion_view import ContentCriterionView +from .types.conversion_action import ConversionAction +from .types.conversion_custom_variable import ConversionCustomVariable +from .types.conversion_goal_campaign_config import ConversionGoalCampaignConfig +from .types.conversion_value_rule import ConversionValueRule +from .types.conversion_value_rule_set import ConversionValueRuleSet +from .types.currency_constant import CurrencyConstant +from .types.custom_audience import CustomAudience +from .types.custom_audience import CustomAudienceMember +from .types.custom_conversion_goal import CustomConversionGoal +from .types.custom_interest import CustomInterest +from .types.custom_interest import CustomInterestMember +from .types.customer import CallReportingSetting +from .types.customer import ConversionTrackingSetting +from .types.customer import Customer +from .types.customer import CustomerAgreementSetting +from .types.customer import GranularInsuranceStatus +from .types.customer import GranularLicenseStatus +from .types.customer import LocalServicesSettings +from .types.customer import RemarketingSetting +from .types.customer import VideoCustomer +from .types.customer_asset import CustomerAsset +from .types.customer_asset_set import CustomerAssetSet +from .types.customer_client import CustomerClient +from .types.customer_client_link import CustomerClientLink +from .types.customer_conversion_goal import CustomerConversionGoal +from .types.customer_customizer import CustomerCustomizer +from .types.customer_label import CustomerLabel +from .types.customer_lifecycle_goal import CustomerLifecycleGoal +from .types.customer_manager_link import CustomerManagerLink +from .types.customer_negative_criterion import CustomerNegativeCriterion +from .types.customer_search_term_insight import CustomerSearchTermInsight +from .types.customer_sk_ad_network_conversion_value_schema import ( + CustomerSkAdNetworkConversionValueSchema, +) +from .types.customer_user_access import CustomerUserAccess +from .types.customer_user_access_invitation import CustomerUserAccessInvitation +from .types.customizer_attribute import CustomizerAttribute +from .types.data_link import DataLink +from .types.data_link import YoutubeVideoIdentifier +from .types.detail_content_suitability_placement_view import ( + DetailContentSuitabilityPlacementView, +) +from .types.detail_placement_view import DetailPlacementView +from .types.detailed_demographic import DetailedDemographic +from .types.display_keyword_view import DisplayKeywordView +from .types.distance_view import DistanceView +from .types.domain_category import DomainCategory +from .types.dynamic_search_ads_search_term_view import ( + DynamicSearchAdsSearchTermView, +) +from .types.expanded_landing_page_view import ExpandedLandingPageView +from .types.experiment import Experiment +from .types.experiment_arm import ExperimentArm +from .types.final_url_expansion_asset_view import FinalUrlExpansionAssetView +from .types.gender_view import GenderView +from .types.geo_target_constant import GeoTargetConstant +from .types.geographic_view import GeographicView +from .types.goal import Goal +from .types.google_ads_field import GoogleAdsField +from .types.group_content_suitability_placement_view import ( + GroupContentSuitabilityPlacementView, +) +from .types.group_placement_view import GroupPlacementView +from .types.hotel_group_view import HotelGroupView +from .types.hotel_performance_view import HotelPerformanceView +from .types.hotel_reconciliation import HotelReconciliation +from .types.income_range_view import IncomeRangeView +from .types.invoice import Invoice +from .types.keyword_plan import KeywordPlan +from .types.keyword_plan import KeywordPlanForecastPeriod +from .types.keyword_plan_ad_group import KeywordPlanAdGroup +from .types.keyword_plan_ad_group_keyword import KeywordPlanAdGroupKeyword +from .types.keyword_plan_campaign import KeywordPlanCampaign +from .types.keyword_plan_campaign import KeywordPlanGeoTarget +from .types.keyword_plan_campaign_keyword import KeywordPlanCampaignKeyword +from .types.keyword_theme_constant import KeywordThemeConstant +from .types.keyword_view import KeywordView +from .types.label import Label +from .types.landing_page_view import LandingPageView +from .types.language_constant import LanguageConstant +from .types.lead_form_submission_data import CustomLeadFormSubmissionField +from .types.lead_form_submission_data import LeadFormSubmissionData +from .types.lead_form_submission_data import LeadFormSubmissionField +from .types.life_event import LifeEvent +from .types.local_services_employee import Fellowship +from .types.local_services_employee import LocalServicesEmployee +from .types.local_services_employee import Residency +from .types.local_services_employee import UniversityDegree +from .types.local_services_lead import ContactDetails +from .types.local_services_lead import CreditDetails +from .types.local_services_lead import LocalServicesLead +from .types.local_services_lead import Note +from .types.local_services_lead_conversation import ( + LocalServicesLeadConversation, +) +from .types.local_services_lead_conversation import MessageDetails +from .types.local_services_lead_conversation import PhoneCallDetails +from .types.local_services_verification_artifact import ( + BackgroundCheckVerificationArtifact, +) +from .types.local_services_verification_artifact import ( + BusinessRegistrationCheckVerificationArtifact, +) +from .types.local_services_verification_artifact import ( + BusinessRegistrationDocument, +) +from .types.local_services_verification_artifact import ( + BusinessRegistrationNumber, +) +from .types.local_services_verification_artifact import ( + InsuranceVerificationArtifact, +) +from .types.local_services_verification_artifact import ( + LicenseVerificationArtifact, +) +from .types.local_services_verification_artifact import ( + LocalServicesVerificationArtifact, +) +from .types.location_interest_view import LocationInterestView +from .types.location_view import LocationView +from .types.managed_placement_view import ManagedPlacementView +from .types.matched_location_interest_view import MatchedLocationInterestView +from .types.media_file import MediaAudio +from .types.media_file import MediaBundle +from .types.media_file import MediaFile +from .types.media_file import MediaImage +from .types.media_file import MediaVideo +from .types.mobile_app_category_constant import MobileAppCategoryConstant +from .types.mobile_device_constant import MobileDeviceConstant +from .types.offline_conversion_upload_client_summary import ( + OfflineConversionAlert, +) +from .types.offline_conversion_upload_client_summary import ( + OfflineConversionError, +) +from .types.offline_conversion_upload_client_summary import ( + OfflineConversionSummary, +) +from .types.offline_conversion_upload_client_summary import ( + OfflineConversionUploadClientSummary, +) +from .types.offline_conversion_upload_conversion_action_summary import ( + OfflineConversionUploadConversionActionSummary, +) +from .types.offline_user_data_job import OfflineUserDataJob +from .types.offline_user_data_job import OfflineUserDataJobMetadata +from .types.operating_system_version_constant import ( + OperatingSystemVersionConstant, +) +from .types.paid_organic_search_term_view import PaidOrganicSearchTermView +from .types.parental_status_view import ParentalStatusView +from .types.payments_account import PaymentsAccount +from .types.per_store_view import PerStoreView +from .types.performance_max_placement_view import PerformanceMaxPlacementView +from .types.product_category_constant import ProductCategoryConstant +from .types.product_group_view import ProductGroupView +from .types.product_link import AdvertisingPartnerIdentifier +from .types.product_link import AdvertisingPartnerProperties +from .types.product_link import DataPartnerIdentifier +from .types.product_link import GoogleAdsIdentifier +from .types.product_link import MerchantCenterIdentifier +from .types.product_link import ProductLink +from .types.product_link_invitation import ( + AdvertisingPartnerLinkInvitationIdentifier, +) +from .types.product_link_invitation import ( + AdvertisingPartnerLinkInvitationProperties, +) +from .types.product_link_invitation import HotelCenterLinkInvitationIdentifier +from .types.product_link_invitation import ( + MerchantCenterLinkInvitationIdentifier, +) +from .types.product_link_invitation import ProductLinkInvitation +from .types.qualifying_question import QualifyingQuestion +from .types.recommendation import Recommendation +from .types.recommendation_subscription import RecommendationSubscription +from .types.remarketing_action import RemarketingAction +from .types.search_term_view import SearchTermView +from .types.shared_criterion import SharedCriterion +from .types.shared_set import SharedSet +from .types.shopping_performance_view import ShoppingPerformanceView +from .types.shopping_product import ShoppingProduct +from .types.smart_campaign_search_term_view import SmartCampaignSearchTermView +from .types.smart_campaign_setting import SmartCampaignSetting +from .types.targeting_expansion_view import TargetingExpansionView +from .types.third_party_app_analytics_link import ThirdPartyAppAnalyticsLink +from .types.topic_constant import TopicConstant +from .types.topic_view import TopicView +from .types.travel_activity_group_view import TravelActivityGroupView +from .types.travel_activity_performance_view import ( + TravelActivityPerformanceView, +) +from .types.user_interest import UserInterest +from .types.user_list import UserList +from .types.user_list_customer_type import UserListCustomerType +from .types.user_location_view import UserLocationView +from .types.video import Video +from .types.video_enhancement import VideoEnhancement +from .types.webpage_view import WebpageView +from .types.youtube_video_upload import YouTubeVideoUpload + +if hasattr(api_core, "check_python_version") and hasattr( + api_core, "check_dependency_versions" +): # pragma: NO COVER + api_core.check_python_version("google.ads.googleads.v24") # type: ignore + api_core.check_dependency_versions("google.ads.googleads.v24") # type: ignore +else: # pragma: NO COVER + # An older version of api_core is installed which does not define the + # functions above. We do equivalent checks manually. + try: + import warnings + import sys + + _py_version_str = sys.version.split()[0] + _package_label = "google.ads.googleads.v24" + if sys.version_info < (3, 9): + warnings.warn( + "You are using a non-supported Python version " + + f"({_py_version_str}). Google will not post any further " + + f"updates to {_package_label} supporting this Python version. " + + "Please upgrade to the latest Python version, or at " + + f"least to Python 3.9, and then update {_package_label}.", + FutureWarning, + ) + if sys.version_info[:2] == (3, 9): + warnings.warn( + f"You are using a Python version ({_py_version_str}) " + + f"which Google will stop supporting in {_package_label} in " + + "January 2026. Please " + + "upgrade to the latest Python version, or at " + + "least to Python 3.10, before then, and " + + f"then update {_package_label}.", + FutureWarning, + ) + + def parse_version_to_tuple(version_string: str): + """Safely converts a semantic version string to a comparable tuple of integers. + Example: "4.25.8" -> (4, 25, 8) + Ignores non-numeric parts and handles common version formats. + Args: + version_string: Version string in the format "x.y.z" or "x.y.z" + Returns: + Tuple of integers for the parsed version string. + """ + parts = [] + for part in version_string.split("."): + try: + parts.append(int(part)) + except ValueError: + # If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here. + # This is a simplification compared to 'packaging.parse_version', but sufficient + # for comparing strictly numeric semantic versions. + break + return tuple(parts) + + def _get_version(dependency_name): + try: + version_string: str = metadata.version(dependency_name) + parsed_version = parse_version_to_tuple(version_string) + return (parsed_version, version_string) + except Exception: + # Catch exceptions from metadata.version() (e.g., PackageNotFoundError) + # or errors during parse_version_to_tuple + return (None, "--") + + _dependency_package = "google.protobuf" + _next_supported_version = "4.25.8" + _next_supported_version_tuple = (4, 25, 8) + _recommendation = " (we recommend 6.x)" + (_version_used, _version_used_string) = _get_version( + _dependency_package + ) + if _version_used and _version_used < _next_supported_version_tuple: + warnings.warn( + f"Package {_package_label} depends on " + + f"{_dependency_package}, currently installed at version " + + f"{_version_used_string}. Future updates to " + + f"{_package_label} will require {_dependency_package} at " + + f"version {_next_supported_version} or higher{_recommendation}." + + " Please ensure " + + "that either (a) your Python environment doesn't pin the " + + f"version of {_dependency_package}, so that updates to " + + f"{_package_label} can require the higher version, or " + + "(b) you manually update your Python environment to use at " + + f"least version {_next_supported_version} of " + + f"{_dependency_package}.", + FutureWarning, + ) + except Exception: + warnings.warn( + "Could not determine the version of Python " + + "currently being used. To continue receiving " + + "updates for {_package_label}, ensure you are " + + "using a supported version of Python; see " + + "https://devguide.python.org/versions/" + ) + +__all__ = ( + "AccessibleBiddingStrategy", + "AccountBudget", + "AccountBudgetProposal", + "AccountLink", + "Ad", + "AdGroup", + "AdGroupAd", + "AdGroupAdAssetAutomationSetting", + "AdGroupAdAssetCombinationView", + "AdGroupAdAssetPolicySummary", + "AdGroupAdAssetView", + "AdGroupAdLabel", + "AdGroupAdPolicySummary", + "AdGroupAsset", + "AdGroupAssetSet", + "AdGroupAudienceView", + "AdGroupBidModifier", + "AdGroupCreativeAssetCombinationData", + "AdGroupCriterion", + "AdGroupCriterionCustomizer", + "AdGroupCriterionLabel", + "AdGroupCriterionSimulation", + "AdGroupCustomizer", + "AdGroupLabel", + "AdGroupSimulation", + "AdParameter", + "AdScheduleView", + "AdStrengthActionItem", + "AdvertisingPartnerIdentifier", + "AdvertisingPartnerLinkInvitationIdentifier", + "AdvertisingPartnerLinkInvitationProperties", + "AdvertisingPartnerProperties", + "AgeRangeView", + "AiMaxSearchTermAdCombinationView", + "AndroidPrivacySharedKeyGoogleAdGroup", + "AndroidPrivacySharedKeyGoogleCampaign", + "AndroidPrivacySharedKeyGoogleNetworkType", + "AppTopCombinationView", + "AppliedIncentive", + "Asset", + "AssetCoverage", + "AssetFieldTypePolicySummary", + "AssetFieldTypeView", + "AssetGroup", + "AssetGroupAsset", + "AssetGroupAssetCombinationData", + "AssetGroupListingGroupFilter", + "AssetGroupProductGroupView", + "AssetGroupSignal", + "AssetGroupTopCombinationView", + "AssetPolicySummary", + "AssetSet", + "AssetSetAsset", + "AssetSetTypeView", + "Audience", + "BackgroundCheckVerificationArtifact", + "BatchJob", + "BiddingDataExclusion", + "BiddingSeasonalityAdjustment", + "BiddingStrategy", + "BiddingStrategySimulation", + "BillingSetup", + "BusinessRegistrationCheckVerificationArtifact", + "BusinessRegistrationDocument", + "BusinessRegistrationNumber", + "CallReportingSetting", + "CallView", + "Campaign", + "CampaignAggregateAssetView", + "CampaignAsset", + "CampaignAssetSet", + "CampaignAudienceView", + "CampaignBidModifier", + "CampaignBudget", + "CampaignConversionGoal", + "CampaignCriterion", + "CampaignCustomizer", + "CampaignDraft", + "CampaignGoalConfig", + "CampaignGroup", + "CampaignLabel", + "CampaignLifecycleGoal", + "CampaignSearchTermInsight", + "CampaignSearchTermView", + "CampaignSharedSet", + "CampaignSimulation", + "CarrierConstant", + "CartDataSalesView", + "ChangeEvent", + "ChangeStatus", + "ChannelAggregateAssetView", + "ClickView", + "CombinedAudience", + "ContactDetails", + "ContentCriterionView", + "ConversionAction", + "ConversionCustomVariable", + "ConversionGoalCampaignConfig", + "ConversionTrackingSetting", + "ConversionValueRule", + "ConversionValueRuleSet", + "CreditDetails", + "CurrencyConstant", + "CustomAudience", + "CustomAudienceMember", + "CustomConversionGoal", + "CustomInterest", + "CustomInterestMember", + "CustomLeadFormSubmissionField", + "Customer", + "CustomerAcquisitionGoalSettings", + "CustomerAgreementSetting", + "CustomerAsset", + "CustomerAssetSet", + "CustomerClient", + "CustomerClientLink", + "CustomerConversionGoal", + "CustomerCustomizer", + "CustomerLabel", + "CustomerLifecycleGoal", + "CustomerManagerLink", + "CustomerNegativeCriterion", + "CustomerSearchTermInsight", + "CustomerSkAdNetworkConversionValueSchema", + "CustomerUserAccess", + "CustomerUserAccessInvitation", + "CustomizerAttribute", + "DataLink", + "DataPartnerIdentifier", + "DetailContentSuitabilityPlacementView", + "DetailPlacementView", + "DetailedDemographic", + "DisplayKeywordView", + "DistanceView", + "DomainCategory", + "DynamicSearchAdsSearchTermView", + "ExpandedLandingPageView", + "Experiment", + "ExperimentArm", + "Fellowship", + "FinalUrlExpansionAssetView", + "GenderView", + "GeoTargetConstant", + "GeographicView", + "Goal", + "GoogleAdsField", + "GoogleAdsIdentifier", + "GranularInsuranceStatus", + "GranularLicenseStatus", + "GroupContentSuitabilityPlacementView", + "GroupPlacementView", + "HotelCenterLinkInvitationIdentifier", + "HotelGroupView", + "HotelPerformanceView", + "HotelReconciliation", + "IncomeRangeView", + "InsuranceVerificationArtifact", + "Invoice", + "KeywordPlan", + "KeywordPlanAdGroup", + "KeywordPlanAdGroupKeyword", + "KeywordPlanCampaign", + "KeywordPlanCampaignKeyword", + "KeywordPlanForecastPeriod", + "KeywordPlanGeoTarget", + "KeywordThemeConstant", + "KeywordView", + "Label", + "LandingPageView", + "LanguageConstant", + "LeadFormSubmissionData", + "LeadFormSubmissionField", + "LicenseVerificationArtifact", + "LifeEvent", + "ListingGroupFilterDimension", + "ListingGroupFilterDimensionPath", + "LocalServicesEmployee", + "LocalServicesLead", + "LocalServicesLeadConversation", + "LocalServicesSettings", + "LocalServicesVerificationArtifact", + "LocationInterestView", + "LocationView", + "ManagedPlacementView", + "MatchedLocationInterestView", + "MediaAudio", + "MediaBundle", + "MediaFile", + "MediaImage", + "MediaVideo", + "MerchantCenterIdentifier", + "MerchantCenterLinkInvitationIdentifier", + "MessageDetails", + "MobileAppCategoryConstant", + "MobileDeviceConstant", + "Note", + "OfflineConversionAlert", + "OfflineConversionError", + "OfflineConversionSummary", + "OfflineConversionUploadClientSummary", + "OfflineConversionUploadConversionActionSummary", + "OfflineUserDataJob", + "OfflineUserDataJobMetadata", + "OperatingSystemVersionConstant", + "PaidOrganicSearchTermView", + "ParentalStatusView", + "PaymentsAccount", + "PerStoreView", + "PerformanceMaxPlacementView", + "PhoneCallDetails", + "ProductCategoryConstant", + "ProductGroupView", + "ProductLink", + "ProductLinkInvitation", + "QualifyingQuestion", + "Recommendation", + "RecommendationSubscription", + "RemarketingAction", + "RemarketingSetting", + "Residency", + "SearchTermView", + "SharedCriterion", + "SharedSet", + "ShoppingPerformanceView", + "ShoppingProduct", + "SmartCampaignSearchTermView", + "SmartCampaignSetting", + "TargetingExpansionView", + "ThirdPartyAppAnalyticsLink", + "ThirdPartyAppAnalyticsLinkIdentifier", + "TopicConstant", + "TopicView", + "TravelActivityGroupView", + "TravelActivityPerformanceView", + "UniversityDegree", + "UserInterest", + "UserList", + "UserListCustomerType", + "UserLocationView", + "Video", + "VideoCustomer", + "VideoEnhancement", + "WebpageView", + "YouTubeVideoUpload", + "YoutubeVideoIdentifier", +) diff --git a/google/ads/googleads/v24/resources/services/__init__.py b/google/ads/googleads/v24/resources/services/__init__.py new file mode 100644 index 000000000..cbf94b283 --- /dev/null +++ b/google/ads/googleads/v24/resources/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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. +# diff --git a/google/ads/googleads/v24/resources/types/__init__.py b/google/ads/googleads/v24/resources/types/__init__.py new file mode 100644 index 000000000..b2e646148 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/__init__.py @@ -0,0 +1,880 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .accessible_bidding_strategy import ( + AccessibleBiddingStrategy, +) +from .account_budget import ( + AccountBudget, +) +from .account_budget_proposal import ( + AccountBudgetProposal, +) +from .account_link import ( + AccountLink, + ThirdPartyAppAnalyticsLinkIdentifier, +) +from .ad import ( + Ad, +) +from .ad_group import ( + AdGroup, +) +from .ad_group_ad import ( + AdGroupAd, + AdGroupAdAssetAutomationSetting, + AdGroupAdPolicySummary, +) +from .ad_group_ad_asset_combination_view import ( + AdGroupAdAssetCombinationView, +) +from .ad_group_ad_asset_view import ( + AdGroupAdAssetPolicySummary, + AdGroupAdAssetView, +) +from .ad_group_ad_label import ( + AdGroupAdLabel, +) +from .ad_group_asset import ( + AdGroupAsset, +) +from .ad_group_asset_set import ( + AdGroupAssetSet, +) +from .ad_group_audience_view import ( + AdGroupAudienceView, +) +from .ad_group_bid_modifier import ( + AdGroupBidModifier, +) +from .ad_group_criterion import ( + AdGroupCriterion, +) +from .ad_group_criterion_customizer import ( + AdGroupCriterionCustomizer, +) +from .ad_group_criterion_label import ( + AdGroupCriterionLabel, +) +from .ad_group_criterion_simulation import ( + AdGroupCriterionSimulation, +) +from .ad_group_customizer import ( + AdGroupCustomizer, +) +from .ad_group_label import ( + AdGroupLabel, +) +from .ad_group_simulation import ( + AdGroupSimulation, +) +from .ad_parameter import ( + AdParameter, +) +from .ad_schedule_view import ( + AdScheduleView, +) +from .age_range_view import ( + AgeRangeView, +) +from .ai_max_search_term_ad_combination_view import ( + AiMaxSearchTermAdCombinationView, +) +from .android_privacy_shared_key_google_ad_group import ( + AndroidPrivacySharedKeyGoogleAdGroup, +) +from .android_privacy_shared_key_google_campaign import ( + AndroidPrivacySharedKeyGoogleCampaign, +) +from .android_privacy_shared_key_google_network_type import ( + AndroidPrivacySharedKeyGoogleNetworkType, +) +from .app_top_combination_view import ( + AdGroupCreativeAssetCombinationData, + AppTopCombinationView, +) +from .applied_incentive import ( + AppliedIncentive, +) +from .asset import ( + Asset, + AssetFieldTypePolicySummary, + AssetPolicySummary, +) +from .asset_field_type_view import ( + AssetFieldTypeView, +) +from .asset_group import ( + AdStrengthActionItem, + AssetCoverage, + AssetGroup, +) +from .asset_group_asset import ( + AssetGroupAsset, +) +from .asset_group_listing_group_filter import ( + AssetGroupListingGroupFilter, + ListingGroupFilterDimension, + ListingGroupFilterDimensionPath, +) +from .asset_group_product_group_view import ( + AssetGroupProductGroupView, +) +from .asset_group_signal import ( + AssetGroupSignal, +) +from .asset_group_top_combination_view import ( + AssetGroupAssetCombinationData, + AssetGroupTopCombinationView, +) +from .asset_set import ( + AssetSet, +) +from .asset_set_asset import ( + AssetSetAsset, +) +from .asset_set_type_view import ( + AssetSetTypeView, +) +from .audience import ( + Audience, +) +from .batch_job import ( + BatchJob, +) +from .bidding_data_exclusion import ( + BiddingDataExclusion, +) +from .bidding_seasonality_adjustment import ( + BiddingSeasonalityAdjustment, +) +from .bidding_strategy import ( + BiddingStrategy, +) +from .bidding_strategy_simulation import ( + BiddingStrategySimulation, +) +from .billing_setup import ( + BillingSetup, +) +from .call_view import ( + CallView, +) +from .campaign import ( + Campaign, +) +from .campaign_aggregate_asset_view import ( + CampaignAggregateAssetView, +) +from .campaign_asset import ( + CampaignAsset, +) +from .campaign_asset_set import ( + CampaignAssetSet, +) +from .campaign_audience_view import ( + CampaignAudienceView, +) +from .campaign_bid_modifier import ( + CampaignBidModifier, +) +from .campaign_budget import ( + CampaignBudget, +) +from .campaign_conversion_goal import ( + CampaignConversionGoal, +) +from .campaign_criterion import ( + CampaignCriterion, +) +from .campaign_customizer import ( + CampaignCustomizer, +) +from .campaign_draft import ( + CampaignDraft, +) +from .campaign_goal_config import ( + CampaignGoalConfig, +) +from .campaign_group import ( + CampaignGroup, +) +from .campaign_label import ( + CampaignLabel, +) +from .campaign_lifecycle_goal import ( + CampaignLifecycleGoal, + CustomerAcquisitionGoalSettings, +) +from .campaign_search_term_insight import ( + CampaignSearchTermInsight, +) +from .campaign_search_term_view import ( + CampaignSearchTermView, +) +from .campaign_shared_set import ( + CampaignSharedSet, +) +from .campaign_simulation import ( + CampaignSimulation, +) +from .carrier_constant import ( + CarrierConstant, +) +from .cart_data_sales_view import ( + CartDataSalesView, +) +from .change_event import ( + ChangeEvent, +) +from .change_status import ( + ChangeStatus, +) +from .channel_aggregate_asset_view import ( + ChannelAggregateAssetView, +) +from .click_view import ( + ClickView, +) +from .combined_audience import ( + CombinedAudience, +) +from .content_criterion_view import ( + ContentCriterionView, +) +from .conversion_action import ( + ConversionAction, +) +from .conversion_custom_variable import ( + ConversionCustomVariable, +) +from .conversion_goal_campaign_config import ( + ConversionGoalCampaignConfig, +) +from .conversion_value_rule import ( + ConversionValueRule, +) +from .conversion_value_rule_set import ( + ConversionValueRuleSet, +) +from .currency_constant import ( + CurrencyConstant, +) +from .custom_audience import ( + CustomAudience, + CustomAudienceMember, +) +from .custom_conversion_goal import ( + CustomConversionGoal, +) +from .custom_interest import ( + CustomInterest, + CustomInterestMember, +) +from .customer import ( + CallReportingSetting, + ConversionTrackingSetting, + Customer, + CustomerAgreementSetting, + GranularInsuranceStatus, + GranularLicenseStatus, + LocalServicesSettings, + RemarketingSetting, + VideoCustomer, +) +from .customer_asset import ( + CustomerAsset, +) +from .customer_asset_set import ( + CustomerAssetSet, +) +from .customer_client import ( + CustomerClient, +) +from .customer_client_link import ( + CustomerClientLink, +) +from .customer_conversion_goal import ( + CustomerConversionGoal, +) +from .customer_customizer import ( + CustomerCustomizer, +) +from .customer_label import ( + CustomerLabel, +) +from .customer_lifecycle_goal import ( + CustomerLifecycleGoal, +) +from .customer_manager_link import ( + CustomerManagerLink, +) +from .customer_negative_criterion import ( + CustomerNegativeCriterion, +) +from .customer_search_term_insight import ( + CustomerSearchTermInsight, +) +from .customer_sk_ad_network_conversion_value_schema import ( + CustomerSkAdNetworkConversionValueSchema, +) +from .customer_user_access import ( + CustomerUserAccess, +) +from .customer_user_access_invitation import ( + CustomerUserAccessInvitation, +) +from .customizer_attribute import ( + CustomizerAttribute, +) +from .data_link import ( + DataLink, + YoutubeVideoIdentifier, +) +from .detail_content_suitability_placement_view import ( + DetailContentSuitabilityPlacementView, +) +from .detail_placement_view import ( + DetailPlacementView, +) +from .detailed_demographic import ( + DetailedDemographic, +) +from .display_keyword_view import ( + DisplayKeywordView, +) +from .distance_view import ( + DistanceView, +) +from .domain_category import ( + DomainCategory, +) +from .dynamic_search_ads_search_term_view import ( + DynamicSearchAdsSearchTermView, +) +from .expanded_landing_page_view import ( + ExpandedLandingPageView, +) +from .experiment import ( + Experiment, +) +from .experiment_arm import ( + ExperimentArm, +) +from .final_url_expansion_asset_view import ( + FinalUrlExpansionAssetView, +) +from .gender_view import ( + GenderView, +) +from .geo_target_constant import ( + GeoTargetConstant, +) +from .geographic_view import ( + GeographicView, +) +from .goal import ( + Goal, +) +from .google_ads_field import ( + GoogleAdsField, +) +from .group_content_suitability_placement_view import ( + GroupContentSuitabilityPlacementView, +) +from .group_placement_view import ( + GroupPlacementView, +) +from .hotel_group_view import ( + HotelGroupView, +) +from .hotel_performance_view import ( + HotelPerformanceView, +) +from .hotel_reconciliation import ( + HotelReconciliation, +) +from .income_range_view import ( + IncomeRangeView, +) +from .invoice import ( + Invoice, +) +from .keyword_plan import ( + KeywordPlan, + KeywordPlanForecastPeriod, +) +from .keyword_plan_ad_group import ( + KeywordPlanAdGroup, +) +from .keyword_plan_ad_group_keyword import ( + KeywordPlanAdGroupKeyword, +) +from .keyword_plan_campaign import ( + KeywordPlanCampaign, + KeywordPlanGeoTarget, +) +from .keyword_plan_campaign_keyword import ( + KeywordPlanCampaignKeyword, +) +from .keyword_theme_constant import ( + KeywordThemeConstant, +) +from .keyword_view import ( + KeywordView, +) +from .label import ( + Label, +) +from .landing_page_view import ( + LandingPageView, +) +from .language_constant import ( + LanguageConstant, +) +from .lead_form_submission_data import ( + CustomLeadFormSubmissionField, + LeadFormSubmissionData, + LeadFormSubmissionField, +) +from .life_event import ( + LifeEvent, +) +from .local_services_employee import ( + Fellowship, + LocalServicesEmployee, + Residency, + UniversityDegree, +) +from .local_services_lead import ( + ContactDetails, + CreditDetails, + LocalServicesLead, + Note, +) +from .local_services_lead_conversation import ( + LocalServicesLeadConversation, + MessageDetails, + PhoneCallDetails, +) +from .local_services_verification_artifact import ( + BackgroundCheckVerificationArtifact, + BusinessRegistrationCheckVerificationArtifact, + BusinessRegistrationDocument, + BusinessRegistrationNumber, + InsuranceVerificationArtifact, + LicenseVerificationArtifact, + LocalServicesVerificationArtifact, +) +from .location_interest_view import ( + LocationInterestView, +) +from .location_view import ( + LocationView, +) +from .managed_placement_view import ( + ManagedPlacementView, +) +from .matched_location_interest_view import ( + MatchedLocationInterestView, +) +from .media_file import ( + MediaAudio, + MediaBundle, + MediaFile, + MediaImage, + MediaVideo, +) +from .mobile_app_category_constant import ( + MobileAppCategoryConstant, +) +from .mobile_device_constant import ( + MobileDeviceConstant, +) +from .offline_conversion_upload_client_summary import ( + OfflineConversionAlert, + OfflineConversionError, + OfflineConversionSummary, + OfflineConversionUploadClientSummary, +) +from .offline_conversion_upload_conversion_action_summary import ( + OfflineConversionUploadConversionActionSummary, +) +from .offline_user_data_job import ( + OfflineUserDataJob, + OfflineUserDataJobMetadata, +) +from .operating_system_version_constant import ( + OperatingSystemVersionConstant, +) +from .paid_organic_search_term_view import ( + PaidOrganicSearchTermView, +) +from .parental_status_view import ( + ParentalStatusView, +) +from .payments_account import ( + PaymentsAccount, +) +from .per_store_view import ( + PerStoreView, +) +from .performance_max_placement_view import ( + PerformanceMaxPlacementView, +) +from .product_category_constant import ( + ProductCategoryConstant, +) +from .product_group_view import ( + ProductGroupView, +) +from .product_link import ( + AdvertisingPartnerIdentifier, + AdvertisingPartnerProperties, + DataPartnerIdentifier, + GoogleAdsIdentifier, + MerchantCenterIdentifier, + ProductLink, +) +from .product_link_invitation import ( + AdvertisingPartnerLinkInvitationIdentifier, + AdvertisingPartnerLinkInvitationProperties, + HotelCenterLinkInvitationIdentifier, + MerchantCenterLinkInvitationIdentifier, + ProductLinkInvitation, +) +from .qualifying_question import ( + QualifyingQuestion, +) +from .recommendation import ( + Recommendation, +) +from .recommendation_subscription import ( + RecommendationSubscription, +) +from .remarketing_action import ( + RemarketingAction, +) +from .search_term_view import ( + SearchTermView, +) +from .shared_criterion import ( + SharedCriterion, +) +from .shared_set import ( + SharedSet, +) +from .shopping_performance_view import ( + ShoppingPerformanceView, +) +from .shopping_product import ( + ShoppingProduct, +) +from .smart_campaign_search_term_view import ( + SmartCampaignSearchTermView, +) +from .smart_campaign_setting import ( + SmartCampaignSetting, +) +from .targeting_expansion_view import ( + TargetingExpansionView, +) +from .third_party_app_analytics_link import ( + ThirdPartyAppAnalyticsLink, +) +from .topic_constant import ( + TopicConstant, +) +from .topic_view import ( + TopicView, +) +from .travel_activity_group_view import ( + TravelActivityGroupView, +) +from .travel_activity_performance_view import ( + TravelActivityPerformanceView, +) +from .user_interest import ( + UserInterest, +) +from .user_list import ( + UserList, +) +from .user_list_customer_type import ( + UserListCustomerType, +) +from .user_location_view import ( + UserLocationView, +) +from .video import ( + Video, +) +from .video_enhancement import ( + VideoEnhancement, +) +from .webpage_view import ( + WebpageView, +) +from .youtube_video_upload import ( + YouTubeVideoUpload, +) + +__all__ = ( + "AccessibleBiddingStrategy", + "AccountBudget", + "AccountBudgetProposal", + "AccountLink", + "ThirdPartyAppAnalyticsLinkIdentifier", + "Ad", + "AdGroup", + "AdGroupAd", + "AdGroupAdAssetAutomationSetting", + "AdGroupAdPolicySummary", + "AdGroupAdAssetCombinationView", + "AdGroupAdAssetPolicySummary", + "AdGroupAdAssetView", + "AdGroupAdLabel", + "AdGroupAsset", + "AdGroupAssetSet", + "AdGroupAudienceView", + "AdGroupBidModifier", + "AdGroupCriterion", + "AdGroupCriterionCustomizer", + "AdGroupCriterionLabel", + "AdGroupCriterionSimulation", + "AdGroupCustomizer", + "AdGroupLabel", + "AdGroupSimulation", + "AdParameter", + "AdScheduleView", + "AgeRangeView", + "AiMaxSearchTermAdCombinationView", + "AndroidPrivacySharedKeyGoogleAdGroup", + "AndroidPrivacySharedKeyGoogleCampaign", + "AndroidPrivacySharedKeyGoogleNetworkType", + "AdGroupCreativeAssetCombinationData", + "AppTopCombinationView", + "AppliedIncentive", + "Asset", + "AssetFieldTypePolicySummary", + "AssetPolicySummary", + "AssetFieldTypeView", + "AdStrengthActionItem", + "AssetCoverage", + "AssetGroup", + "AssetGroupAsset", + "AssetGroupListingGroupFilter", + "ListingGroupFilterDimension", + "ListingGroupFilterDimensionPath", + "AssetGroupProductGroupView", + "AssetGroupSignal", + "AssetGroupAssetCombinationData", + "AssetGroupTopCombinationView", + "AssetSet", + "AssetSetAsset", + "AssetSetTypeView", + "Audience", + "BatchJob", + "BiddingDataExclusion", + "BiddingSeasonalityAdjustment", + "BiddingStrategy", + "BiddingStrategySimulation", + "BillingSetup", + "CallView", + "Campaign", + "CampaignAggregateAssetView", + "CampaignAsset", + "CampaignAssetSet", + "CampaignAudienceView", + "CampaignBidModifier", + "CampaignBudget", + "CampaignConversionGoal", + "CampaignCriterion", + "CampaignCustomizer", + "CampaignDraft", + "CampaignGoalConfig", + "CampaignGroup", + "CampaignLabel", + "CampaignLifecycleGoal", + "CustomerAcquisitionGoalSettings", + "CampaignSearchTermInsight", + "CampaignSearchTermView", + "CampaignSharedSet", + "CampaignSimulation", + "CarrierConstant", + "CartDataSalesView", + "ChangeEvent", + "ChangeStatus", + "ChannelAggregateAssetView", + "ClickView", + "CombinedAudience", + "ContentCriterionView", + "ConversionAction", + "ConversionCustomVariable", + "ConversionGoalCampaignConfig", + "ConversionValueRule", + "ConversionValueRuleSet", + "CurrencyConstant", + "CustomAudience", + "CustomAudienceMember", + "CustomConversionGoal", + "CustomInterest", + "CustomInterestMember", + "CallReportingSetting", + "ConversionTrackingSetting", + "Customer", + "CustomerAgreementSetting", + "GranularInsuranceStatus", + "GranularLicenseStatus", + "LocalServicesSettings", + "RemarketingSetting", + "VideoCustomer", + "CustomerAsset", + "CustomerAssetSet", + "CustomerClient", + "CustomerClientLink", + "CustomerConversionGoal", + "CustomerCustomizer", + "CustomerLabel", + "CustomerLifecycleGoal", + "CustomerManagerLink", + "CustomerNegativeCriterion", + "CustomerSearchTermInsight", + "CustomerSkAdNetworkConversionValueSchema", + "CustomerUserAccess", + "CustomerUserAccessInvitation", + "CustomizerAttribute", + "DataLink", + "YoutubeVideoIdentifier", + "DetailContentSuitabilityPlacementView", + "DetailPlacementView", + "DetailedDemographic", + "DisplayKeywordView", + "DistanceView", + "DomainCategory", + "DynamicSearchAdsSearchTermView", + "ExpandedLandingPageView", + "Experiment", + "ExperimentArm", + "FinalUrlExpansionAssetView", + "GenderView", + "GeoTargetConstant", + "GeographicView", + "Goal", + "GoogleAdsField", + "GroupContentSuitabilityPlacementView", + "GroupPlacementView", + "HotelGroupView", + "HotelPerformanceView", + "HotelReconciliation", + "IncomeRangeView", + "Invoice", + "KeywordPlan", + "KeywordPlanForecastPeriod", + "KeywordPlanAdGroup", + "KeywordPlanAdGroupKeyword", + "KeywordPlanCampaign", + "KeywordPlanGeoTarget", + "KeywordPlanCampaignKeyword", + "KeywordThemeConstant", + "KeywordView", + "Label", + "LandingPageView", + "LanguageConstant", + "CustomLeadFormSubmissionField", + "LeadFormSubmissionData", + "LeadFormSubmissionField", + "LifeEvent", + "Fellowship", + "LocalServicesEmployee", + "Residency", + "UniversityDegree", + "ContactDetails", + "CreditDetails", + "LocalServicesLead", + "Note", + "LocalServicesLeadConversation", + "MessageDetails", + "PhoneCallDetails", + "BackgroundCheckVerificationArtifact", + "BusinessRegistrationCheckVerificationArtifact", + "BusinessRegistrationDocument", + "BusinessRegistrationNumber", + "InsuranceVerificationArtifact", + "LicenseVerificationArtifact", + "LocalServicesVerificationArtifact", + "LocationInterestView", + "LocationView", + "ManagedPlacementView", + "MatchedLocationInterestView", + "MediaAudio", + "MediaBundle", + "MediaFile", + "MediaImage", + "MediaVideo", + "MobileAppCategoryConstant", + "MobileDeviceConstant", + "OfflineConversionAlert", + "OfflineConversionError", + "OfflineConversionSummary", + "OfflineConversionUploadClientSummary", + "OfflineConversionUploadConversionActionSummary", + "OfflineUserDataJob", + "OfflineUserDataJobMetadata", + "OperatingSystemVersionConstant", + "PaidOrganicSearchTermView", + "ParentalStatusView", + "PaymentsAccount", + "PerStoreView", + "PerformanceMaxPlacementView", + "ProductCategoryConstant", + "ProductGroupView", + "AdvertisingPartnerIdentifier", + "AdvertisingPartnerProperties", + "DataPartnerIdentifier", + "GoogleAdsIdentifier", + "MerchantCenterIdentifier", + "ProductLink", + "AdvertisingPartnerLinkInvitationIdentifier", + "AdvertisingPartnerLinkInvitationProperties", + "HotelCenterLinkInvitationIdentifier", + "MerchantCenterLinkInvitationIdentifier", + "ProductLinkInvitation", + "QualifyingQuestion", + "Recommendation", + "RecommendationSubscription", + "RemarketingAction", + "SearchTermView", + "SharedCriterion", + "SharedSet", + "ShoppingPerformanceView", + "ShoppingProduct", + "SmartCampaignSearchTermView", + "SmartCampaignSetting", + "TargetingExpansionView", + "ThirdPartyAppAnalyticsLink", + "TopicConstant", + "TopicView", + "TravelActivityGroupView", + "TravelActivityPerformanceView", + "UserInterest", + "UserList", + "UserListCustomerType", + "UserLocationView", + "Video", + "VideoEnhancement", + "WebpageView", + "YouTubeVideoUpload", +) diff --git a/google/ads/googleads/v24/resources/types/accessible_bidding_strategy.py b/google/ads/googleads/v24/resources/types/accessible_bidding_strategy.py new file mode 100644 index 000000000..b73e24c22 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/accessible_bidding_strategy.py @@ -0,0 +1,344 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import bidding_strategy_type +from google.ads.googleads.v24.enums.types import ( + target_impression_share_location, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AccessibleBiddingStrategy", + }, +) + + +class AccessibleBiddingStrategy(proto.Message): + r"""Represents a view of BiddingStrategies owned by and shared + with the customer. + In contrast to BiddingStrategy, this resource includes + strategies owned by managers of the customer and shared with + this customer - in addition to strategies owned by this + customer. This resource does not provide metrics and only + exposes a limited subset of the BiddingStrategy attributes. + + 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: + resource_name (str): + Output only. The resource name of the accessible bidding + strategy. AccessibleBiddingStrategy resource names have the + form: + + ``customers/{customer_id}/accessibleBiddingStrategies/{bidding_strategy_id}`` + id (int): + Output only. The ID of the bidding strategy. + name (str): + Output only. The name of the bidding + strategy. + type_ (google.ads.googleads.v24.enums.types.BiddingStrategyTypeEnum.BiddingStrategyType): + Output only. The type of the bidding + strategy. + owner_customer_id (int): + Output only. The ID of the Customer which + owns the bidding strategy. + owner_descriptive_name (str): + Output only. descriptive_name of the Customer which owns the + bidding strategy. + maximize_conversion_value (google.ads.googleads.v24.resources.types.AccessibleBiddingStrategy.MaximizeConversionValue): + Output only. An automated bidding strategy to + help get the most conversion value for your + campaigns while spending your budget. + + This field is a member of `oneof`_ ``scheme``. + maximize_conversions (google.ads.googleads.v24.resources.types.AccessibleBiddingStrategy.MaximizeConversions): + Output only. An automated bidding strategy to + help get the most conversions for your campaigns + while spending your budget. + + This field is a member of `oneof`_ ``scheme``. + target_cpa (google.ads.googleads.v24.resources.types.AccessibleBiddingStrategy.TargetCpa): + Output only. A bidding strategy that sets + bids to help get as many conversions as possible + at the target cost-per-acquisition (CPA) you + set. + + This field is a member of `oneof`_ ``scheme``. + target_impression_share (google.ads.googleads.v24.resources.types.AccessibleBiddingStrategy.TargetImpressionShare): + Output only. A bidding strategy that + automatically optimizes towards a chosen + percentage of impressions. + + This field is a member of `oneof`_ ``scheme``. + target_roas (google.ads.googleads.v24.resources.types.AccessibleBiddingStrategy.TargetRoas): + Output only. A bidding strategy that helps + you maximize revenue while averaging a specific + target Return On Ad Spend (ROAS). + + This field is a member of `oneof`_ ``scheme``. + target_spend (google.ads.googleads.v24.resources.types.AccessibleBiddingStrategy.TargetSpend): + Output only. A bid strategy that sets your + bids to help get as many clicks as possible + within your budget. + + This field is a member of `oneof`_ ``scheme``. + """ + + class MaximizeConversionValue(proto.Message): + r"""An automated bidding strategy to help get the most conversion + value for your campaigns while spending your budget. + + Attributes: + target_roas (float): + Output only. The target return on ad spend + (ROAS) option. If set, the bid strategy will + maximize revenue while averaging the target + return on ad spend. If the target ROAS is high, + the bid strategy may not be able to spend the + full budget. If the target ROAS is not set, the + bid strategy will aim to achieve the highest + possible ROAS for the budget. + """ + + target_roas: float = proto.Field( + proto.DOUBLE, + number=1, + ) + + class MaximizeConversions(proto.Message): + r"""An automated bidding strategy to help get the most + conversions for your campaigns while spending your budget. + + Attributes: + target_cpa_micros (int): + Output only. The target cost per acquisition + (CPA) option. This is the average amount that + you would like to spend per acquisition. + """ + + target_cpa_micros: int = proto.Field( + proto.INT64, + number=2, + ) + + class TargetCpa(proto.Message): + r"""An automated bid strategy that sets bids to help get as many + conversions as possible at the target cost-per-acquisition (CPA) + you set. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_cpa_micros (int): + Output only. Average CPA target. + This target should be greater than or equal to + minimum billable unit based on the currency for + the account. + + This field is a member of `oneof`_ ``_target_cpa_micros``. + """ + + target_cpa_micros: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + + class TargetImpressionShare(proto.Message): + r"""An automated bidding strategy that sets bids so that a + certain percentage of search ads are shown at the top of the + first page (or other targeted location). + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + location (google.ads.googleads.v24.enums.types.TargetImpressionShareLocationEnum.TargetImpressionShareLocation): + Output only. The targeted location on the + search results page. + location_fraction_micros (int): + The chosen fraction of ads to be shown in the + targeted location in micros. For example, 1% + equals 10,000. + + This field is a member of `oneof`_ ``_location_fraction_micros``. + cpc_bid_ceiling_micros (int): + Output only. The highest CPC bid the + automated bidding system is permitted to + specify. This is a required field entered by the + advertiser that sets the ceiling and specified + in local micros. + + This field is a member of `oneof`_ ``_cpc_bid_ceiling_micros``. + """ + + location: ( + target_impression_share_location.TargetImpressionShareLocationEnum.TargetImpressionShareLocation + ) = proto.Field( + proto.ENUM, + number=1, + enum=target_impression_share_location.TargetImpressionShareLocationEnum.TargetImpressionShareLocation, + ) + location_fraction_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + cpc_bid_ceiling_micros: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + + class TargetRoas(proto.Message): + r"""An automated bidding strategy that helps you maximize revenue + while averaging a specific target return on ad spend (ROAS). + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_roas (float): + Output only. The chosen revenue (based on + conversion data) per unit of spend. + + This field is a member of `oneof`_ ``_target_roas``. + """ + + target_roas: float = proto.Field( + proto.DOUBLE, + number=1, + optional=True, + ) + + class TargetSpend(proto.Message): + r"""An automated bid strategy that sets your bids to help get as + many clicks as possible within your budget. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_spend_micros (int): + Output only. The spend target under which to + maximize clicks. A TargetSpend bidder will + attempt to spend the smaller of this value or + the natural throttling spend amount. + If not specified, the budget is used as the + spend target. This field is deprecated and + should no longer be used. See + https://ads-developers.googleblog.com/2020/05/reminder-about-sunset-creation-of.html + for details. + + This field is a member of `oneof`_ ``_target_spend_micros``. + cpc_bid_ceiling_micros (int): + Output only. Maximum bid limit that can be + set by the bid strategy. The limit applies to + all keywords managed by the strategy. + + This field is a member of `oneof`_ ``_cpc_bid_ceiling_micros``. + """ + + target_spend_micros: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + cpc_bid_ceiling_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + ) + name: str = proto.Field( + proto.STRING, + number=3, + ) + type_: bidding_strategy_type.BiddingStrategyTypeEnum.BiddingStrategyType = ( + proto.Field( + proto.ENUM, + number=4, + enum=bidding_strategy_type.BiddingStrategyTypeEnum.BiddingStrategyType, + ) + ) + owner_customer_id: int = proto.Field( + proto.INT64, + number=5, + ) + owner_descriptive_name: str = proto.Field( + proto.STRING, + number=6, + ) + maximize_conversion_value: MaximizeConversionValue = proto.Field( + proto.MESSAGE, + number=7, + oneof="scheme", + message=MaximizeConversionValue, + ) + maximize_conversions: MaximizeConversions = proto.Field( + proto.MESSAGE, + number=8, + oneof="scheme", + message=MaximizeConversions, + ) + target_cpa: TargetCpa = proto.Field( + proto.MESSAGE, + number=9, + oneof="scheme", + message=TargetCpa, + ) + target_impression_share: TargetImpressionShare = proto.Field( + proto.MESSAGE, + number=10, + oneof="scheme", + message=TargetImpressionShare, + ) + target_roas: TargetRoas = proto.Field( + proto.MESSAGE, + number=11, + oneof="scheme", + message=TargetRoas, + ) + target_spend: TargetSpend = proto.Field( + proto.MESSAGE, + number=12, + oneof="scheme", + message=TargetSpend, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/account_budget.py b/google/ads/googleads/v24/resources/types/account_budget.py new file mode 100644 index 000000000..9cfd1a19e --- /dev/null +++ b/google/ads/googleads/v24/resources/types/account_budget.py @@ -0,0 +1,465 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import account_budget_proposal_type +from google.ads.googleads.v24.enums.types import account_budget_status +from google.ads.googleads.v24.enums.types import ( + spending_limit_type as gage_spending_limit_type, +) +from google.ads.googleads.v24.enums.types import time_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AccountBudget", + }, +) + + +class AccountBudget(proto.Message): + r"""An account-level budget. It contains information about the budget + itself, as well as the most recently approved changes to the budget + and proposed changes that are pending approval. The proposed changes + that are pending approval, if any, are found in 'pending_proposal'. + Effective details about the budget are found in fields prefixed + 'approved\_', 'adjusted\_' and those without a prefix. Since some + effective details may differ from what the user had originally + requested (for example, spending limit), these differences are + juxtaposed through 'proposed\_', 'approved\_', and possibly + 'adjusted\_' fields. + + This resource is mutated using AccountBudgetProposal and cannot be + mutated directly. A budget may have at most one pending proposal at + any given time. It is read through pending_proposal. + + Once approved, a budget may be subject to adjustments, such as + credit adjustments. Adjustments create differences between the + 'approved' and 'adjusted' fields, which would otherwise be + identical. + + 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: + resource_name (str): + Output only. The resource name of the account-level budget. + AccountBudget resource names have the form: + + ``customers/{customer_id}/accountBudgets/{account_budget_id}`` + id (int): + Output only. The ID of the account-level + budget. + + This field is a member of `oneof`_ ``_id``. + billing_setup (str): + Output only. The resource name of the billing setup + associated with this account-level budget. BillingSetup + resource names have the form: + + ``customers/{customer_id}/billingSetups/{billing_setup_id}`` + + This field is a member of `oneof`_ ``_billing_setup``. + status (google.ads.googleads.v24.enums.types.AccountBudgetStatusEnum.AccountBudgetStatus): + Output only. The status of this account-level + budget. + name (str): + Output only. The name of the account-level + budget. + + This field is a member of `oneof`_ ``_name``. + proposed_start_date_time (str): + Output only. The proposed start time of the + account-level budget in yyyy-MM-dd HH:mm:ss + format. If a start time type of NOW was + proposed, this is the time of request. + + This field is a member of `oneof`_ ``_proposed_start_date_time``. + approved_start_date_time (str): + Output only. The approved start time of the + account-level budget in yyyy-MM-dd HH:mm:ss + format. + + For example, if a new budget is approved after + the proposed start time, the approved start time + is the time of approval. + + This field is a member of `oneof`_ ``_approved_start_date_time``. + total_adjustments_micros (int): + Output only. The total adjustments amount. + + An example of an adjustment is courtesy credits. + amount_served_micros (int): + Output only. The value of Ads that have been served, in + micros. + + This includes overdelivery costs, in which case a credit + might be automatically applied to the budget (see + total_adjustments_micros). + purchase_order_number (str): + Output only. A purchase order number is a + value that helps users reference this budget in + their monthly invoices. + + This field is a member of `oneof`_ ``_purchase_order_number``. + notes (str): + Output only. Notes associated with the + budget. + + This field is a member of `oneof`_ ``_notes``. + pending_proposal (google.ads.googleads.v24.resources.types.AccountBudget.PendingAccountBudgetProposal): + Output only. The pending proposal to modify + this budget, if applicable. + proposed_end_date_time (str): + Output only. The proposed end time in + yyyy-MM-dd HH:mm:ss format. + + This field is a member of `oneof`_ ``proposed_end_time``. + proposed_end_time_type (google.ads.googleads.v24.enums.types.TimeTypeEnum.TimeType): + Output only. The proposed end time as a + well-defined type, for example, FOREVER. + + This field is a member of `oneof`_ ``proposed_end_time``. + approved_end_date_time (str): + Output only. The approved end time in + yyyy-MM-dd HH:mm:ss format. + + This field is a member of `oneof`_ ``approved_end_time``. + approved_end_time_type (google.ads.googleads.v24.enums.types.TimeTypeEnum.TimeType): + Output only. The approved end time as a + well-defined type, for example, FOREVER. + + This field is a member of `oneof`_ ``approved_end_time``. + proposed_spending_limit_micros (int): + Output only. The proposed spending limit in + micros. One million is equivalent to one unit. + + This field is a member of `oneof`_ ``proposed_spending_limit``. + proposed_spending_limit_type (google.ads.googleads.v24.enums.types.SpendingLimitTypeEnum.SpendingLimitType): + Output only. The proposed spending limit as a + well-defined type, for example, INFINITE. + + This field is a member of `oneof`_ ``proposed_spending_limit``. + approved_spending_limit_micros (int): + Output only. The approved spending limit in + micros. One million is equivalent to one unit. + This will only be populated if the proposed + spending limit is finite, and will always be + greater than or equal to the proposed spending + limit. + + This field is a member of `oneof`_ ``approved_spending_limit``. + approved_spending_limit_type (google.ads.googleads.v24.enums.types.SpendingLimitTypeEnum.SpendingLimitType): + Output only. The approved spending limit as a + well-defined type, for example, INFINITE. This + will only be populated if the approved spending + limit is INFINITE. + + This field is a member of `oneof`_ ``approved_spending_limit``. + adjusted_spending_limit_micros (int): + Output only. The adjusted spending limit in + micros. One million is equivalent to one unit. + + If the approved spending limit is finite, the + adjusted spending limit may vary depending on + the types of adjustments applied to this budget, + if applicable. + + The different kinds of adjustments are described + here: + + https://support.google.com/google-ads/answer/1704323 + + For example, a debit adjustment reduces how much + the account is allowed to spend. + + This field is a member of `oneof`_ ``adjusted_spending_limit``. + adjusted_spending_limit_type (google.ads.googleads.v24.enums.types.SpendingLimitTypeEnum.SpendingLimitType): + Output only. The adjusted spending limit as a + well-defined type, for example, INFINITE. This + will only be populated if the adjusted spending + limit is INFINITE, which is guaranteed to be + true if the approved spending limit is INFINITE. + + This field is a member of `oneof`_ ``adjusted_spending_limit``. + """ + + class PendingAccountBudgetProposal(proto.Message): + r"""A pending proposal associated with the enclosing + account-level budget, if applicable. + + 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: + account_budget_proposal (str): + Output only. The resource name of the proposal. + AccountBudgetProposal resource names have the form: + + ``customers/{customer_id}/accountBudgetProposals/{account_budget_proposal_id}`` + + This field is a member of `oneof`_ ``_account_budget_proposal``. + proposal_type (google.ads.googleads.v24.enums.types.AccountBudgetProposalTypeEnum.AccountBudgetProposalType): + Output only. The type of this proposal, for + example, END to end the budget associated with + this proposal. + name (str): + Output only. The name to assign to the + account-level budget. + + This field is a member of `oneof`_ ``_name``. + start_date_time (str): + Output only. The start time in yyyy-MM-dd + HH:mm:ss format. + + This field is a member of `oneof`_ ``_start_date_time``. + purchase_order_number (str): + Output only. A purchase order number is a + value that helps users reference this budget in + their monthly invoices. + + This field is a member of `oneof`_ ``_purchase_order_number``. + notes (str): + Output only. Notes associated with this + budget. + + This field is a member of `oneof`_ ``_notes``. + creation_date_time (str): + Output only. The time when this account-level + budget proposal was created. Formatted as + yyyy-MM-dd HH:mm:ss. + + This field is a member of `oneof`_ ``_creation_date_time``. + end_date_time (str): + Output only. The end time in yyyy-MM-dd + HH:mm:ss format. + + This field is a member of `oneof`_ ``end_time``. + end_time_type (google.ads.googleads.v24.enums.types.TimeTypeEnum.TimeType): + Output only. The end time as a well-defined + type, for example, FOREVER. + + This field is a member of `oneof`_ ``end_time``. + spending_limit_micros (int): + Output only. The spending limit in micros. + One million is equivalent to one unit. + + This field is a member of `oneof`_ ``spending_limit``. + spending_limit_type (google.ads.googleads.v24.enums.types.SpendingLimitTypeEnum.SpendingLimitType): + Output only. The spending limit as a + well-defined type, for example, INFINITE. + + This field is a member of `oneof`_ ``spending_limit``. + """ + + account_budget_proposal: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + proposal_type: ( + account_budget_proposal_type.AccountBudgetProposalTypeEnum.AccountBudgetProposalType + ) = proto.Field( + proto.ENUM, + number=2, + enum=account_budget_proposal_type.AccountBudgetProposalTypeEnum.AccountBudgetProposalType, + ) + name: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + start_date_time: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + purchase_order_number: str = proto.Field( + proto.STRING, + number=17, + optional=True, + ) + notes: str = proto.Field( + proto.STRING, + number=18, + optional=True, + ) + creation_date_time: str = proto.Field( + proto.STRING, + number=19, + optional=True, + ) + end_date_time: str = proto.Field( + proto.STRING, + number=15, + oneof="end_time", + ) + end_time_type: time_type.TimeTypeEnum.TimeType = proto.Field( + proto.ENUM, + number=6, + oneof="end_time", + enum=time_type.TimeTypeEnum.TimeType, + ) + spending_limit_micros: int = proto.Field( + proto.INT64, + number=16, + oneof="spending_limit", + ) + spending_limit_type: ( + gage_spending_limit_type.SpendingLimitTypeEnum.SpendingLimitType + ) = proto.Field( + proto.ENUM, + number=8, + oneof="spending_limit", + enum=gage_spending_limit_type.SpendingLimitTypeEnum.SpendingLimitType, + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=23, + optional=True, + ) + billing_setup: str = proto.Field( + proto.STRING, + number=24, + optional=True, + ) + status: ( + account_budget_status.AccountBudgetStatusEnum.AccountBudgetStatus + ) = proto.Field( + proto.ENUM, + number=4, + enum=account_budget_status.AccountBudgetStatusEnum.AccountBudgetStatus, + ) + name: str = proto.Field( + proto.STRING, + number=25, + optional=True, + ) + proposed_start_date_time: str = proto.Field( + proto.STRING, + number=26, + optional=True, + ) + approved_start_date_time: str = proto.Field( + proto.STRING, + number=27, + optional=True, + ) + total_adjustments_micros: int = proto.Field( + proto.INT64, + number=33, + ) + amount_served_micros: int = proto.Field( + proto.INT64, + number=34, + ) + purchase_order_number: str = proto.Field( + proto.STRING, + number=35, + optional=True, + ) + notes: str = proto.Field( + proto.STRING, + number=36, + optional=True, + ) + pending_proposal: PendingAccountBudgetProposal = proto.Field( + proto.MESSAGE, + number=22, + message=PendingAccountBudgetProposal, + ) + proposed_end_date_time: str = proto.Field( + proto.STRING, + number=28, + oneof="proposed_end_time", + ) + proposed_end_time_type: time_type.TimeTypeEnum.TimeType = proto.Field( + proto.ENUM, + number=9, + oneof="proposed_end_time", + enum=time_type.TimeTypeEnum.TimeType, + ) + approved_end_date_time: str = proto.Field( + proto.STRING, + number=29, + oneof="approved_end_time", + ) + approved_end_time_type: time_type.TimeTypeEnum.TimeType = proto.Field( + proto.ENUM, + number=11, + oneof="approved_end_time", + enum=time_type.TimeTypeEnum.TimeType, + ) + proposed_spending_limit_micros: int = proto.Field( + proto.INT64, + number=30, + oneof="proposed_spending_limit", + ) + proposed_spending_limit_type: ( + gage_spending_limit_type.SpendingLimitTypeEnum.SpendingLimitType + ) = proto.Field( + proto.ENUM, + number=13, + oneof="proposed_spending_limit", + enum=gage_spending_limit_type.SpendingLimitTypeEnum.SpendingLimitType, + ) + approved_spending_limit_micros: int = proto.Field( + proto.INT64, + number=31, + oneof="approved_spending_limit", + ) + approved_spending_limit_type: ( + gage_spending_limit_type.SpendingLimitTypeEnum.SpendingLimitType + ) = proto.Field( + proto.ENUM, + number=15, + oneof="approved_spending_limit", + enum=gage_spending_limit_type.SpendingLimitTypeEnum.SpendingLimitType, + ) + adjusted_spending_limit_micros: int = proto.Field( + proto.INT64, + number=32, + oneof="adjusted_spending_limit", + ) + adjusted_spending_limit_type: ( + gage_spending_limit_type.SpendingLimitTypeEnum.SpendingLimitType + ) = proto.Field( + proto.ENUM, + number=17, + oneof="adjusted_spending_limit", + enum=gage_spending_limit_type.SpendingLimitTypeEnum.SpendingLimitType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/account_budget_proposal.py b/google/ads/googleads/v24/resources/types/account_budget_proposal.py new file mode 100644 index 000000000..f84f15242 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/account_budget_proposal.py @@ -0,0 +1,292 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import account_budget_proposal_status +from google.ads.googleads.v24.enums.types import account_budget_proposal_type +from google.ads.googleads.v24.enums.types import spending_limit_type +from google.ads.googleads.v24.enums.types import time_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AccountBudgetProposal", + }, +) + + +class AccountBudgetProposal(proto.Message): + r"""An account-level budget proposal. + + All fields prefixed with 'proposed' may not necessarily be applied + directly. For example, proposed spending limits may be adjusted + before their application. This is true if the 'proposed' field has + an 'approved' counterpart, for example, spending limits. + + Note that the proposal type (proposal_type) changes which fields are + required and which must remain empty. + + 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: + resource_name (str): + Immutable. The resource name of the proposal. + AccountBudgetProposal resource names have the form: + + ``customers/{customer_id}/accountBudgetProposals/{account_budget_proposal_id}`` + id (int): + Output only. The ID of the proposal. + + This field is a member of `oneof`_ ``_id``. + billing_setup (str): + Immutable. The resource name of the billing + setup associated with this proposal. + + This field is a member of `oneof`_ ``_billing_setup``. + account_budget (str): + Immutable. The resource name of the + account-level budget associated with this + proposal. + + This field is a member of `oneof`_ ``_account_budget``. + proposal_type (google.ads.googleads.v24.enums.types.AccountBudgetProposalTypeEnum.AccountBudgetProposalType): + Immutable. The type of this proposal, for + example, END to end the budget associated with + this proposal. + status (google.ads.googleads.v24.enums.types.AccountBudgetProposalStatusEnum.AccountBudgetProposalStatus): + Output only. The status of this proposal. + When a new proposal is created, the status + defaults to PENDING. + proposed_name (str): + Immutable. The name to assign to the + account-level budget. + + This field is a member of `oneof`_ ``_proposed_name``. + approved_start_date_time (str): + Output only. The approved start date time in + yyyy-mm-dd hh:mm:ss format. + + This field is a member of `oneof`_ ``_approved_start_date_time``. + proposed_purchase_order_number (str): + Immutable. A purchase order number is a value + that enables the user to help them reference + this budget in their monthly invoices. + + This field is a member of `oneof`_ ``_proposed_purchase_order_number``. + proposed_notes (str): + Immutable. Notes associated with this budget. + + This field is a member of `oneof`_ ``_proposed_notes``. + creation_date_time (str): + Output only. The date time when this + account-level budget proposal was created, which + is not the same as its approval date time, if + applicable. + + This field is a member of `oneof`_ ``_creation_date_time``. + approval_date_time (str): + Output only. The date time when this + account-level budget was approved, if + applicable. + + This field is a member of `oneof`_ ``_approval_date_time``. + proposed_start_date_time (str): + Immutable. The proposed start date time in + yyyy-mm-dd hh:mm:ss format. + + This field is a member of `oneof`_ ``proposed_start_time``. + proposed_start_time_type (google.ads.googleads.v24.enums.types.TimeTypeEnum.TimeType): + Immutable. The proposed start date time as a + well-defined type, for example, NOW. + + This field is a member of `oneof`_ ``proposed_start_time``. + proposed_end_date_time (str): + Immutable. The proposed end date time in + yyyy-mm-dd hh:mm:ss format. + + This field is a member of `oneof`_ ``proposed_end_time``. + proposed_end_time_type (google.ads.googleads.v24.enums.types.TimeTypeEnum.TimeType): + Immutable. The proposed end date time as a + well-defined type, for example, FOREVER. + + This field is a member of `oneof`_ ``proposed_end_time``. + approved_end_date_time (str): + Output only. The approved end date time in + yyyy-mm-dd hh:mm:ss format. + + This field is a member of `oneof`_ ``approved_end_time``. + approved_end_time_type (google.ads.googleads.v24.enums.types.TimeTypeEnum.TimeType): + Output only. The approved end date time as a + well-defined type, for example, FOREVER. + + This field is a member of `oneof`_ ``approved_end_time``. + proposed_spending_limit_micros (int): + Immutable. The proposed spending limit in + micros. One million is equivalent to one unit. + + This field is a member of `oneof`_ ``proposed_spending_limit``. + proposed_spending_limit_type (google.ads.googleads.v24.enums.types.SpendingLimitTypeEnum.SpendingLimitType): + Immutable. The proposed spending limit as a + well-defined type, for example, INFINITE. + + This field is a member of `oneof`_ ``proposed_spending_limit``. + approved_spending_limit_micros (int): + Output only. The approved spending limit in + micros. One million is equivalent to one unit. + + This field is a member of `oneof`_ ``approved_spending_limit``. + approved_spending_limit_type (google.ads.googleads.v24.enums.types.SpendingLimitTypeEnum.SpendingLimitType): + Output only. The approved spending limit as a + well-defined type, for example, INFINITE. + + This field is a member of `oneof`_ ``approved_spending_limit``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=25, + optional=True, + ) + billing_setup: str = proto.Field( + proto.STRING, + number=26, + optional=True, + ) + account_budget: str = proto.Field( + proto.STRING, + number=27, + optional=True, + ) + proposal_type: ( + account_budget_proposal_type.AccountBudgetProposalTypeEnum.AccountBudgetProposalType + ) = proto.Field( + proto.ENUM, + number=4, + enum=account_budget_proposal_type.AccountBudgetProposalTypeEnum.AccountBudgetProposalType, + ) + status: ( + account_budget_proposal_status.AccountBudgetProposalStatusEnum.AccountBudgetProposalStatus + ) = proto.Field( + proto.ENUM, + number=15, + enum=account_budget_proposal_status.AccountBudgetProposalStatusEnum.AccountBudgetProposalStatus, + ) + proposed_name: str = proto.Field( + proto.STRING, + number=28, + optional=True, + ) + approved_start_date_time: str = proto.Field( + proto.STRING, + number=30, + optional=True, + ) + proposed_purchase_order_number: str = proto.Field( + proto.STRING, + number=35, + optional=True, + ) + proposed_notes: str = proto.Field( + proto.STRING, + number=36, + optional=True, + ) + creation_date_time: str = proto.Field( + proto.STRING, + number=37, + optional=True, + ) + approval_date_time: str = proto.Field( + proto.STRING, + number=38, + optional=True, + ) + proposed_start_date_time: str = proto.Field( + proto.STRING, + number=29, + oneof="proposed_start_time", + ) + proposed_start_time_type: time_type.TimeTypeEnum.TimeType = proto.Field( + proto.ENUM, + number=7, + oneof="proposed_start_time", + enum=time_type.TimeTypeEnum.TimeType, + ) + proposed_end_date_time: str = proto.Field( + proto.STRING, + number=31, + oneof="proposed_end_time", + ) + proposed_end_time_type: time_type.TimeTypeEnum.TimeType = proto.Field( + proto.ENUM, + number=9, + oneof="proposed_end_time", + enum=time_type.TimeTypeEnum.TimeType, + ) + approved_end_date_time: str = proto.Field( + proto.STRING, + number=32, + oneof="approved_end_time", + ) + approved_end_time_type: time_type.TimeTypeEnum.TimeType = proto.Field( + proto.ENUM, + number=22, + oneof="approved_end_time", + enum=time_type.TimeTypeEnum.TimeType, + ) + proposed_spending_limit_micros: int = proto.Field( + proto.INT64, + number=33, + oneof="proposed_spending_limit", + ) + proposed_spending_limit_type: ( + spending_limit_type.SpendingLimitTypeEnum.SpendingLimitType + ) = proto.Field( + proto.ENUM, + number=11, + oneof="proposed_spending_limit", + enum=spending_limit_type.SpendingLimitTypeEnum.SpendingLimitType, + ) + approved_spending_limit_micros: int = proto.Field( + proto.INT64, + number=34, + oneof="approved_spending_limit", + ) + approved_spending_limit_type: ( + spending_limit_type.SpendingLimitTypeEnum.SpendingLimitType + ) = proto.Field( + proto.ENUM, + number=24, + oneof="approved_spending_limit", + enum=spending_limit_type.SpendingLimitTypeEnum.SpendingLimitType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/account_link.py b/google/ads/googleads/v24/resources/types/account_link.py new file mode 100644 index 000000000..41002b2d4 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/account_link.py @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import account_link_status +from google.ads.googleads.v24.enums.types import linked_account_type +from google.ads.googleads.v24.enums.types import mobile_app_vendor + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AccountLink", + "ThirdPartyAppAnalyticsLinkIdentifier", + }, +) + + +class AccountLink(proto.Message): + r"""Represents the data sharing connection between a Google Ads + account and another account + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. Resource name of the account link. AccountLink + resource names have the form: + ``customers/{customer_id}/accountLinks/{account_link_id}`` + account_link_id (int): + Output only. The ID of the link. + This field is read only. + + This field is a member of `oneof`_ ``_account_link_id``. + status (google.ads.googleads.v24.enums.types.AccountLinkStatusEnum.AccountLinkStatus): + The status of the link. + type_ (google.ads.googleads.v24.enums.types.LinkedAccountTypeEnum.LinkedAccountType): + Output only. The type of the linked account. + third_party_app_analytics (google.ads.googleads.v24.resources.types.ThirdPartyAppAnalyticsLinkIdentifier): + Immutable. A third party app analytics link. + + This field is a member of `oneof`_ ``linked_account``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + account_link_id: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + status: account_link_status.AccountLinkStatusEnum.AccountLinkStatus = ( + proto.Field( + proto.ENUM, + number=3, + enum=account_link_status.AccountLinkStatusEnum.AccountLinkStatus, + ) + ) + type_: linked_account_type.LinkedAccountTypeEnum.LinkedAccountType = ( + proto.Field( + proto.ENUM, + number=4, + enum=linked_account_type.LinkedAccountTypeEnum.LinkedAccountType, + ) + ) + third_party_app_analytics: "ThirdPartyAppAnalyticsLinkIdentifier" = ( + proto.Field( + proto.MESSAGE, + number=5, + oneof="linked_account", + message="ThirdPartyAppAnalyticsLinkIdentifier", + ) + ) + + +class ThirdPartyAppAnalyticsLinkIdentifier(proto.Message): + r"""The identifiers of a Third Party App Analytics Link. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + app_analytics_provider_id (int): + Immutable. The ID of the app analytics + provider. This field should not be empty when + creating a new third party app analytics link. + It is unable to be modified after the creation + of the link. + + This field is a member of `oneof`_ ``_app_analytics_provider_id``. + app_id (str): + Immutable. A string that uniquely identifies + a mobile application from which the data was + collected to the Google Ads API. For iOS, the ID + string is the 9 digit string that appears at the + end of an App Store URL (for example, + "422689480" for "Gmail" whose App Store link is + https://apps.apple.com/us/app/gmail-email-by-google/id422689480). + For Android, the ID string is the application's + package name (for example, + "com.google.android.gm" for "Gmail" given Google + Play link + https://play.google.com/store/apps/details?id=com.google.android.gm) + This field should not be empty when creating a + new third party app analytics link. It is unable + to be modified after the creation of the link. + + This field is a member of `oneof`_ ``_app_id``. + app_vendor (google.ads.googleads.v24.enums.types.MobileAppVendorEnum.MobileAppVendor): + Immutable. The vendor of the app. + This field should not be empty when creating a + new third party app analytics link. It is unable + to be modified after the creation of the link. + """ + + app_analytics_provider_id: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + app_id: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + app_vendor: mobile_app_vendor.MobileAppVendorEnum.MobileAppVendor = ( + proto.Field( + proto.ENUM, + number=3, + enum=mobile_app_vendor.MobileAppVendorEnum.MobileAppVendor, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad.py b/google/ads/googleads/v24/resources/types/ad.py new file mode 100644 index 000000000..6a1a3d8ee --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad.py @@ -0,0 +1,489 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import ad_type_infos +from google.ads.googleads.v24.common.types import custom_parameter +from google.ads.googleads.v24.common.types import final_app_url +from google.ads.googleads.v24.common.types import url_collection +from google.ads.googleads.v24.enums.types import ad_type +from google.ads.googleads.v24.enums.types import device +from google.ads.googleads.v24.enums.types import system_managed_entity_source + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "Ad", + }, +) + + +class Ad(proto.Message): + r"""An ad. + + 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: + resource_name (str): + Immutable. The resource name of the ad. Ad resource names + have the form: + + ``customers/{customer_id}/ads/{ad_id}`` + id (int): + Output only. The ID of the ad. + + This field is a member of `oneof`_ ``_id``. + final_urls (MutableSequence[str]): + The list of possible final URLs after all + cross-domain redirects for the ad. + final_app_urls (MutableSequence[google.ads.googleads.v24.common.types.FinalAppUrl]): + A list of final app URLs that will be used on + mobile if the user has the specific app + installed. + final_mobile_urls (MutableSequence[str]): + The list of possible final mobile URLs after + all cross-domain redirects for the ad. + tracking_url_template (str): + The URL template for constructing a tracking + URL. + + This field is a member of `oneof`_ ``_tracking_url_template``. + final_url_suffix (str): + The suffix to use when constructing a final + URL. + + This field is a member of `oneof`_ ``_final_url_suffix``. + url_custom_parameters (MutableSequence[google.ads.googleads.v24.common.types.CustomParameter]): + The list of mappings that can be used to substitute custom + parameter tags in a ``tracking_url_template``, + ``final_urls``, or ``mobile_final_urls``. For mutates, use + url custom parameter operations. + display_url (str): + The URL that appears in the ad description + for some ad formats. + + This field is a member of `oneof`_ ``_display_url``. + type_ (google.ads.googleads.v24.enums.types.AdTypeEnum.AdType): + Output only. The type of ad. + added_by_google_ads (bool): + Output only. Indicates if this ad was + automatically added by Google Ads and not by a + user. For example, this could happen when ads + are automatically created as suggestions for new + ads based on knowledge of how existing ads are + performing. + + This field is a member of `oneof`_ ``_added_by_google_ads``. + device_preference (google.ads.googleads.v24.enums.types.DeviceEnum.Device): + The device preference for the ad. You can + only specify a preference for mobile devices. + When this preference is set the ad will be + preferred over other ads when being displayed on + a mobile device. The ad can still be displayed + on other device types, for example, if no other + ads are available. If unspecified (no device + preference), all devices are targeted. This is + only supported by some ad types. + url_collections (MutableSequence[google.ads.googleads.v24.common.types.UrlCollection]): + Additional URLs for the ad that are tagged + with a unique identifier that can be referenced + from other fields in the ad. + name (str): + Immutable. The name of the ad. This is only + used to be able to identify the ad. It does not + need to be unique and does not affect the served + ad. The name field is currently only supported + for DisplayUploadAd, ImageAd, + LegacyAppInstallAd, ShoppingComparisonListingAd, + VideoAd, VideoResponsiveAd and DemandGen ads. + + This field is a member of `oneof`_ ``_name``. + system_managed_resource_source (google.ads.googleads.v24.enums.types.SystemManagedResourceSourceEnum.SystemManagedResourceSource): + Output only. If this ad is system managed, + then this field will indicate the source. This + field is read-only. + text_ad (google.ads.googleads.v24.common.types.TextAdInfo): + Immutable. Details pertaining to a text ad. + + This field is a member of `oneof`_ ``ad_data``. + expanded_text_ad (google.ads.googleads.v24.common.types.ExpandedTextAdInfo): + Details pertaining to an expanded text ad. Expanded text ads + are deprecated. Use ``ResponsiveSearchAd`` instead. + + This field is a member of `oneof`_ ``ad_data``. + expanded_dynamic_search_ad (google.ads.googleads.v24.common.types.ExpandedDynamicSearchAdInfo): + Immutable. Details pertaining to an Expanded Dynamic Search + Ad. This type of ad has its headline, final URLs, and + display URL auto-generated at serving time according to + domain name specific information provided by + ``dynamic_search_ads_setting`` linked at the campaign level. + + This field is a member of `oneof`_ ``ad_data``. + hotel_ad (google.ads.googleads.v24.common.types.HotelAdInfo): + Details pertaining to a hotel ad. + + This field is a member of `oneof`_ ``ad_data``. + shopping_smart_ad (google.ads.googleads.v24.common.types.ShoppingSmartAdInfo): + Details pertaining to a Smart Shopping ad. + + This field is a member of `oneof`_ ``ad_data``. + shopping_product_ad (google.ads.googleads.v24.common.types.ShoppingProductAdInfo): + Details pertaining to a Shopping product ad. + + This field is a member of `oneof`_ ``ad_data``. + image_ad (google.ads.googleads.v24.common.types.ImageAdInfo): + Immutable. Details pertaining to an Image ad. + + This field is a member of `oneof`_ ``ad_data``. + video_ad (google.ads.googleads.v24.common.types.VideoAdInfo): + Details pertaining to a Video ad. + + This field is a member of `oneof`_ ``ad_data``. + video_responsive_ad (google.ads.googleads.v24.common.types.VideoResponsiveAdInfo): + Details pertaining to a Video responsive ad. + + This field is a member of `oneof`_ ``ad_data``. + responsive_search_ad (google.ads.googleads.v24.common.types.ResponsiveSearchAdInfo): + Details pertaining to a responsive search ad. + + This field is a member of `oneof`_ ``ad_data``. + legacy_responsive_display_ad (google.ads.googleads.v24.common.types.LegacyResponsiveDisplayAdInfo): + Details pertaining to a legacy responsive + display ad. + + This field is a member of `oneof`_ ``ad_data``. + app_ad (google.ads.googleads.v24.common.types.AppAdInfo): + Details pertaining to an app ad. + + This field is a member of `oneof`_ ``ad_data``. + legacy_app_install_ad (google.ads.googleads.v24.common.types.LegacyAppInstallAdInfo): + Immutable. Details pertaining to a legacy app + install ad. + + This field is a member of `oneof`_ ``ad_data``. + responsive_display_ad (google.ads.googleads.v24.common.types.ResponsiveDisplayAdInfo): + Details pertaining to a responsive display + ad. + + This field is a member of `oneof`_ ``ad_data``. + local_ad (google.ads.googleads.v24.common.types.LocalAdInfo): + Details pertaining to a local ad. + + This field is a member of `oneof`_ ``ad_data``. + display_upload_ad (google.ads.googleads.v24.common.types.DisplayUploadAdInfo): + Details pertaining to a display upload ad. + + This field is a member of `oneof`_ ``ad_data``. + app_engagement_ad (google.ads.googleads.v24.common.types.AppEngagementAdInfo): + Details pertaining to an app engagement ad. + + This field is a member of `oneof`_ ``ad_data``. + shopping_comparison_listing_ad (google.ads.googleads.v24.common.types.ShoppingComparisonListingAdInfo): + Details pertaining to a Shopping Comparison + Listing ad. + + This field is a member of `oneof`_ ``ad_data``. + smart_campaign_ad (google.ads.googleads.v24.common.types.SmartCampaignAdInfo): + Details pertaining to a Smart campaign ad. + + This field is a member of `oneof`_ ``ad_data``. + app_pre_registration_ad (google.ads.googleads.v24.common.types.AppPreRegistrationAdInfo): + Details pertaining to an app pre-registration + ad. + + This field is a member of `oneof`_ ``ad_data``. + demand_gen_multi_asset_ad (google.ads.googleads.v24.common.types.DemandGenMultiAssetAdInfo): + Details pertaining to a Demand Gen multi + asset ad. + + This field is a member of `oneof`_ ``ad_data``. + demand_gen_carousel_ad (google.ads.googleads.v24.common.types.DemandGenCarouselAdInfo): + Details pertaining to a Demand Gen carousel + ad. + + This field is a member of `oneof`_ ``ad_data``. + demand_gen_video_responsive_ad (google.ads.googleads.v24.common.types.DemandGenVideoResponsiveAdInfo): + Details pertaining to a Demand Gen video + responsive ad. + + This field is a member of `oneof`_ ``ad_data``. + demand_gen_product_ad (google.ads.googleads.v24.common.types.DemandGenProductAdInfo): + Details pertaining to a Demand Gen product + ad. + + This field is a member of `oneof`_ ``ad_data``. + travel_ad (google.ads.googleads.v24.common.types.TravelAdInfo): + Details pertaining to a travel ad. + + This field is a member of `oneof`_ ``ad_data``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=37, + ) + id: int = proto.Field( + proto.INT64, + number=40, + optional=True, + ) + final_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=41, + ) + final_app_urls: MutableSequence[final_app_url.FinalAppUrl] = ( + proto.RepeatedField( + proto.MESSAGE, + number=35, + message=final_app_url.FinalAppUrl, + ) + ) + final_mobile_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=42, + ) + tracking_url_template: str = proto.Field( + proto.STRING, + number=43, + optional=True, + ) + final_url_suffix: str = proto.Field( + proto.STRING, + number=44, + optional=True, + ) + url_custom_parameters: MutableSequence[custom_parameter.CustomParameter] = ( + proto.RepeatedField( + proto.MESSAGE, + number=10, + message=custom_parameter.CustomParameter, + ) + ) + display_url: str = proto.Field( + proto.STRING, + number=45, + optional=True, + ) + type_: ad_type.AdTypeEnum.AdType = proto.Field( + proto.ENUM, + number=5, + enum=ad_type.AdTypeEnum.AdType, + ) + added_by_google_ads: bool = proto.Field( + proto.BOOL, + number=46, + optional=True, + ) + device_preference: device.DeviceEnum.Device = proto.Field( + proto.ENUM, + number=20, + enum=device.DeviceEnum.Device, + ) + url_collections: MutableSequence[url_collection.UrlCollection] = ( + proto.RepeatedField( + proto.MESSAGE, + number=26, + message=url_collection.UrlCollection, + ) + ) + name: str = proto.Field( + proto.STRING, + number=47, + optional=True, + ) + system_managed_resource_source: ( + system_managed_entity_source.SystemManagedResourceSourceEnum.SystemManagedResourceSource + ) = proto.Field( + proto.ENUM, + number=27, + enum=system_managed_entity_source.SystemManagedResourceSourceEnum.SystemManagedResourceSource, + ) + text_ad: ad_type_infos.TextAdInfo = proto.Field( + proto.MESSAGE, + number=6, + oneof="ad_data", + message=ad_type_infos.TextAdInfo, + ) + expanded_text_ad: ad_type_infos.ExpandedTextAdInfo = proto.Field( + proto.MESSAGE, + number=7, + oneof="ad_data", + message=ad_type_infos.ExpandedTextAdInfo, + ) + expanded_dynamic_search_ad: ad_type_infos.ExpandedDynamicSearchAdInfo = ( + proto.Field( + proto.MESSAGE, + number=14, + oneof="ad_data", + message=ad_type_infos.ExpandedDynamicSearchAdInfo, + ) + ) + hotel_ad: ad_type_infos.HotelAdInfo = proto.Field( + proto.MESSAGE, + number=15, + oneof="ad_data", + message=ad_type_infos.HotelAdInfo, + ) + shopping_smart_ad: ad_type_infos.ShoppingSmartAdInfo = proto.Field( + proto.MESSAGE, + number=17, + oneof="ad_data", + message=ad_type_infos.ShoppingSmartAdInfo, + ) + shopping_product_ad: ad_type_infos.ShoppingProductAdInfo = proto.Field( + proto.MESSAGE, + number=18, + oneof="ad_data", + message=ad_type_infos.ShoppingProductAdInfo, + ) + image_ad: ad_type_infos.ImageAdInfo = proto.Field( + proto.MESSAGE, + number=22, + oneof="ad_data", + message=ad_type_infos.ImageAdInfo, + ) + video_ad: ad_type_infos.VideoAdInfo = proto.Field( + proto.MESSAGE, + number=24, + oneof="ad_data", + message=ad_type_infos.VideoAdInfo, + ) + video_responsive_ad: ad_type_infos.VideoResponsiveAdInfo = proto.Field( + proto.MESSAGE, + number=39, + oneof="ad_data", + message=ad_type_infos.VideoResponsiveAdInfo, + ) + responsive_search_ad: ad_type_infos.ResponsiveSearchAdInfo = proto.Field( + proto.MESSAGE, + number=25, + oneof="ad_data", + message=ad_type_infos.ResponsiveSearchAdInfo, + ) + legacy_responsive_display_ad: ( + ad_type_infos.LegacyResponsiveDisplayAdInfo + ) = proto.Field( + proto.MESSAGE, + number=28, + oneof="ad_data", + message=ad_type_infos.LegacyResponsiveDisplayAdInfo, + ) + app_ad: ad_type_infos.AppAdInfo = proto.Field( + proto.MESSAGE, + number=29, + oneof="ad_data", + message=ad_type_infos.AppAdInfo, + ) + legacy_app_install_ad: ad_type_infos.LegacyAppInstallAdInfo = proto.Field( + proto.MESSAGE, + number=30, + oneof="ad_data", + message=ad_type_infos.LegacyAppInstallAdInfo, + ) + responsive_display_ad: ad_type_infos.ResponsiveDisplayAdInfo = proto.Field( + proto.MESSAGE, + number=31, + oneof="ad_data", + message=ad_type_infos.ResponsiveDisplayAdInfo, + ) + local_ad: ad_type_infos.LocalAdInfo = proto.Field( + proto.MESSAGE, + number=32, + oneof="ad_data", + message=ad_type_infos.LocalAdInfo, + ) + display_upload_ad: ad_type_infos.DisplayUploadAdInfo = proto.Field( + proto.MESSAGE, + number=33, + oneof="ad_data", + message=ad_type_infos.DisplayUploadAdInfo, + ) + app_engagement_ad: ad_type_infos.AppEngagementAdInfo = proto.Field( + proto.MESSAGE, + number=34, + oneof="ad_data", + message=ad_type_infos.AppEngagementAdInfo, + ) + shopping_comparison_listing_ad: ( + ad_type_infos.ShoppingComparisonListingAdInfo + ) = proto.Field( + proto.MESSAGE, + number=36, + oneof="ad_data", + message=ad_type_infos.ShoppingComparisonListingAdInfo, + ) + smart_campaign_ad: ad_type_infos.SmartCampaignAdInfo = proto.Field( + proto.MESSAGE, + number=48, + oneof="ad_data", + message=ad_type_infos.SmartCampaignAdInfo, + ) + app_pre_registration_ad: ad_type_infos.AppPreRegistrationAdInfo = ( + proto.Field( + proto.MESSAGE, + number=50, + oneof="ad_data", + message=ad_type_infos.AppPreRegistrationAdInfo, + ) + ) + demand_gen_multi_asset_ad: ad_type_infos.DemandGenMultiAssetAdInfo = ( + proto.Field( + proto.MESSAGE, + number=62, + oneof="ad_data", + message=ad_type_infos.DemandGenMultiAssetAdInfo, + ) + ) + demand_gen_carousel_ad: ad_type_infos.DemandGenCarouselAdInfo = proto.Field( + proto.MESSAGE, + number=63, + oneof="ad_data", + message=ad_type_infos.DemandGenCarouselAdInfo, + ) + demand_gen_video_responsive_ad: ( + ad_type_infos.DemandGenVideoResponsiveAdInfo + ) = proto.Field( + proto.MESSAGE, + number=64, + oneof="ad_data", + message=ad_type_infos.DemandGenVideoResponsiveAdInfo, + ) + demand_gen_product_ad: ad_type_infos.DemandGenProductAdInfo = proto.Field( + proto.MESSAGE, + number=61, + oneof="ad_data", + message=ad_type_infos.DemandGenProductAdInfo, + ) + travel_ad: ad_type_infos.TravelAdInfo = proto.Field( + proto.MESSAGE, + number=54, + oneof="ad_data", + message=ad_type_infos.TravelAdInfo, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group.py b/google/ads/googleads/v24/resources/types/ad_group.py new file mode 100644 index 000000000..955676427 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group.py @@ -0,0 +1,739 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import custom_parameter +from google.ads.googleads.v24.common.types import ( + targeting_setting as gagc_targeting_setting, +) +from google.ads.googleads.v24.enums.types import ad_group_ad_rotation_mode +from google.ads.googleads.v24.enums.types import ad_group_primary_status +from google.ads.googleads.v24.enums.types import ad_group_primary_status_reason +from google.ads.googleads.v24.enums.types import ad_group_status +from google.ads.googleads.v24.enums.types import ad_group_type +from google.ads.googleads.v24.enums.types import asset_field_type +from google.ads.googleads.v24.enums.types import asset_set_type +from google.ads.googleads.v24.enums.types import bidding_source +from google.ads.googleads.v24.enums.types import demand_gen_channel_config +from google.ads.googleads.v24.enums.types import demand_gen_channel_strategy +from google.ads.googleads.v24.enums.types import targeting_dimension + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroup", + }, +) + + +class AdGroup(proto.Message): + r"""An ad group. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the ad group. Ad group + resource names have the form: + + ``customers/{customer_id}/adGroups/{ad_group_id}`` + id (int): + Output only. The ID of the ad group. + + This field is a member of `oneof`_ ``_id``. + name (str): + The name of the ad group. + + This field is required and should not be empty + when creating new ad groups. + + It must contain fewer than 255 UTF-8 full-width + characters. + + It must not contain any null (code point 0x0), + NL line feed (code point 0xA) or carriage return + (code point 0xD) characters. + + This field is a member of `oneof`_ ``_name``. + status (google.ads.googleads.v24.enums.types.AdGroupStatusEnum.AdGroupStatus): + The status of the ad group. + type_ (google.ads.googleads.v24.enums.types.AdGroupTypeEnum.AdGroupType): + Immutable. The type of the ad group. + ad_rotation_mode (google.ads.googleads.v24.enums.types.AdGroupAdRotationModeEnum.AdGroupAdRotationMode): + The ad rotation mode of the ad group. + base_ad_group (str): + Output only. For draft or experiment ad + groups, this field is the resource name of the + base ad group from which this ad group was + created. If a draft or experiment ad group does + not have a base ad group, then this field is + null. + + For base ad groups, this field equals the ad + group resource name. + + This field is read-only. + + This field is a member of `oneof`_ ``_base_ad_group``. + tracking_url_template (str): + The URL template for constructing a tracking + URL. + + This field is a member of `oneof`_ ``_tracking_url_template``. + url_custom_parameters (MutableSequence[google.ads.googleads.v24.common.types.CustomParameter]): + The list of mappings used to substitute custom parameter + tags in a ``tracking_url_template``, ``final_urls``, or + ``mobile_final_urls``. + campaign (str): + Immutable. The campaign to which the ad group + belongs. + + This field is a member of `oneof`_ ``_campaign``. + cpc_bid_micros (int): + The maximum CPC (cost-per-click) bid. This + field is used when the ad group's effective + bidding strategy is Manual CPC. This field is + not applicable and will be ignored if the ad + group's campaign is using a portfolio bidding + strategy. + + This field is a member of `oneof`_ ``_cpc_bid_micros``. + effective_cpc_bid_micros (int): + Output only. Value will be same as that of + the CPC (cost-per-click) bid value when the + bidding strategy is one of manual cpc, enhanced + cpc, page one promoted or target outrank share, + otherwise the value will be null. + + This field is a member of `oneof`_ ``_effective_cpc_bid_micros``. + cpm_bid_micros (int): + The maximum CPM (cost-per-thousand viewable + impressions) bid. + + This field is a member of `oneof`_ ``_cpm_bid_micros``. + target_cpa_micros (int): + The target CPA (cost-per-acquisition). If the ad group's + campaign bidding strategy is TargetCpa or + MaximizeConversions (with its target_cpa field set), then + this field overrides the target CPA specified in the + campaign's bidding strategy. Otherwise, this value is + ignored. + + This field is a member of `oneof`_ ``_target_cpa_micros``. + cpv_bid_micros (int): + The CPV (cost-per-view) bid. + + This field is a member of `oneof`_ ``_cpv_bid_micros``. + target_cpm_micros (int): + Average amount in micros that the advertiser + is willing to pay for every thousand times the + ad is shown. + + This field is a member of `oneof`_ ``_target_cpm_micros``. + target_roas (float): + The target ROAS (return-on-ad-spend) for this ad group. + + This field lets you override the target ROAS specified in + the campaign's bidding strategy, but only if the campaign is + using a standard (not portfolio) ``TargetRoas`` strategy or + a standard ``MaximizeConversionValue`` strategy with its + ``target_roas`` field set. + + If the campaign is using a portfolio bidding strategy, this + field cannot be set and attempting to do so will result in + an error. + + For any other bidding strategies, this value is ignored. + + To see the actual target ROAS being used by the ad group, + considering potential overrides, query the + ``effective_target_roas`` and + ``effective_target_roas_source`` fields. + + This field is a member of `oneof`_ ``_target_roas``. + percent_cpc_bid_micros (int): + The percent cpc bid amount, expressed as a fraction of the + advertised price for some good or service. The valid range + for the fraction is [0,1) and the value stored here is + 1,000,000 \* [fraction]. + + This field is a member of `oneof`_ ``_percent_cpc_bid_micros``. + fixed_cpm_micros (int): + The fixed amount in micros that the + advertiser pays for every thousand impressions + of the ad. + + This field is a member of `oneof`_ ``_fixed_cpm_micros``. + target_cpv_micros (int): + Average amount in micros that the advertiser + is willing to pay for every ad view. + + This field is a member of `oneof`_ ``_target_cpv_micros``. + target_cpc_micros (int): + Average amount in micros that the advertiser + is willing to pay for every ad click. Overrides + the target CPC configured at the campaign level. + + This field is a member of `oneof`_ ``_target_cpc_micros``. + optimized_targeting_enabled (bool): + True if optimized targeting is enabled. + Optimized Targeting is the replacement for + Audience Expansion. + exclude_demographic_expansion (bool): + When this value is true, demographics will be excluded from + the types of targeting which are expanded when + optimized_targeting_enabled is true. When + optimized_targeting_enabled is false, this field is ignored. + Default is false. + display_custom_bid_dimension (google.ads.googleads.v24.enums.types.TargetingDimensionEnum.TargetingDimension): + Lets advertisers specify a targeting + dimension on which to place absolute bids. This + is only applicable for campaigns that target + only the display network and not search. + final_url_suffix (str): + URL template for appending params to Final + URL. + + This field is a member of `oneof`_ ``_final_url_suffix``. + targeting_setting (google.ads.googleads.v24.common.types.TargetingSetting): + Setting for targeting related features. + audience_setting (google.ads.googleads.v24.resources.types.AdGroup.AudienceSetting): + Immutable. Setting for audience related + features. + effective_target_cpa_micros (int): + Output only. The effective target CPA + (cost-per-acquisition). This field is read-only. + + This field is a member of `oneof`_ ``_effective_target_cpa_micros``. + effective_target_cpa_source (google.ads.googleads.v24.enums.types.BiddingSourceEnum.BiddingSource): + Output only. Source of the effective target + CPA. This field is read-only. + effective_target_roas (float): + Output only. The effective target ROAS + (return-on-ad-spend). This field is read-only. + + This field is a member of `oneof`_ ``_effective_target_roas``. + effective_target_roas_source (google.ads.googleads.v24.enums.types.BiddingSourceEnum.BiddingSource): + Output only. Source of the effective target + ROAS. This field is read-only. + effective_target_cpc (int): + Output only. The effective target CPC + (cost-per-click). This field is read-only. + + This field is a member of `oneof`_ ``_effective_target_cpc``. + effective_target_cpc_source (google.ads.googleads.v24.enums.types.BiddingSourceEnum.BiddingSource): + Output only. Source of the effective target + CPC. This field is read-only. + labels (MutableSequence[str]): + Output only. The resource names of labels + attached to this ad group. + excluded_parent_asset_field_types (MutableSequence[google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType]): + The asset field types that should be excluded + from this ad group. Asset links with these field + types will not be inherited by this ad group + from the upper levels. + excluded_parent_asset_set_types (MutableSequence[google.ads.googleads.v24.enums.types.AssetSetTypeEnum.AssetSetType]): + The asset set types that should be excluded from this ad + group. Asset set links with these types will not be + inherited by this ad group from the upper levels. Location + group types (GMB_DYNAMIC_LOCATION_GROUP, + CHAIN_DYNAMIC_LOCATION_GROUP, and STATIC_LOCATION_GROUP) are + child types of LOCATION_SYNC. Therefore, if LOCATION_SYNC is + set for this field, all location group asset sets are not + allowed to be linked to this ad group, and all Location + Extension (LE) and Affiliate Location Extensions (ALE) will + not be served under this ad group. Only LOCATION_SYNC is + currently supported. + primary_status (google.ads.googleads.v24.enums.types.AdGroupPrimaryStatusEnum.AdGroupPrimaryStatus): + Output only. Provides aggregated view into + why an ad group is not serving or not serving + optimally. + primary_status_reasons (MutableSequence[google.ads.googleads.v24.enums.types.AdGroupPrimaryStatusReasonEnum.AdGroupPrimaryStatusReason]): + Output only. Provides reasons for why an ad + group is not serving or not serving optimally. + demand_gen_ad_group_settings (google.ads.googleads.v24.resources.types.AdGroup.DemandGenAdGroupSettings): + Settings for Demand Gen ad groups. + video_ad_group_settings (google.ads.googleads.v24.resources.types.AdGroup.VideoAdGroupSettings): + Settings for video ad groups. + ai_max_ad_group_setting (google.ads.googleads.v24.resources.types.AdGroup.AiMaxAdGroupSetting): + Settings for AI Max feature in standard + search adgroups. + vertical_ads_format_setting (google.ads.googleads.v24.resources.types.AdGroup.VerticalAdsFormatSetting): + Vertical ads setting feature to + enable/disable ad group format controls in + search campaigns. This setting requires + AiMaxAdGroupSetting to be enabled and a travel + feed to be attached to the campaign. + """ + + class AudienceSetting(proto.Message): + r"""Settings for the audience targeting. + + Attributes: + use_audience_grouped (bool): + Immutable. If true, this ad group uses an + Audience resource for audience targeting. If + false, this ad group may use audience segment + criteria instead. + """ + + use_audience_grouped: bool = proto.Field( + proto.BOOL, + number=1, + ) + + class DemandGenAdGroupSettings(proto.Message): + r"""Settings for Demand Gen ad groups. + + Attributes: + channel_controls (google.ads.googleads.v24.resources.types.AdGroup.DemandGenAdGroupSettings.DemandGenChannelControls): + Channel controls for Demand Gen ad groups. + """ + + class DemandGenChannelControls(proto.Message): + r"""Channel controls for Demand Gen ad groups. + + 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: + channel_config (google.ads.googleads.v24.enums.types.DemandGenChannelConfigEnum.DemandGenChannelConfig): + Output only. Channel configuration reflecting + which field in the oneof is populated. + channel_strategy (google.ads.googleads.v24.enums.types.DemandGenChannelStrategyEnum.DemandGenChannelStrategy): + High level channel strategy. + + This field is a member of `oneof`_ ``channel_configuration``. + selected_channels (google.ads.googleads.v24.resources.types.AdGroup.DemandGenAdGroupSettings.DemandGenChannelControls.DemandGenSelectedChannels): + Explicitly selected channels. This field + should be set with at least one true value when + present. + + This field is a member of `oneof`_ ``channel_configuration``. + """ + + class DemandGenSelectedChannels(proto.Message): + r"""Explicitly selected channels for channel controls in Demand + Gen ad groups. + + Attributes: + youtube_in_stream (bool): + Whether to enable ads on the YouTube + In-Stream channel. + youtube_in_feed (bool): + Whether to enable ads on the YouTube In-Feed + channel. + youtube_shorts (bool): + Whether to enable ads on the YouTube Shorts + channel. + discover (bool): + Whether to enable ads on the Discover + channel. + gmail (bool): + Whether to enable ads on the Gmail channel. + display (bool): + Whether to enable ads on the Display channel. + """ + + youtube_in_stream: bool = proto.Field( + proto.BOOL, + number=1, + ) + youtube_in_feed: bool = proto.Field( + proto.BOOL, + number=2, + ) + youtube_shorts: bool = proto.Field( + proto.BOOL, + number=3, + ) + discover: bool = proto.Field( + proto.BOOL, + number=4, + ) + gmail: bool = proto.Field( + proto.BOOL, + number=5, + ) + display: bool = proto.Field( + proto.BOOL, + number=6, + ) + + channel_config: ( + demand_gen_channel_config.DemandGenChannelConfigEnum.DemandGenChannelConfig + ) = proto.Field( + proto.ENUM, + number=1, + enum=demand_gen_channel_config.DemandGenChannelConfigEnum.DemandGenChannelConfig, + ) + channel_strategy: ( + demand_gen_channel_strategy.DemandGenChannelStrategyEnum.DemandGenChannelStrategy + ) = proto.Field( + proto.ENUM, + number=2, + oneof="channel_configuration", + enum=demand_gen_channel_strategy.DemandGenChannelStrategyEnum.DemandGenChannelStrategy, + ) + selected_channels: "AdGroup.DemandGenAdGroupSettings.DemandGenChannelControls.DemandGenSelectedChannels" = proto.Field( + proto.MESSAGE, + number=3, + oneof="channel_configuration", + message="AdGroup.DemandGenAdGroupSettings.DemandGenChannelControls.DemandGenSelectedChannels", + ) + + channel_controls: ( + "AdGroup.DemandGenAdGroupSettings.DemandGenChannelControls" + ) = proto.Field( + proto.MESSAGE, + number=1, + message="AdGroup.DemandGenAdGroupSettings.DemandGenChannelControls", + ) + + class VideoAdGroupSettings(proto.Message): + r"""Settings for video ad groups. + + Attributes: + video_ad_sequence (google.ads.googleads.v24.resources.types.AdGroup.VideoAdGroupSettings.VideoAdSequenceStepSetting): + The video ads sequence step settings + containing step ID. + """ + + class VideoAdSequenceStepSetting(proto.Message): + r"""The video ads sequence step settings containing step ID. + + Attributes: + step_id (int): + The ID of this sequence step from an existing + ``campaign.video_campaign_settings.video_ad_sequence`` + definition. Only one Ad Group can point to a given + ``step_id``. + """ + + step_id: int = proto.Field( + proto.INT64, + number=1, + ) + + video_ad_sequence: ( + "AdGroup.VideoAdGroupSettings.VideoAdSequenceStepSetting" + ) = proto.Field( + proto.MESSAGE, + number=1, + message="AdGroup.VideoAdGroupSettings.VideoAdSequenceStepSetting", + ) + + class AiMaxAdGroupSetting(proto.Message): + r"""Settings for AI Max feature in standard search adgroups. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + disable_search_term_matching (bool): + Disable search term matching for this adgroup + when AI Max is enabled. Search term matching + uses broad match, asset-based, and landing + page-based technology to improve reach. + + This field is a member of `oneof`_ ``_disable_search_term_matching``. + """ + + disable_search_term_matching: bool = proto.Field( + proto.BOOL, + number=1, + optional=True, + ) + + class VerticalAdsFormatSetting(proto.Message): + r"""Vertical ads setting feature to enable/disable ad group + format controls in search campaigns. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + disable_text_ads (bool): + If true, text ads will be disabled for this + ad group. + + This field is a member of `oneof`_ ``_disable_text_ads``. + enable_booking_links (bool): + If true, booking links will be enabled for + this ad group. + + This field is a member of `oneof`_ ``_enable_booking_links``. + enable_vertical_promotion_ads (bool): + If true, vertical promotion ads will be + enabled for this ad group. + + This field is a member of `oneof`_ ``_enable_vertical_promotion_ads``. + """ + + disable_text_ads: bool = proto.Field( + proto.BOOL, + number=1, + optional=True, + ) + enable_booking_links: bool = proto.Field( + proto.BOOL, + number=2, + optional=True, + ) + enable_vertical_promotion_ads: bool = proto.Field( + proto.BOOL, + number=3, + optional=True, + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=34, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=35, + optional=True, + ) + status: ad_group_status.AdGroupStatusEnum.AdGroupStatus = proto.Field( + proto.ENUM, + number=5, + enum=ad_group_status.AdGroupStatusEnum.AdGroupStatus, + ) + type_: ad_group_type.AdGroupTypeEnum.AdGroupType = proto.Field( + proto.ENUM, + number=12, + enum=ad_group_type.AdGroupTypeEnum.AdGroupType, + ) + ad_rotation_mode: ( + ad_group_ad_rotation_mode.AdGroupAdRotationModeEnum.AdGroupAdRotationMode + ) = proto.Field( + proto.ENUM, + number=22, + enum=ad_group_ad_rotation_mode.AdGroupAdRotationModeEnum.AdGroupAdRotationMode, + ) + base_ad_group: str = proto.Field( + proto.STRING, + number=36, + optional=True, + ) + tracking_url_template: str = proto.Field( + proto.STRING, + number=37, + optional=True, + ) + url_custom_parameters: MutableSequence[custom_parameter.CustomParameter] = ( + proto.RepeatedField( + proto.MESSAGE, + number=6, + message=custom_parameter.CustomParameter, + ) + ) + campaign: str = proto.Field( + proto.STRING, + number=38, + optional=True, + ) + cpc_bid_micros: int = proto.Field( + proto.INT64, + number=39, + optional=True, + ) + effective_cpc_bid_micros: int = proto.Field( + proto.INT64, + number=57, + optional=True, + ) + cpm_bid_micros: int = proto.Field( + proto.INT64, + number=40, + optional=True, + ) + target_cpa_micros: int = proto.Field( + proto.INT64, + number=41, + optional=True, + ) + cpv_bid_micros: int = proto.Field( + proto.INT64, + number=42, + optional=True, + ) + target_cpm_micros: int = proto.Field( + proto.INT64, + number=43, + optional=True, + ) + target_roas: float = proto.Field( + proto.DOUBLE, + number=44, + optional=True, + ) + percent_cpc_bid_micros: int = proto.Field( + proto.INT64, + number=45, + optional=True, + ) + fixed_cpm_micros: int = proto.Field( + proto.INT64, + number=64, + optional=True, + ) + target_cpv_micros: int = proto.Field( + proto.INT64, + number=65, + optional=True, + ) + target_cpc_micros: int = proto.Field( + proto.INT64, + number=68, + optional=True, + ) + optimized_targeting_enabled: bool = proto.Field( + proto.BOOL, + number=59, + ) + exclude_demographic_expansion: bool = proto.Field( + proto.BOOL, + number=67, + ) + display_custom_bid_dimension: ( + targeting_dimension.TargetingDimensionEnum.TargetingDimension + ) = proto.Field( + proto.ENUM, + number=23, + enum=targeting_dimension.TargetingDimensionEnum.TargetingDimension, + ) + final_url_suffix: str = proto.Field( + proto.STRING, + number=46, + optional=True, + ) + targeting_setting: gagc_targeting_setting.TargetingSetting = proto.Field( + proto.MESSAGE, + number=25, + message=gagc_targeting_setting.TargetingSetting, + ) + audience_setting: AudienceSetting = proto.Field( + proto.MESSAGE, + number=56, + message=AudienceSetting, + ) + effective_target_cpa_micros: int = proto.Field( + proto.INT64, + number=47, + optional=True, + ) + effective_target_cpa_source: ( + bidding_source.BiddingSourceEnum.BiddingSource + ) = proto.Field( + proto.ENUM, + number=29, + enum=bidding_source.BiddingSourceEnum.BiddingSource, + ) + effective_target_roas: float = proto.Field( + proto.DOUBLE, + number=48, + optional=True, + ) + effective_target_roas_source: ( + bidding_source.BiddingSourceEnum.BiddingSource + ) = proto.Field( + proto.ENUM, + number=32, + enum=bidding_source.BiddingSourceEnum.BiddingSource, + ) + effective_target_cpc: int = proto.Field( + proto.INT64, + number=69, + optional=True, + ) + effective_target_cpc_source: ( + bidding_source.BiddingSourceEnum.BiddingSource + ) = proto.Field( + proto.ENUM, + number=70, + enum=bidding_source.BiddingSourceEnum.BiddingSource, + ) + labels: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=49, + ) + excluded_parent_asset_field_types: MutableSequence[ + asset_field_type.AssetFieldTypeEnum.AssetFieldType + ] = proto.RepeatedField( + proto.ENUM, + number=54, + enum=asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + excluded_parent_asset_set_types: MutableSequence[ + asset_set_type.AssetSetTypeEnum.AssetSetType + ] = proto.RepeatedField( + proto.ENUM, + number=58, + enum=asset_set_type.AssetSetTypeEnum.AssetSetType, + ) + primary_status: ( + ad_group_primary_status.AdGroupPrimaryStatusEnum.AdGroupPrimaryStatus + ) = proto.Field( + proto.ENUM, + number=62, + enum=ad_group_primary_status.AdGroupPrimaryStatusEnum.AdGroupPrimaryStatus, + ) + primary_status_reasons: MutableSequence[ + ad_group_primary_status_reason.AdGroupPrimaryStatusReasonEnum.AdGroupPrimaryStatusReason + ] = proto.RepeatedField( + proto.ENUM, + number=63, + enum=ad_group_primary_status_reason.AdGroupPrimaryStatusReasonEnum.AdGroupPrimaryStatusReason, + ) + demand_gen_ad_group_settings: DemandGenAdGroupSettings = proto.Field( + proto.MESSAGE, + number=91, + message=DemandGenAdGroupSettings, + ) + video_ad_group_settings: VideoAdGroupSettings = proto.Field( + proto.MESSAGE, + number=92, + message=VideoAdGroupSettings, + ) + ai_max_ad_group_setting: AiMaxAdGroupSetting = proto.Field( + proto.MESSAGE, + number=71, + message=AiMaxAdGroupSetting, + ) + vertical_ads_format_setting: VerticalAdsFormatSetting = proto.Field( + proto.MESSAGE, + number=72, + message=VerticalAdsFormatSetting, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_ad.py b/google/ads/googleads/v24/resources/types/ad_group_ad.py new file mode 100644 index 000000000..1f939ab09 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_ad.py @@ -0,0 +1,260 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import policy +from google.ads.googleads.v24.enums.types import ad_group_ad_primary_status +from google.ads.googleads.v24.enums.types import ( + ad_group_ad_primary_status_reason, +) +from google.ads.googleads.v24.enums.types import ad_group_ad_status +from google.ads.googleads.v24.enums.types import ad_strength as gage_ad_strength +from google.ads.googleads.v24.enums.types import ( + asset_automation_status as gage_asset_automation_status, +) +from google.ads.googleads.v24.enums.types import ( + asset_automation_type as gage_asset_automation_type, +) +from google.ads.googleads.v24.enums.types import policy_approval_status +from google.ads.googleads.v24.enums.types import policy_review_status +from google.ads.googleads.v24.resources.types import ad as gagr_ad + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupAd", + "AdGroupAdPolicySummary", + "AdGroupAdAssetAutomationSetting", + }, +) + + +class AdGroupAd(proto.Message): + r"""An ad group ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the ad. Ad group ad resource + names have the form: + + ``customers/{customer_id}/adGroupAds/{ad_group_id}~{ad_id}`` + status (google.ads.googleads.v24.enums.types.AdGroupAdStatusEnum.AdGroupAdStatus): + The status of the ad. + ad_group (str): + Immutable. The ad group to which the ad + belongs. + + This field is a member of `oneof`_ ``_ad_group``. + ad (google.ads.googleads.v24.resources.types.Ad): + Immutable. The ad. + start_date_time (str): + The date and time when ad group ad starts + serving. This is added on top of the campaign's + start date and time, if present, to further + restrict the duration of an ad group ad. The + timestamp is in the customer's time zone and in + "yyyy-MM-dd HH:mm:ss" format. Only supported for + some ad types. + end_date_time (str): + The last day and time when ad group ad + serves. This is added on top of the campaign's + end date and time, if present, to further + restrict the duration of an ad group ad. The + timestamp is in the customer's time zone and in + "yyyy-MM-dd HH:mm:ss" format. Only supported for + some ad types. + policy_summary (google.ads.googleads.v24.resources.types.AdGroupAdPolicySummary): + Output only. Policy information for the ad. + ad_strength (google.ads.googleads.v24.enums.types.AdStrengthEnum.AdStrength): + Output only. Overall ad strength for this ad + group ad. + action_items (MutableSequence[str]): + Output only. A list of recommendations to + improve the ad strength. For example, a + recommendation could be "Try adding a few more + unique headlines or unpinning some assets.". + labels (MutableSequence[str]): + Output only. The resource names of labels + attached to this ad group ad. + primary_status (google.ads.googleads.v24.enums.types.AdGroupAdPrimaryStatusEnum.AdGroupAdPrimaryStatus): + Output only. Provides aggregated view into + why an ad group ad is not serving or not serving + optimally. + primary_status_reasons (MutableSequence[google.ads.googleads.v24.enums.types.AdGroupAdPrimaryStatusReasonEnum.AdGroupAdPrimaryStatusReason]): + Output only. Provides reasons for why an ad + group ad is not serving or not serving + optimally. + ad_group_ad_asset_automation_settings (MutableSequence[google.ads.googleads.v24.resources.types.AdGroupAdAssetAutomationSetting]): + Settings that control the types of asset + automation. See the AssetAutomationTypeEnum + documentation for the default opt in/out + behavior of each type. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + status: ad_group_ad_status.AdGroupAdStatusEnum.AdGroupAdStatus = ( + proto.Field( + proto.ENUM, + number=3, + enum=ad_group_ad_status.AdGroupAdStatusEnum.AdGroupAdStatus, + ) + ) + ad_group: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + ad: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=5, + message=gagr_ad.Ad, + ) + start_date_time: str = proto.Field( + proto.STRING, + number=20, + ) + end_date_time: str = proto.Field( + proto.STRING, + number=21, + ) + policy_summary: "AdGroupAdPolicySummary" = proto.Field( + proto.MESSAGE, + number=6, + message="AdGroupAdPolicySummary", + ) + ad_strength: gage_ad_strength.AdStrengthEnum.AdStrength = proto.Field( + proto.ENUM, + number=7, + enum=gage_ad_strength.AdStrengthEnum.AdStrength, + ) + action_items: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=13, + ) + labels: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=10, + ) + primary_status: ( + ad_group_ad_primary_status.AdGroupAdPrimaryStatusEnum.AdGroupAdPrimaryStatus + ) = proto.Field( + proto.ENUM, + number=16, + enum=ad_group_ad_primary_status.AdGroupAdPrimaryStatusEnum.AdGroupAdPrimaryStatus, + ) + primary_status_reasons: MutableSequence[ + ad_group_ad_primary_status_reason.AdGroupAdPrimaryStatusReasonEnum.AdGroupAdPrimaryStatusReason + ] = proto.RepeatedField( + proto.ENUM, + number=17, + enum=ad_group_ad_primary_status_reason.AdGroupAdPrimaryStatusReasonEnum.AdGroupAdPrimaryStatusReason, + ) + ad_group_ad_asset_automation_settings: MutableSequence[ + "AdGroupAdAssetAutomationSetting" + ] = proto.RepeatedField( + proto.MESSAGE, + number=18, + message="AdGroupAdAssetAutomationSetting", + ) + + +class AdGroupAdPolicySummary(proto.Message): + r"""Contains policy information for an ad. + + Attributes: + policy_topic_entries (MutableSequence[google.ads.googleads.v24.common.types.PolicyTopicEntry]): + Output only. The list of policy findings for + this ad. + review_status (google.ads.googleads.v24.enums.types.PolicyReviewStatusEnum.PolicyReviewStatus): + Output only. Where in the review process this + ad is. + approval_status (google.ads.googleads.v24.enums.types.PolicyApprovalStatusEnum.PolicyApprovalStatus): + Output only. The overall approval status of + this ad, calculated based on the status of its + individual policy topic entries. + """ + + policy_topic_entries: MutableSequence[policy.PolicyTopicEntry] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=policy.PolicyTopicEntry, + ) + ) + review_status: ( + policy_review_status.PolicyReviewStatusEnum.PolicyReviewStatus + ) = proto.Field( + proto.ENUM, + number=2, + enum=policy_review_status.PolicyReviewStatusEnum.PolicyReviewStatus, + ) + approval_status: ( + policy_approval_status.PolicyApprovalStatusEnum.PolicyApprovalStatus + ) = proto.Field( + proto.ENUM, + number=3, + enum=policy_approval_status.PolicyApprovalStatusEnum.PolicyApprovalStatus, + ) + + +class AdGroupAdAssetAutomationSetting(proto.Message): + r"""Asset automation setting for an AdGroupAd. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + asset_automation_type (google.ads.googleads.v24.enums.types.AssetAutomationTypeEnum.AssetAutomationType): + The asset automation type that this setting + configures. + + This field is a member of `oneof`_ ``_asset_automation_type``. + asset_automation_status (google.ads.googleads.v24.enums.types.AssetAutomationStatusEnum.AssetAutomationStatus): + The opt-in/out status for the specified asset + automation type. + + This field is a member of `oneof`_ ``_asset_automation_status``. + """ + + asset_automation_type: ( + gage_asset_automation_type.AssetAutomationTypeEnum.AssetAutomationType + ) = proto.Field( + proto.ENUM, + number=1, + optional=True, + enum=gage_asset_automation_type.AssetAutomationTypeEnum.AssetAutomationType, + ) + asset_automation_status: ( + gage_asset_automation_status.AssetAutomationStatusEnum.AssetAutomationStatus + ) = proto.Field( + proto.ENUM, + number=2, + optional=True, + enum=gage_asset_automation_status.AssetAutomationStatusEnum.AssetAutomationStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_ad_asset_combination_view.py b/google/ads/googleads/v24/resources/types/ad_group_ad_asset_combination_view.py new file mode 100644 index 000000000..816b46865 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_ad_asset_combination_view.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import asset_usage + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupAdAssetCombinationView", + }, +) + + +class AdGroupAdAssetCombinationView(proto.Message): + r"""A view on the usage of ad group ad asset combination. + Now we only support AdGroupAdAssetCombinationView for Responsive + Search Ads, with more ad types planned for the future. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the ad group ad asset + combination view. The combination ID is 128 bits long, where + the upper 64 bits are stored in asset_combination_id_high, + and the lower 64 bits are stored in + asset_combination_id_low. AdGroupAd Asset Combination view + resource names have the form: + ``customers/{customer_id}/adGroupAdAssetCombinationViews/{AdGroupAd.ad_group_id}~{AdGroupAd.ad.ad_id}~{AssetCombination.asset_combination_id_low}~{AssetCombination.asset_combination_id_high}`` + served_assets (MutableSequence[google.ads.googleads.v24.common.types.AssetUsage]): + Output only. Served assets. + enabled (bool): + Output only. The status between the asset + combination and the latest version of the ad. If + true, the asset combination is linked to the + latest version of the ad. If false, it means the + link once existed but has been removed and is no + longer present in the latest version of the ad. + + This field is a member of `oneof`_ ``_enabled``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + served_assets: MutableSequence[asset_usage.AssetUsage] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message=asset_usage.AssetUsage, + ) + ) + enabled: bool = proto.Field( + proto.BOOL, + number=3, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_ad_asset_view.py b/google/ads/googleads/v24/resources/types/ad_group_ad_asset_view.py new file mode 100644 index 000000000..fec06a2ae --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_ad_asset_view.py @@ -0,0 +1,193 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import policy +from google.ads.googleads.v24.enums.types import asset_field_type +from google.ads.googleads.v24.enums.types import asset_performance_label +from google.ads.googleads.v24.enums.types import asset_source +from google.ads.googleads.v24.enums.types import policy_approval_status +from google.ads.googleads.v24.enums.types import policy_review_status +from google.ads.googleads.v24.enums.types import served_asset_field_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupAdAssetView", + "AdGroupAdAssetPolicySummary", + }, +) + + +class AdGroupAdAssetView(proto.Message): + r"""Represents a link between an AdGroupAd and an Asset. This view + provides insights into the performance of assets within specific + ads. + + AdGroupAdAssetView supports the following ad types: + + - App Ads + - Demand Gen campaigns + - Responsive Search Ads + + It does not support Responsive Display Ads. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the ad group ad asset + view. Ad group ad asset view resource names have the form + (Before V4): + + ``customers/{customer_id}/adGroupAdAssets/{AdGroupAdAsset.ad_group_id}~{AdGroupAdAsset.ad.ad_id}~{AdGroupAdAsset.asset_id}~{AdGroupAdAsset.field_type}`` + + Ad group ad asset view resource names have the form + (Beginning from V4): + + ``customers/{customer_id}/adGroupAdAssetViews/{AdGroupAdAsset.ad_group_id}~{AdGroupAdAsset.ad_id}~{AdGroupAdAsset.asset_id}~{AdGroupAdAsset.field_type}`` + ad_group_ad (str): + Output only. The ad group ad to which the + asset is linked. + + This field is a member of `oneof`_ ``_ad_group_ad``. + asset (str): + Output only. The asset which is linked to the + ad group ad. + + This field is a member of `oneof`_ ``_asset``. + field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + Output only. Role that the asset takes in the + ad. + enabled (bool): + Output only. The status between the asset and + the latest version of the ad. If true, the asset + is linked to the latest version of the ad. If + false, it means the link once existed but has + been removed and is no longer present in the + latest version of the ad. + + This field is a member of `oneof`_ ``_enabled``. + policy_summary (google.ads.googleads.v24.resources.types.AdGroupAdAssetPolicySummary): + Output only. Policy information for the ad + group ad asset. + performance_label (google.ads.googleads.v24.enums.types.AssetPerformanceLabelEnum.AssetPerformanceLabel): + Output only. Performance of an asset linkage. + pinned_field (google.ads.googleads.v24.enums.types.ServedAssetFieldTypeEnum.ServedAssetFieldType): + Output only. Pinned field. + source (google.ads.googleads.v24.enums.types.AssetSourceEnum.AssetSource): + Output only. Source of the ad group ad asset. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_ad: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + asset: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + field_type: asset_field_type.AssetFieldTypeEnum.AssetFieldType = ( + proto.Field( + proto.ENUM, + number=2, + enum=asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + ) + enabled: bool = proto.Field( + proto.BOOL, + number=8, + optional=True, + ) + policy_summary: "AdGroupAdAssetPolicySummary" = proto.Field( + proto.MESSAGE, + number=3, + message="AdGroupAdAssetPolicySummary", + ) + performance_label: ( + asset_performance_label.AssetPerformanceLabelEnum.AssetPerformanceLabel + ) = proto.Field( + proto.ENUM, + number=4, + enum=asset_performance_label.AssetPerformanceLabelEnum.AssetPerformanceLabel, + ) + pinned_field: ( + served_asset_field_type.ServedAssetFieldTypeEnum.ServedAssetFieldType + ) = proto.Field( + proto.ENUM, + number=11, + enum=served_asset_field_type.ServedAssetFieldTypeEnum.ServedAssetFieldType, + ) + source: asset_source.AssetSourceEnum.AssetSource = proto.Field( + proto.ENUM, + number=12, + enum=asset_source.AssetSourceEnum.AssetSource, + ) + + +class AdGroupAdAssetPolicySummary(proto.Message): + r"""Contains policy information for an ad group ad asset. + + Attributes: + policy_topic_entries (MutableSequence[google.ads.googleads.v24.common.types.PolicyTopicEntry]): + Output only. The list of policy findings for + the ad group ad asset. + review_status (google.ads.googleads.v24.enums.types.PolicyReviewStatusEnum.PolicyReviewStatus): + Output only. Where in the review process this + ad group ad asset is. + approval_status (google.ads.googleads.v24.enums.types.PolicyApprovalStatusEnum.PolicyApprovalStatus): + Output only. The overall approval status of + this ad group ad asset, calculated based on the + status of its individual policy topic entries. + """ + + policy_topic_entries: MutableSequence[policy.PolicyTopicEntry] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=policy.PolicyTopicEntry, + ) + ) + review_status: ( + policy_review_status.PolicyReviewStatusEnum.PolicyReviewStatus + ) = proto.Field( + proto.ENUM, + number=2, + enum=policy_review_status.PolicyReviewStatusEnum.PolicyReviewStatus, + ) + approval_status: ( + policy_approval_status.PolicyApprovalStatusEnum.PolicyApprovalStatus + ) = proto.Field( + proto.ENUM, + number=3, + enum=policy_approval_status.PolicyApprovalStatusEnum.PolicyApprovalStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_ad_label.py b/google/ads/googleads/v24/resources/types/ad_group_ad_label.py new file mode 100644 index 000000000..89d8fda6f --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_ad_label.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupAdLabel", + }, +) + + +class AdGroupAdLabel(proto.Message): + r"""A relationship between an ad group ad and a label. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the ad group ad label. Ad + group ad label resource names have the form: + ``customers/{customer_id}/adGroupAdLabels/{ad_group_id}~{ad_id}~{label_id}`` + ad_group_ad (str): + Immutable. The ad group ad to which the label + is attached. + + This field is a member of `oneof`_ ``_ad_group_ad``. + label (str): + Immutable. The label assigned to the ad group + ad. + + This field is a member of `oneof`_ ``_label``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_ad: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + label: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_asset.py b/google/ads/googleads/v24/resources/types/ad_group_asset.py new file mode 100644 index 000000000..908486730 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_asset.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import asset_policy +from google.ads.googleads.v24.enums.types import asset_field_type +from google.ads.googleads.v24.enums.types import asset_link_primary_status +from google.ads.googleads.v24.enums.types import ( + asset_link_primary_status_reason, +) +from google.ads.googleads.v24.enums.types import asset_link_status +from google.ads.googleads.v24.enums.types import asset_source + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupAsset", + }, +) + + +class AdGroupAsset(proto.Message): + r"""A link between an ad group and an asset. + + Attributes: + resource_name (str): + Immutable. The resource name of the ad group asset. + AdGroupAsset resource names have the form: + + ``customers/{customer_id}/adGroupAssets/{ad_group_id}~{asset_id}~{field_type}`` + ad_group (str): + Required. Immutable. The ad group to which + the asset is linked. + asset (str): + Required. Immutable. The asset which is + linked to the ad group. + field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + Required. Immutable. Role that the asset + takes under the linked ad group. + source (google.ads.googleads.v24.enums.types.AssetSourceEnum.AssetSource): + Output only. Source of the adgroup asset + link. + status (google.ads.googleads.v24.enums.types.AssetLinkStatusEnum.AssetLinkStatus): + Status of the ad group asset. + primary_status (google.ads.googleads.v24.enums.types.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus): + Output only. Provides the PrimaryStatus of + this asset link. Primary status is meant + essentially to differentiate between the plain + "status" field, which has advertiser set values + of enabled, paused, or removed. The primary + status takes into account other signals (for + assets its mainly policy and quality approvals) + to come up with a more comprehensive status to + indicate its serving state. + primary_status_details (MutableSequence[google.ads.googleads.v24.common.types.AssetLinkPrimaryStatusDetails]): + Output only. Provides the details of the + primary status and its associated reasons. + primary_status_reasons (MutableSequence[google.ads.googleads.v24.enums.types.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason]): + Output only. Provides a list of reasons for + why an asset is not serving or not serving at + full capacity. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group: str = proto.Field( + proto.STRING, + number=2, + ) + asset: str = proto.Field( + proto.STRING, + number=3, + ) + field_type: asset_field_type.AssetFieldTypeEnum.AssetFieldType = ( + proto.Field( + proto.ENUM, + number=4, + enum=asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + ) + source: asset_source.AssetSourceEnum.AssetSource = proto.Field( + proto.ENUM, + number=6, + enum=asset_source.AssetSourceEnum.AssetSource, + ) + status: asset_link_status.AssetLinkStatusEnum.AssetLinkStatus = proto.Field( + proto.ENUM, + number=5, + enum=asset_link_status.AssetLinkStatusEnum.AssetLinkStatus, + ) + primary_status: ( + asset_link_primary_status.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus + ) = proto.Field( + proto.ENUM, + number=7, + enum=asset_link_primary_status.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus, + ) + primary_status_details: MutableSequence[ + asset_policy.AssetLinkPrimaryStatusDetails + ] = proto.RepeatedField( + proto.MESSAGE, + number=8, + message=asset_policy.AssetLinkPrimaryStatusDetails, + ) + primary_status_reasons: MutableSequence[ + asset_link_primary_status_reason.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason + ] = proto.RepeatedField( + proto.ENUM, + number=9, + enum=asset_link_primary_status_reason.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_asset_set.py b/google/ads/googleads/v24/resources/types/ad_group_asset_set.py new file mode 100644 index 000000000..56dc9c278 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_asset_set.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import asset_set_link_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupAssetSet", + }, +) + + +class AdGroupAssetSet(proto.Message): + r"""AdGroupAssetSet is the linkage between an ad group and an + asset set. Creating an AdGroupAssetSet links an asset set with + an ad group. + + Attributes: + resource_name (str): + Immutable. The resource name of the ad group asset set. Ad + group asset set resource names have the form: + + ``customers/{customer_id}/adGroupAssetSets/{ad_group_id}~{asset_set_id}`` + ad_group (str): + Immutable. The ad group to which this asset + set is linked. + asset_set (str): + Immutable. The asset set which is linked to + the ad group. + status (google.ads.googleads.v24.enums.types.AssetSetLinkStatusEnum.AssetSetLinkStatus): + Output only. The status of the ad group asset + set. Read-only. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group: str = proto.Field( + proto.STRING, + number=2, + ) + asset_set: str = proto.Field( + proto.STRING, + number=3, + ) + status: asset_set_link_status.AssetSetLinkStatusEnum.AssetSetLinkStatus = ( + proto.Field( + proto.ENUM, + number=4, + enum=asset_set_link_status.AssetSetLinkStatusEnum.AssetSetLinkStatus, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_audience_view.py b/google/ads/googleads/v24/resources/types/ad_group_audience_view.py new file mode 100644 index 000000000..410535aa5 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_audience_view.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupAudienceView", + }, +) + + +class AdGroupAudienceView(proto.Message): + r"""An ad group audience view. + Includes performance data from interests and remarketing lists + for Display Network and YouTube Network ads, and remarketing + lists for search ads (RLSA), aggregated at the audience level. + + Attributes: + resource_name (str): + Output only. The resource name of the ad group audience + view. Ad group audience view resource names have the form: + + ``customers/{customer_id}/adGroupAudienceViews/{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_bid_modifier.py b/google/ads/googleads/v24/resources/types/ad_group_bid_modifier.py new file mode 100644 index 000000000..22023e791 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_bid_modifier.py @@ -0,0 +1,184 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.enums.types import ( + bid_modifier_source as gage_bid_modifier_source, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupBidModifier", + }, +) + + +class AdGroupBidModifier(proto.Message): + r"""Represents an ad group bid modifier. + + 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: + resource_name (str): + Immutable. The resource name of the ad group bid modifier. + Ad group bid modifier resource names have the form: + + ``customers/{customer_id}/adGroupBidModifiers/{ad_group_id}~{criterion_id}`` + ad_group (str): + Immutable. The ad group to which this + criterion belongs. + + This field is a member of `oneof`_ ``_ad_group``. + criterion_id (int): + Output only. The ID of the criterion to bid + modify. + This field is ignored for mutates. + + This field is a member of `oneof`_ ``_criterion_id``. + bid_modifier (float): + The modifier for the bid when the criterion + matches. The modifier must be in the range: 0.1 + - 10.0. Use 0 to opt out of a Device type. + + This field is a member of `oneof`_ ``_bid_modifier``. + base_ad_group (str): + Output only. The base ad group from which this draft/trial + adgroup bid modifier was created. If ad_group is a base ad + group then this field will be equal to ad_group. If the ad + group was created in the draft or trial and has no + corresponding base ad group, then this field will be null. + This field is readonly. + + This field is a member of `oneof`_ ``_base_ad_group``. + bid_modifier_source (google.ads.googleads.v24.enums.types.BidModifierSourceEnum.BidModifierSource): + Output only. Bid modifier source. + hotel_date_selection_type (google.ads.googleads.v24.common.types.HotelDateSelectionTypeInfo): + Immutable. Criterion for hotel date selection + (default dates versus user selected). + + This field is a member of `oneof`_ ``criterion``. + hotel_advance_booking_window (google.ads.googleads.v24.common.types.HotelAdvanceBookingWindowInfo): + Immutable. Criterion for number of days prior + to the stay the booking is being made. + + This field is a member of `oneof`_ ``criterion``. + hotel_length_of_stay (google.ads.googleads.v24.common.types.HotelLengthOfStayInfo): + Immutable. Criterion for length of hotel stay + in nights. + + This field is a member of `oneof`_ ``criterion``. + hotel_check_in_day (google.ads.googleads.v24.common.types.HotelCheckInDayInfo): + Immutable. Criterion for day of the week the + booking is for. + + This field is a member of `oneof`_ ``criterion``. + device (google.ads.googleads.v24.common.types.DeviceInfo): + Immutable. A device criterion. + + This field is a member of `oneof`_ ``criterion``. + hotel_check_in_date_range (google.ads.googleads.v24.common.types.HotelCheckInDateRangeInfo): + Immutable. Criterion for a hotel check-in + date range. + + This field is a member of `oneof`_ ``criterion``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + criterion_id: int = proto.Field( + proto.INT64, + number=14, + optional=True, + ) + bid_modifier: float = proto.Field( + proto.DOUBLE, + number=15, + optional=True, + ) + base_ad_group: str = proto.Field( + proto.STRING, + number=16, + optional=True, + ) + bid_modifier_source: ( + gage_bid_modifier_source.BidModifierSourceEnum.BidModifierSource + ) = proto.Field( + proto.ENUM, + number=10, + enum=gage_bid_modifier_source.BidModifierSourceEnum.BidModifierSource, + ) + hotel_date_selection_type: criteria.HotelDateSelectionTypeInfo = ( + proto.Field( + proto.MESSAGE, + number=5, + oneof="criterion", + message=criteria.HotelDateSelectionTypeInfo, + ) + ) + hotel_advance_booking_window: criteria.HotelAdvanceBookingWindowInfo = ( + proto.Field( + proto.MESSAGE, + number=6, + oneof="criterion", + message=criteria.HotelAdvanceBookingWindowInfo, + ) + ) + hotel_length_of_stay: criteria.HotelLengthOfStayInfo = proto.Field( + proto.MESSAGE, + number=7, + oneof="criterion", + message=criteria.HotelLengthOfStayInfo, + ) + hotel_check_in_day: criteria.HotelCheckInDayInfo = proto.Field( + proto.MESSAGE, + number=8, + oneof="criterion", + message=criteria.HotelCheckInDayInfo, + ) + device: criteria.DeviceInfo = proto.Field( + proto.MESSAGE, + number=11, + oneof="criterion", + message=criteria.DeviceInfo, + ) + hotel_check_in_date_range: criteria.HotelCheckInDateRangeInfo = proto.Field( + proto.MESSAGE, + number=17, + oneof="criterion", + message=criteria.HotelCheckInDateRangeInfo, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_criterion.py b/google/ads/googleads/v24/resources/types/ad_group_criterion.py new file mode 100644 index 000000000..5e0787875 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_criterion.py @@ -0,0 +1,807 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.common.types import custom_parameter +from google.ads.googleads.v24.enums.types import ( + ad_group_criterion_approval_status, +) +from google.ads.googleads.v24.enums.types import ( + ad_group_criterion_primary_status, +) +from google.ads.googleads.v24.enums.types import ( + ad_group_criterion_primary_status_reason, +) +from google.ads.googleads.v24.enums.types import ad_group_criterion_status +from google.ads.googleads.v24.enums.types import bidding_source +from google.ads.googleads.v24.enums.types import criterion_system_serving_status +from google.ads.googleads.v24.enums.types import criterion_type +from google.ads.googleads.v24.enums.types import quality_score_bucket + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupCriterion", + }, +) + + +class AdGroupCriterion(proto.Message): + r"""An ad group criterion. The ad_group_criterion report only returns + criteria that were explicitly added to the ad group. + + 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: + resource_name (str): + Immutable. The resource name of the ad group criterion. Ad + group criterion resource names have the form: + + ``customers/{customer_id}/adGroupCriteria/{ad_group_id}~{criterion_id}`` + criterion_id (int): + Output only. The ID of the criterion. + + This field is ignored for mutates. + + This field is a member of `oneof`_ ``_criterion_id``. + display_name (str): + Output only. The display name of the + criterion. + This field is ignored for mutates. + status (google.ads.googleads.v24.enums.types.AdGroupCriterionStatusEnum.AdGroupCriterionStatus): + The status of the criterion. + + This is the status of the ad group criterion + entity, set by the client. Note: UI reports may + incorporate additional information that affects + whether a criterion is eligible to run. In some + cases a criterion that's REMOVED in the API can + still show as enabled in the UI. For example, + campaigns by default show to users of all age + ranges unless excluded. The UI will show each + age range as "enabled", since they're eligible + to see the ads; but AdGroupCriterion.status will + show "removed", since no positive criterion was + added. + quality_info (google.ads.googleads.v24.resources.types.AdGroupCriterion.QualityInfo): + Output only. Information regarding the + quality of the criterion. + ad_group (str): + Immutable. The ad group to which the + criterion belongs. + + This field is a member of `oneof`_ ``_ad_group``. + type_ (google.ads.googleads.v24.enums.types.CriterionTypeEnum.CriterionType): + Output only. The type of the criterion. + negative (bool): + Immutable. Whether to target (``false``) or exclude + (``true``) the criterion. + + This field is immutable. To switch a criterion from positive + to negative, remove then re-add it. + + This field is a member of `oneof`_ ``_negative``. + system_serving_status (google.ads.googleads.v24.enums.types.CriterionSystemServingStatusEnum.CriterionSystemServingStatus): + Output only. Serving status of the criterion. + approval_status (google.ads.googleads.v24.enums.types.AdGroupCriterionApprovalStatusEnum.AdGroupCriterionApprovalStatus): + Output only. Approval status of the + criterion. + disapproval_reasons (MutableSequence[str]): + Output only. List of disapproval reasons of + the criterion. + The different reasons for disapproving a + criterion can be found here: + + https://support.google.com/adspolicy/answer/6008942 + + This field is read-only. + labels (MutableSequence[str]): + Output only. The resource names of labels + attached to this ad group criterion. + bid_modifier (float): + The modifier for the bid when the criterion + matches. The modifier must be in the range: 0.1 + - 10.0. Most targetable criteria types support + modifiers. + + This field is a member of `oneof`_ ``_bid_modifier``. + cpc_bid_micros (int): + The CPC (cost-per-click) bid. + + This field is a member of `oneof`_ ``_cpc_bid_micros``. + cpm_bid_micros (int): + The CPM (cost-per-thousand viewable + impressions) bid. + + This field is a member of `oneof`_ ``_cpm_bid_micros``. + cpv_bid_micros (int): + The CPV (cost-per-view) bid. + + This field is a member of `oneof`_ ``_cpv_bid_micros``. + percent_cpc_bid_micros (int): + The CPC bid amount, expressed as a fraction of the + advertised price for some good or service. The valid range + for the fraction is [0,1) and the value stored here is + 1,000,000 \* [fraction]. + + This field is a member of `oneof`_ ``_percent_cpc_bid_micros``. + effective_cpc_bid_micros (int): + Output only. The effective CPC + (cost-per-click) bid. + + This field is a member of `oneof`_ ``_effective_cpc_bid_micros``. + effective_cpm_bid_micros (int): + Output only. The effective CPM + (cost-per-thousand viewable impressions) bid. + + This field is a member of `oneof`_ ``_effective_cpm_bid_micros``. + effective_cpv_bid_micros (int): + Output only. The effective CPV + (cost-per-view) bid. + + This field is a member of `oneof`_ ``_effective_cpv_bid_micros``. + effective_percent_cpc_bid_micros (int): + Output only. The effective Percent CPC bid + amount. + + This field is a member of `oneof`_ ``_effective_percent_cpc_bid_micros``. + effective_cpc_bid_source (google.ads.googleads.v24.enums.types.BiddingSourceEnum.BiddingSource): + Output only. Source of the effective CPC bid. + effective_cpm_bid_source (google.ads.googleads.v24.enums.types.BiddingSourceEnum.BiddingSource): + Output only. Source of the effective CPM bid. + effective_cpv_bid_source (google.ads.googleads.v24.enums.types.BiddingSourceEnum.BiddingSource): + Output only. Source of the effective CPV bid. + effective_percent_cpc_bid_source (google.ads.googleads.v24.enums.types.BiddingSourceEnum.BiddingSource): + Output only. Source of the effective Percent + CPC bid. + position_estimates (google.ads.googleads.v24.resources.types.AdGroupCriterion.PositionEstimates): + Output only. Estimates for criterion bids at + various positions. + final_urls (MutableSequence[str]): + The list of possible final URLs after all + cross-domain redirects for the ad. + final_mobile_urls (MutableSequence[str]): + The list of possible final mobile URLs after + all cross-domain redirects. + final_url_suffix (str): + URL template for appending params to final + URL. + + This field is a member of `oneof`_ ``_final_url_suffix``. + tracking_url_template (str): + The URL template for constructing a tracking + URL. + + This field is a member of `oneof`_ ``_tracking_url_template``. + url_custom_parameters (MutableSequence[google.ads.googleads.v24.common.types.CustomParameter]): + The list of mappings used to substitute custom parameter + tags in a ``tracking_url_template``, ``final_urls``, or + ``mobile_final_urls``. + primary_status (google.ads.googleads.v24.enums.types.AdGroupCriterionPrimaryStatusEnum.AdGroupCriterionPrimaryStatus): + Output only. The primary status for the ad + group criterion. + + This field is a member of `oneof`_ ``_primary_status``. + primary_status_reasons (MutableSequence[google.ads.googleads.v24.enums.types.AdGroupCriterionPrimaryStatusReasonEnum.AdGroupCriterionPrimaryStatusReason]): + Output only. The primary status reasons for + the ad group criterion. + keyword (google.ads.googleads.v24.common.types.KeywordInfo): + Immutable. Keyword. + + This field is a member of `oneof`_ ``criterion``. + placement (google.ads.googleads.v24.common.types.PlacementInfo): + Immutable. Placement. + + This field is a member of `oneof`_ ``criterion``. + mobile_app_category (google.ads.googleads.v24.common.types.MobileAppCategoryInfo): + Immutable. Mobile app category. + + This field is a member of `oneof`_ ``criterion``. + mobile_application (google.ads.googleads.v24.common.types.MobileApplicationInfo): + Immutable. Mobile application. + + This field is a member of `oneof`_ ``criterion``. + listing_group (google.ads.googleads.v24.common.types.ListingGroupInfo): + Immutable. Listing group. + + This field is a member of `oneof`_ ``criterion``. + age_range (google.ads.googleads.v24.common.types.AgeRangeInfo): + Immutable. Age range. + + This field is a member of `oneof`_ ``criterion``. + gender (google.ads.googleads.v24.common.types.GenderInfo): + Immutable. Gender. + + This field is a member of `oneof`_ ``criterion``. + income_range (google.ads.googleads.v24.common.types.IncomeRangeInfo): + Immutable. Income range. + + This field is a member of `oneof`_ ``criterion``. + parental_status (google.ads.googleads.v24.common.types.ParentalStatusInfo): + Immutable. Parental status. + + This field is a member of `oneof`_ ``criterion``. + user_list (google.ads.googleads.v24.common.types.UserListInfo): + Immutable. User List. + + This field is a member of `oneof`_ ``criterion``. + youtube_video (google.ads.googleads.v24.common.types.YouTubeVideoInfo): + Immutable. YouTube Video. + + This field is a member of `oneof`_ ``criterion``. + youtube_channel (google.ads.googleads.v24.common.types.YouTubeChannelInfo): + Immutable. YouTube Channel. + + This field is a member of `oneof`_ ``criterion``. + topic (google.ads.googleads.v24.common.types.TopicInfo): + Immutable. Topic. + + This field is a member of `oneof`_ ``criterion``. + user_interest (google.ads.googleads.v24.common.types.UserInterestInfo): + Immutable. User Interest. + + This field is a member of `oneof`_ ``criterion``. + webpage (google.ads.googleads.v24.common.types.WebpageInfo): + Immutable. Webpage + + This field is a member of `oneof`_ ``criterion``. + app_payment_model (google.ads.googleads.v24.common.types.AppPaymentModelInfo): + Immutable. App Payment Model. + + This field is a member of `oneof`_ ``criterion``. + custom_affinity (google.ads.googleads.v24.common.types.CustomAffinityInfo): + Immutable. Custom Affinity. + + This field is a member of `oneof`_ ``criterion``. + custom_intent (google.ads.googleads.v24.common.types.CustomIntentInfo): + Immutable. Custom Intent. + + This field is a member of `oneof`_ ``criterion``. + custom_audience (google.ads.googleads.v24.common.types.CustomAudienceInfo): + Immutable. Custom Audience. + + This field is a member of `oneof`_ ``criterion``. + combined_audience (google.ads.googleads.v24.common.types.CombinedAudienceInfo): + Immutable. Combined Audience. + + This field is a member of `oneof`_ ``criterion``. + audience (google.ads.googleads.v24.common.types.AudienceInfo): + Immutable. Audience. + + This field is a member of `oneof`_ ``criterion``. + location (google.ads.googleads.v24.common.types.LocationInfo): + Immutable. Location. + + This field is a member of `oneof`_ ``criterion``. + language (google.ads.googleads.v24.common.types.LanguageInfo): + Immutable. Language. + + This field is a member of `oneof`_ ``criterion``. + life_event (google.ads.googleads.v24.common.types.LifeEventInfo): + Immutable. Life event campaign criterion. + + This field is a member of `oneof`_ ``criterion``. + video_lineup (google.ads.googleads.v24.common.types.VideoLineupInfo): + Immutable. Video lineup criterion. + + This field is a member of `oneof`_ ``criterion``. + extended_demographic (google.ads.googleads.v24.common.types.ExtendedDemographicInfo): + Immutable. Extended demographic criterion. + + This field is a member of `oneof`_ ``criterion``. + brand_list (google.ads.googleads.v24.common.types.BrandListInfo): + Immutable. Brand list criterion. + + This field is a member of `oneof`_ ``criterion``. + vertical_ads_item_group_rule_list (google.ads.googleads.v24.common.types.VerticalAdsItemGroupRuleListInfo): + Immutable. Vertical ads item group rule list + criterion. + + This field is a member of `oneof`_ ``criterion``. + retail_filter_bundle (google.ads.googleads.v24.common.types.RetailFilterBundle): + Immutable. Retail Filter Bundle. + + This field is a member of `oneof`_ ``criterion``. + """ + + class QualityInfo(proto.Message): + r"""A container for ad group criterion quality information. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + quality_score (int): + Output only. The quality score. + + This field may not be populated if Google does + not have enough information to determine a + value. + + This field is a member of `oneof`_ ``_quality_score``. + creative_quality_score (google.ads.googleads.v24.enums.types.QualityScoreBucketEnum.QualityScoreBucket): + Output only. The performance of the ad + compared to other advertisers. + post_click_quality_score (google.ads.googleads.v24.enums.types.QualityScoreBucketEnum.QualityScoreBucket): + Output only. The quality score of the landing + page. + search_predicted_ctr (google.ads.googleads.v24.enums.types.QualityScoreBucketEnum.QualityScoreBucket): + Output only. The click-through rate compared + to that of other advertisers. + """ + + quality_score: int = proto.Field( + proto.INT32, + number=5, + optional=True, + ) + creative_quality_score: ( + quality_score_bucket.QualityScoreBucketEnum.QualityScoreBucket + ) = proto.Field( + proto.ENUM, + number=2, + enum=quality_score_bucket.QualityScoreBucketEnum.QualityScoreBucket, + ) + post_click_quality_score: ( + quality_score_bucket.QualityScoreBucketEnum.QualityScoreBucket + ) = proto.Field( + proto.ENUM, + number=3, + enum=quality_score_bucket.QualityScoreBucketEnum.QualityScoreBucket, + ) + search_predicted_ctr: ( + quality_score_bucket.QualityScoreBucketEnum.QualityScoreBucket + ) = proto.Field( + proto.ENUM, + number=4, + enum=quality_score_bucket.QualityScoreBucketEnum.QualityScoreBucket, + ) + + class PositionEstimates(proto.Message): + r"""Estimates for criterion bids at various positions. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + first_page_cpc_micros (int): + Output only. The estimate of the CPC bid + required for ad to be shown on first page of + search results. + + This field is a member of `oneof`_ ``_first_page_cpc_micros``. + first_position_cpc_micros (int): + Output only. The estimate of the CPC bid + required for ad to be displayed in first + position, at the top of the first page of search + results. + + This field is a member of `oneof`_ ``_first_position_cpc_micros``. + top_of_page_cpc_micros (int): + Output only. The estimate of the CPC bid + required for ad to be displayed at the top of + the first page of search results. + + This field is a member of `oneof`_ ``_top_of_page_cpc_micros``. + estimated_add_clicks_at_first_position_cpc (int): + Output only. Estimate of how many clicks per week you might + get by changing your keyword bid to the value in + first_position_cpc_micros. + + This field is a member of `oneof`_ ``_estimated_add_clicks_at_first_position_cpc``. + estimated_add_cost_at_first_position_cpc (int): + Output only. Estimate of how your cost per week might change + when changing your keyword bid to the value in + first_position_cpc_micros. + + This field is a member of `oneof`_ ``_estimated_add_cost_at_first_position_cpc``. + """ + + first_page_cpc_micros: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + first_position_cpc_micros: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + top_of_page_cpc_micros: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + estimated_add_clicks_at_first_position_cpc: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + estimated_add_cost_at_first_position_cpc: int = proto.Field( + proto.INT64, + number=10, + optional=True, + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + criterion_id: int = proto.Field( + proto.INT64, + number=56, + optional=True, + ) + display_name: str = proto.Field( + proto.STRING, + number=77, + ) + status: ( + ad_group_criterion_status.AdGroupCriterionStatusEnum.AdGroupCriterionStatus + ) = proto.Field( + proto.ENUM, + number=3, + enum=ad_group_criterion_status.AdGroupCriterionStatusEnum.AdGroupCriterionStatus, + ) + quality_info: QualityInfo = proto.Field( + proto.MESSAGE, + number=4, + message=QualityInfo, + ) + ad_group: str = proto.Field( + proto.STRING, + number=57, + optional=True, + ) + type_: criterion_type.CriterionTypeEnum.CriterionType = proto.Field( + proto.ENUM, + number=25, + enum=criterion_type.CriterionTypeEnum.CriterionType, + ) + negative: bool = proto.Field( + proto.BOOL, + number=58, + optional=True, + ) + system_serving_status: ( + criterion_system_serving_status.CriterionSystemServingStatusEnum.CriterionSystemServingStatus + ) = proto.Field( + proto.ENUM, + number=52, + enum=criterion_system_serving_status.CriterionSystemServingStatusEnum.CriterionSystemServingStatus, + ) + approval_status: ( + ad_group_criterion_approval_status.AdGroupCriterionApprovalStatusEnum.AdGroupCriterionApprovalStatus + ) = proto.Field( + proto.ENUM, + number=53, + enum=ad_group_criterion_approval_status.AdGroupCriterionApprovalStatusEnum.AdGroupCriterionApprovalStatus, + ) + disapproval_reasons: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=59, + ) + labels: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=60, + ) + bid_modifier: float = proto.Field( + proto.DOUBLE, + number=61, + optional=True, + ) + cpc_bid_micros: int = proto.Field( + proto.INT64, + number=62, + optional=True, + ) + cpm_bid_micros: int = proto.Field( + proto.INT64, + number=63, + optional=True, + ) + cpv_bid_micros: int = proto.Field( + proto.INT64, + number=64, + optional=True, + ) + percent_cpc_bid_micros: int = proto.Field( + proto.INT64, + number=65, + optional=True, + ) + effective_cpc_bid_micros: int = proto.Field( + proto.INT64, + number=66, + optional=True, + ) + effective_cpm_bid_micros: int = proto.Field( + proto.INT64, + number=67, + optional=True, + ) + effective_cpv_bid_micros: int = proto.Field( + proto.INT64, + number=68, + optional=True, + ) + effective_percent_cpc_bid_micros: int = proto.Field( + proto.INT64, + number=69, + optional=True, + ) + effective_cpc_bid_source: bidding_source.BiddingSourceEnum.BiddingSource = ( + proto.Field( + proto.ENUM, + number=21, + enum=bidding_source.BiddingSourceEnum.BiddingSource, + ) + ) + effective_cpm_bid_source: bidding_source.BiddingSourceEnum.BiddingSource = ( + proto.Field( + proto.ENUM, + number=22, + enum=bidding_source.BiddingSourceEnum.BiddingSource, + ) + ) + effective_cpv_bid_source: bidding_source.BiddingSourceEnum.BiddingSource = ( + proto.Field( + proto.ENUM, + number=23, + enum=bidding_source.BiddingSourceEnum.BiddingSource, + ) + ) + effective_percent_cpc_bid_source: ( + bidding_source.BiddingSourceEnum.BiddingSource + ) = proto.Field( + proto.ENUM, + number=35, + enum=bidding_source.BiddingSourceEnum.BiddingSource, + ) + position_estimates: PositionEstimates = proto.Field( + proto.MESSAGE, + number=10, + message=PositionEstimates, + ) + final_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=70, + ) + final_mobile_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=71, + ) + final_url_suffix: str = proto.Field( + proto.STRING, + number=72, + optional=True, + ) + tracking_url_template: str = proto.Field( + proto.STRING, + number=73, + optional=True, + ) + url_custom_parameters: MutableSequence[custom_parameter.CustomParameter] = ( + proto.RepeatedField( + proto.MESSAGE, + number=14, + message=custom_parameter.CustomParameter, + ) + ) + primary_status: ( + ad_group_criterion_primary_status.AdGroupCriterionPrimaryStatusEnum.AdGroupCriterionPrimaryStatus + ) = proto.Field( + proto.ENUM, + number=85, + optional=True, + enum=ad_group_criterion_primary_status.AdGroupCriterionPrimaryStatusEnum.AdGroupCriterionPrimaryStatus, + ) + primary_status_reasons: MutableSequence[ + ad_group_criterion_primary_status_reason.AdGroupCriterionPrimaryStatusReasonEnum.AdGroupCriterionPrimaryStatusReason + ] = proto.RepeatedField( + proto.ENUM, + number=86, + enum=ad_group_criterion_primary_status_reason.AdGroupCriterionPrimaryStatusReasonEnum.AdGroupCriterionPrimaryStatusReason, + ) + keyword: criteria.KeywordInfo = proto.Field( + proto.MESSAGE, + number=27, + oneof="criterion", + message=criteria.KeywordInfo, + ) + placement: criteria.PlacementInfo = proto.Field( + proto.MESSAGE, + number=28, + oneof="criterion", + message=criteria.PlacementInfo, + ) + mobile_app_category: criteria.MobileAppCategoryInfo = proto.Field( + proto.MESSAGE, + number=29, + oneof="criterion", + message=criteria.MobileAppCategoryInfo, + ) + mobile_application: criteria.MobileApplicationInfo = proto.Field( + proto.MESSAGE, + number=30, + oneof="criterion", + message=criteria.MobileApplicationInfo, + ) + listing_group: criteria.ListingGroupInfo = proto.Field( + proto.MESSAGE, + number=32, + oneof="criterion", + message=criteria.ListingGroupInfo, + ) + age_range: criteria.AgeRangeInfo = proto.Field( + proto.MESSAGE, + number=36, + oneof="criterion", + message=criteria.AgeRangeInfo, + ) + gender: criteria.GenderInfo = proto.Field( + proto.MESSAGE, + number=37, + oneof="criterion", + message=criteria.GenderInfo, + ) + income_range: criteria.IncomeRangeInfo = proto.Field( + proto.MESSAGE, + number=38, + oneof="criterion", + message=criteria.IncomeRangeInfo, + ) + parental_status: criteria.ParentalStatusInfo = proto.Field( + proto.MESSAGE, + number=39, + oneof="criterion", + message=criteria.ParentalStatusInfo, + ) + user_list: criteria.UserListInfo = proto.Field( + proto.MESSAGE, + number=42, + oneof="criterion", + message=criteria.UserListInfo, + ) + youtube_video: criteria.YouTubeVideoInfo = proto.Field( + proto.MESSAGE, + number=40, + oneof="criterion", + message=criteria.YouTubeVideoInfo, + ) + youtube_channel: criteria.YouTubeChannelInfo = proto.Field( + proto.MESSAGE, + number=41, + oneof="criterion", + message=criteria.YouTubeChannelInfo, + ) + topic: criteria.TopicInfo = proto.Field( + proto.MESSAGE, + number=43, + oneof="criterion", + message=criteria.TopicInfo, + ) + user_interest: criteria.UserInterestInfo = proto.Field( + proto.MESSAGE, + number=45, + oneof="criterion", + message=criteria.UserInterestInfo, + ) + webpage: criteria.WebpageInfo = proto.Field( + proto.MESSAGE, + number=46, + oneof="criterion", + message=criteria.WebpageInfo, + ) + app_payment_model: criteria.AppPaymentModelInfo = proto.Field( + proto.MESSAGE, + number=47, + oneof="criterion", + message=criteria.AppPaymentModelInfo, + ) + custom_affinity: criteria.CustomAffinityInfo = proto.Field( + proto.MESSAGE, + number=48, + oneof="criterion", + message=criteria.CustomAffinityInfo, + ) + custom_intent: criteria.CustomIntentInfo = proto.Field( + proto.MESSAGE, + number=49, + oneof="criterion", + message=criteria.CustomIntentInfo, + ) + custom_audience: criteria.CustomAudienceInfo = proto.Field( + proto.MESSAGE, + number=74, + oneof="criterion", + message=criteria.CustomAudienceInfo, + ) + combined_audience: criteria.CombinedAudienceInfo = proto.Field( + proto.MESSAGE, + number=75, + oneof="criterion", + message=criteria.CombinedAudienceInfo, + ) + audience: criteria.AudienceInfo = proto.Field( + proto.MESSAGE, + number=79, + oneof="criterion", + message=criteria.AudienceInfo, + ) + location: criteria.LocationInfo = proto.Field( + proto.MESSAGE, + number=82, + oneof="criterion", + message=criteria.LocationInfo, + ) + language: criteria.LanguageInfo = proto.Field( + proto.MESSAGE, + number=83, + oneof="criterion", + message=criteria.LanguageInfo, + ) + life_event: criteria.LifeEventInfo = proto.Field( + proto.MESSAGE, + number=84, + oneof="criterion", + message=criteria.LifeEventInfo, + ) + video_lineup: criteria.VideoLineupInfo = proto.Field( + proto.MESSAGE, + number=88, + oneof="criterion", + message=criteria.VideoLineupInfo, + ) + extended_demographic: criteria.ExtendedDemographicInfo = proto.Field( + proto.MESSAGE, + number=90, + oneof="criterion", + message=criteria.ExtendedDemographicInfo, + ) + brand_list: criteria.BrandListInfo = proto.Field( + proto.MESSAGE, + number=89, + oneof="criterion", + message=criteria.BrandListInfo, + ) + vertical_ads_item_group_rule_list: ( + criteria.VerticalAdsItemGroupRuleListInfo + ) = proto.Field( + proto.MESSAGE, + number=91, + oneof="criterion", + message=criteria.VerticalAdsItemGroupRuleListInfo, + ) + retail_filter_bundle: criteria.RetailFilterBundle = proto.Field( + proto.MESSAGE, + number=180, + oneof="criterion", + message=criteria.RetailFilterBundle, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_criterion_customizer.py b/google/ads/googleads/v24/resources/types/ad_group_criterion_customizer.py new file mode 100644 index 000000000..f6fa83051 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_criterion_customizer.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import customizer_value +from google.ads.googleads.v24.enums.types import customizer_value_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupCriterionCustomizer", + }, +) + + +class AdGroupCriterionCustomizer(proto.Message): + r"""A customizer value for the associated CustomizerAttribute at + the AdGroupCriterion level. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the ad group criterion + customizer. Ad group criterion customizer resource names + have the form: + + ``customers/{customer_id}/adGroupCriterionCustomizers/{ad_group_id}~{criterion_id}~{customizer_attribute_id}`` + ad_group_criterion (str): + Immutable. The ad group criterion to which + the customizer attribute is linked. It must be a + keyword criterion. + + This field is a member of `oneof`_ ``_ad_group_criterion``. + customizer_attribute (str): + Required. Immutable. The customizer attribute + which is linked to the ad group criterion. + status (google.ads.googleads.v24.enums.types.CustomizerValueStatusEnum.CustomizerValueStatus): + Output only. The status of the ad group + criterion customizer. + value (google.ads.googleads.v24.common.types.CustomizerValue): + Required. The value to associate with the + customizer attribute at this level. The value + must be of the type specified for the + CustomizerAttribute. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_criterion: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + customizer_attribute: str = proto.Field( + proto.STRING, + number=3, + ) + status: ( + customizer_value_status.CustomizerValueStatusEnum.CustomizerValueStatus + ) = proto.Field( + proto.ENUM, + number=4, + enum=customizer_value_status.CustomizerValueStatusEnum.CustomizerValueStatus, + ) + value: customizer_value.CustomizerValue = proto.Field( + proto.MESSAGE, + number=5, + message=customizer_value.CustomizerValue, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_criterion_label.py b/google/ads/googleads/v24/resources/types/ad_group_criterion_label.py new file mode 100644 index 000000000..9b7b5d7de --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_criterion_label.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupCriterionLabel", + }, +) + + +class AdGroupCriterionLabel(proto.Message): + r"""A relationship between an ad group criterion and a label. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the ad group criterion + label. Ad group criterion label resource names have the + form: + ``customers/{customer_id}/adGroupCriterionLabels/{ad_group_id}~{criterion_id}~{label_id}`` + ad_group_criterion (str): + Immutable. The ad group criterion to which + the label is attached. + + This field is a member of `oneof`_ ``_ad_group_criterion``. + label (str): + Immutable. The label assigned to the ad group + criterion. + + This field is a member of `oneof`_ ``_label``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_criterion: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + label: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_criterion_simulation.py b/google/ads/googleads/v24/resources/types/ad_group_criterion_simulation.py new file mode 100644 index 000000000..78d1b6b01 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_criterion_simulation.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import simulation +from google.ads.googleads.v24.enums.types import simulation_modification_method +from google.ads.googleads.v24.enums.types import simulation_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupCriterionSimulation", + }, +) + + +class AdGroupCriterionSimulation(proto.Message): + r"""An ad group criterion simulation. Supported combinations of + advertising channel type, criterion type, simulation type, and + simulation modification method are detailed below respectively. + Hotel AdGroupCriterion simulation operations starting in V5. + + 1. DISPLAY - KEYWORD - CPC_BID - UNIFORM + 2. SEARCH - KEYWORD - CPC_BID - UNIFORM + 3. SHOPPING - LISTING_GROUP - CPC_BID - UNIFORM + 4. HOTEL - LISTING_GROUP - CPC_BID - UNIFORM + 5. HOTEL - LISTING_GROUP - PERCENT_CPC_BID - UNIFORM + + 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: + resource_name (str): + Output only. The resource name of the ad group criterion + simulation. Ad group criterion simulation resource names + have the form: + + ``customers/{customer_id}/adGroupCriterionSimulations/{ad_group_id}~{criterion_id}~{type}~{modification_method}~{start_date}~{end_date}`` + ad_group_id (int): + Output only. AdGroup ID of the simulation. + + This field is a member of `oneof`_ ``_ad_group_id``. + criterion_id (int): + Output only. Criterion ID of the simulation. + + This field is a member of `oneof`_ ``_criterion_id``. + type_ (google.ads.googleads.v24.enums.types.SimulationTypeEnum.SimulationType): + Output only. The field that the simulation + modifies. + modification_method (google.ads.googleads.v24.enums.types.SimulationModificationMethodEnum.SimulationModificationMethod): + Output only. How the simulation modifies the + field. + start_date (str): + Output only. First day on which the + simulation is based, in YYYY-MM-DD format. + + This field is a member of `oneof`_ ``_start_date``. + end_date (str): + Output only. Last day on which the simulation + is based, in YYYY-MM-DD format. + + This field is a member of `oneof`_ ``_end_date``. + cpc_bid_point_list (google.ads.googleads.v24.common.types.CpcBidSimulationPointList): + Output only. Simulation points if the simulation type is + CPC_BID. + + This field is a member of `oneof`_ ``point_list``. + percent_cpc_bid_point_list (google.ads.googleads.v24.common.types.PercentCpcBidSimulationPointList): + Output only. Simulation points if the simulation type is + PERCENT_CPC_BID. + + This field is a member of `oneof`_ ``point_list``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_id: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + criterion_id: int = proto.Field( + proto.INT64, + number=10, + optional=True, + ) + type_: simulation_type.SimulationTypeEnum.SimulationType = proto.Field( + proto.ENUM, + number=4, + enum=simulation_type.SimulationTypeEnum.SimulationType, + ) + modification_method: ( + simulation_modification_method.SimulationModificationMethodEnum.SimulationModificationMethod + ) = proto.Field( + proto.ENUM, + number=5, + enum=simulation_modification_method.SimulationModificationMethodEnum.SimulationModificationMethod, + ) + start_date: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + end_date: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + cpc_bid_point_list: simulation.CpcBidSimulationPointList = proto.Field( + proto.MESSAGE, + number=8, + oneof="point_list", + message=simulation.CpcBidSimulationPointList, + ) + percent_cpc_bid_point_list: simulation.PercentCpcBidSimulationPointList = ( + proto.Field( + proto.MESSAGE, + number=13, + oneof="point_list", + message=simulation.PercentCpcBidSimulationPointList, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_customizer.py b/google/ads/googleads/v24/resources/types/ad_group_customizer.py new file mode 100644 index 000000000..f8a62dcc9 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_customizer.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import customizer_value +from google.ads.googleads.v24.enums.types import customizer_value_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupCustomizer", + }, +) + + +class AdGroupCustomizer(proto.Message): + r"""A customizer value for the associated CustomizerAttribute at + the AdGroup level. + + Attributes: + resource_name (str): + Immutable. The resource name of the ad group customizer. Ad + group customizer resource names have the form: + + ``customers/{customer_id}/adGroupCustomizers/{ad_group_id}~{customizer_attribute_id}`` + ad_group (str): + Immutable. The ad group to which the + customizer attribute is linked. + customizer_attribute (str): + Required. Immutable. The customizer attribute + which is linked to the ad group. + status (google.ads.googleads.v24.enums.types.CustomizerValueStatusEnum.CustomizerValueStatus): + Output only. The status of the ad group + customizer. + value (google.ads.googleads.v24.common.types.CustomizerValue): + Required. The value to associate with the + customizer attribute at this level. The value + must be of the type specified for the + CustomizerAttribute. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group: str = proto.Field( + proto.STRING, + number=2, + ) + customizer_attribute: str = proto.Field( + proto.STRING, + number=3, + ) + status: ( + customizer_value_status.CustomizerValueStatusEnum.CustomizerValueStatus + ) = proto.Field( + proto.ENUM, + number=4, + enum=customizer_value_status.CustomizerValueStatusEnum.CustomizerValueStatus, + ) + value: customizer_value.CustomizerValue = proto.Field( + proto.MESSAGE, + number=5, + message=customizer_value.CustomizerValue, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_label.py b/google/ads/googleads/v24/resources/types/ad_group_label.py new file mode 100644 index 000000000..70b8b3ceb --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_label.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupLabel", + }, +) + + +class AdGroupLabel(proto.Message): + r"""A relationship between an ad group and a label. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the ad group label. Ad group + label resource names have the form: + ``customers/{customer_id}/adGroupLabels/{ad_group_id}~{label_id}`` + ad_group (str): + Immutable. The ad group to which the label is + attached. + + This field is a member of `oneof`_ ``_ad_group``. + label (str): + Immutable. The label assigned to the ad + group. + + This field is a member of `oneof`_ ``_label``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + label: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_group_simulation.py b/google/ads/googleads/v24/resources/types/ad_group_simulation.py new file mode 100644 index 000000000..55edcdc96 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_group_simulation.py @@ -0,0 +1,170 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import simulation +from google.ads.googleads.v24.enums.types import simulation_modification_method +from google.ads.googleads.v24.enums.types import simulation_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdGroupSimulation", + }, +) + + +class AdGroupSimulation(proto.Message): + r"""An ad group simulation. Supported combinations of advertising + channel type, simulation type and simulation modification method is + detailed below respectively. + + 1. SEARCH - CPC_BID - DEFAULT + + 2. SEARCH - CPC_BID - UNIFORM + + 3. SEARCH - TARGET_CPA - UNIFORM + + 4. SEARCH - TARGET_ROAS - UNIFORM + + 5. DISPLAY - CPC_BID - DEFAULT + + 6. DISPLAY - CPC_BID - UNIFORM + + 7. DISPLAY - TARGET_CPA - UNIFORM + + 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: + resource_name (str): + Output only. The resource name of the ad group simulation. + Ad group simulation resource names have the form: + + ``customers/{customer_id}/adGroupSimulations/{ad_group_id}~{type}~{modification_method}~{start_date}~{end_date}`` + ad_group_id (int): + Output only. Ad group id of the simulation. + + This field is a member of `oneof`_ ``_ad_group_id``. + type_ (google.ads.googleads.v24.enums.types.SimulationTypeEnum.SimulationType): + Output only. The field that the simulation + modifies. + modification_method (google.ads.googleads.v24.enums.types.SimulationModificationMethodEnum.SimulationModificationMethod): + Output only. How the simulation modifies the + field. + start_date (str): + Output only. First day on which the + simulation is based, in YYYY-MM-DD format. + + This field is a member of `oneof`_ ``_start_date``. + end_date (str): + Output only. Last day on which the simulation + is based, in YYYY-MM-DD format + + This field is a member of `oneof`_ ``_end_date``. + cpc_bid_point_list (google.ads.googleads.v24.common.types.CpcBidSimulationPointList): + Output only. Simulation points if the simulation type is + CPC_BID. + + This field is a member of `oneof`_ ``point_list``. + cpv_bid_point_list (google.ads.googleads.v24.common.types.CpvBidSimulationPointList): + Output only. Simulation points if the simulation type is + CPV_BID. + + This field is a member of `oneof`_ ``point_list``. + target_cpa_point_list (google.ads.googleads.v24.common.types.TargetCpaSimulationPointList): + Output only. Simulation points if the simulation type is + TARGET_CPA. + + This field is a member of `oneof`_ ``point_list``. + target_roas_point_list (google.ads.googleads.v24.common.types.TargetRoasSimulationPointList): + Output only. Simulation points if the simulation type is + TARGET_ROAS. + + This field is a member of `oneof`_ ``point_list``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_id: int = proto.Field( + proto.INT64, + number=12, + optional=True, + ) + type_: simulation_type.SimulationTypeEnum.SimulationType = proto.Field( + proto.ENUM, + number=3, + enum=simulation_type.SimulationTypeEnum.SimulationType, + ) + modification_method: ( + simulation_modification_method.SimulationModificationMethodEnum.SimulationModificationMethod + ) = proto.Field( + proto.ENUM, + number=4, + enum=simulation_modification_method.SimulationModificationMethodEnum.SimulationModificationMethod, + ) + start_date: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + end_date: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + cpc_bid_point_list: simulation.CpcBidSimulationPointList = proto.Field( + proto.MESSAGE, + number=8, + oneof="point_list", + message=simulation.CpcBidSimulationPointList, + ) + cpv_bid_point_list: simulation.CpvBidSimulationPointList = proto.Field( + proto.MESSAGE, + number=10, + oneof="point_list", + message=simulation.CpvBidSimulationPointList, + ) + target_cpa_point_list: simulation.TargetCpaSimulationPointList = ( + proto.Field( + proto.MESSAGE, + number=9, + oneof="point_list", + message=simulation.TargetCpaSimulationPointList, + ) + ) + target_roas_point_list: simulation.TargetRoasSimulationPointList = ( + proto.Field( + proto.MESSAGE, + number=11, + oneof="point_list", + message=simulation.TargetRoasSimulationPointList, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_parameter.py b/google/ads/googleads/v24/resources/types/ad_parameter.py new file mode 100644 index 000000000..855f27b9a --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_parameter.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdParameter", + }, +) + + +class AdParameter(proto.Message): + r"""An ad parameter that is used to update numeric values (such as + prices or inventory levels) in any text line of an ad (including + URLs). There can be a maximum of two AdParameters per ad group + criterion. (One with parameter_index = 1 and one with + parameter_index = 2.) In the ad the parameters are referenced by a + placeholder of the form "{param#:value}". For example, + "{param1:$17}" + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the ad parameter. Ad + parameter resource names have the form: + + ``customers/{customer_id}/adParameters/{ad_group_id}~{criterion_id}~{parameter_index}`` + ad_group_criterion (str): + Immutable. The ad group criterion that this + ad parameter belongs to. + + This field is a member of `oneof`_ ``_ad_group_criterion``. + parameter_index (int): + Immutable. The unique index of this ad + parameter. Must be either 1 or 2. + + This field is a member of `oneof`_ ``_parameter_index``. + insertion_text (str): + Numeric value to insert into the ad text. The + following restrictions apply: + + - Can use comma or period as a separator, with + an optional period or comma (respectively) + for fractional values. For example, + 1,000,000.00 and 2.000.000,10 are valid. + - Can be prepended or appended with a currency + symbol. For example, $99.99 is valid. + - Can be prepended or appended with a currency + code. For example, 99.99USD and EUR200 are + valid. + - Can use '%'. For example, 1.0% and 1,0% are + valid. + - Can use plus or minus. For example, -10.99 + and 25+ are valid. + - Can use '/' between two numbers. For example + 4/1 and 0.95/0.45 are valid. + + This field is a member of `oneof`_ ``_insertion_text``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_criterion: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + parameter_index: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + insertion_text: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ad_schedule_view.py b/google/ads/googleads/v24/resources/types/ad_schedule_view.py new file mode 100644 index 000000000..50a6c8ee7 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ad_schedule_view.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AdScheduleView", + }, +) + + +class AdScheduleView(proto.Message): + r"""An ad schedule view summarizes the performance of campaigns + by AdSchedule criteria. + + Attributes: + resource_name (str): + Output only. The resource name of the ad schedule view. + AdSchedule view resource names have the form: + + ``customers/{customer_id}/adScheduleViews/{campaign_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/age_range_view.py b/google/ads/googleads/v24/resources/types/age_range_view.py new file mode 100644 index 000000000..ee70dd4c1 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/age_range_view.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AgeRangeView", + }, +) + + +class AgeRangeView(proto.Message): + r"""An age range view. + + Attributes: + resource_name (str): + Output only. The resource name of the age range view. Age + range view resource names have the form: + + ``customers/{customer_id}/ageRangeViews/{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/ai_max_search_term_ad_combination_view.py b/google/ads/googleads/v24/resources/types/ai_max_search_term_ad_combination_view.py new file mode 100644 index 000000000..d40f98790 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/ai_max_search_term_ad_combination_view.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AiMaxSearchTermAdCombinationView", + }, +) + + +class AiMaxSearchTermAdCombinationView(proto.Message): + r"""AiMaxSearchTermAdCombinationView Resource. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the AI Max Search Term Ad + Combination view AI Max Search Term Ad Combination view + resource names have the form: + + ``customers/{customer_id}/aiMaxSearchTermAdCombinationViews/{ad_group_id}~{URL-base64_search_term}~{URL-base64_landing_page}~{URL-base64_headline}`` + ad_group (str): + Output only. Ad group where the search term + served. + + This field is a member of `oneof`_ ``_ad_group``. + search_term (str): + Output only. The search term that triggered + the ad. This field is read-only. + + This field is a member of `oneof`_ ``_search_term``. + landing_page (str): + Output only. The destination URL, which was + dynamically generated. This field is read-only. + + This field is a member of `oneof`_ ``_landing_page``. + headline (str): + Output only. The concatenated string containing headline + assets for the ad. Up to three headline assets are + concatenated, separated by " \| ". This field is read-only. + + This field is a member of `oneof`_ ``_headline``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + search_term: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + landing_page: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + headline: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/android_privacy_shared_key_google_ad_group.py b/google/ads/googleads/v24/resources/types/android_privacy_shared_key_google_ad_group.py new file mode 100644 index 000000000..bff1d1762 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/android_privacy_shared_key_google_ad_group.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + android_privacy_interaction_type as gage_android_privacy_interaction_type, +) +from google.ads.googleads.v24.enums.types import ( + android_privacy_network_type as gage_android_privacy_network_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AndroidPrivacySharedKeyGoogleAdGroup", + }, +) + + +class AndroidPrivacySharedKeyGoogleAdGroup(proto.Message): + r"""An Android privacy shared key view for Google ad group key. + + Attributes: + resource_name (str): + Output only. The resource name of the Android privacy shared + key. Android privacy shared key resource names have the + form: + + ``customers/{customer_id}/androidPrivacySharedKeyGoogleAdGroups/{campaign_id}~{ad_group_id}~{android_privacy_interaction_type}~{android_privacy_network_type}~{android_privacy_interaction_date(yyyy-mm-dd)}`` + campaign_id (int): + Output only. The campaign ID used in the + share key encoding. + android_privacy_interaction_type (google.ads.googleads.v24.enums.types.AndroidPrivacyInteractionTypeEnum.AndroidPrivacyInteractionType): + Output only. The interaction type enum used + in the share key encoding. + android_privacy_interaction_date (str): + Output only. The interaction date used in the + shared key encoding in the format of + "YYYY-MM-DD" in UTC timezone. + android_privacy_network_type (google.ads.googleads.v24.enums.types.AndroidPrivacyNetworkTypeEnum.AndroidPrivacyNetworkType): + Output only. The network type enum used in + the share key encoding. + ad_group_id (int): + Output only. The ad group ID used in the + share key encoding. + shared_ad_group_key (str): + Output only. 128 bit hex string of the + encoded shared ad group key, including a '0x' + prefix. This key can be used to do a bitwise OR + operator with the aggregate conversion key to + create a full aggregation key to retrieve the + Aggregate API Report in Android Privacy Sandbox. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_id: int = proto.Field( + proto.INT64, + number=2, + ) + android_privacy_interaction_type: ( + gage_android_privacy_interaction_type.AndroidPrivacyInteractionTypeEnum.AndroidPrivacyInteractionType + ) = proto.Field( + proto.ENUM, + number=3, + enum=gage_android_privacy_interaction_type.AndroidPrivacyInteractionTypeEnum.AndroidPrivacyInteractionType, + ) + android_privacy_interaction_date: str = proto.Field( + proto.STRING, + number=4, + ) + android_privacy_network_type: ( + gage_android_privacy_network_type.AndroidPrivacyNetworkTypeEnum.AndroidPrivacyNetworkType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_android_privacy_network_type.AndroidPrivacyNetworkTypeEnum.AndroidPrivacyNetworkType, + ) + ad_group_id: int = proto.Field( + proto.INT64, + number=6, + ) + shared_ad_group_key: str = proto.Field( + proto.STRING, + number=7, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/android_privacy_shared_key_google_campaign.py b/google/ads/googleads/v24/resources/types/android_privacy_shared_key_google_campaign.py new file mode 100644 index 000000000..904c47d2e --- /dev/null +++ b/google/ads/googleads/v24/resources/types/android_privacy_shared_key_google_campaign.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + android_privacy_interaction_type as gage_android_privacy_interaction_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AndroidPrivacySharedKeyGoogleCampaign", + }, +) + + +class AndroidPrivacySharedKeyGoogleCampaign(proto.Message): + r"""An Android privacy shared key view for Google campaign key. + + Attributes: + resource_name (str): + Output only. The resource name of the Android privacy shared + key. Android privacy shared key resource names have the + form: + + ``customers/{customer_id}/androidPrivacySharedKeyGoogleCampaigns/{campaign_id}~{android_privacy_interaction_type}~{android_privacy_interaction_date(yyyy-mm-dd)}`` + campaign_id (int): + Output only. The campaign ID used in the + share key encoding. + android_privacy_interaction_type (google.ads.googleads.v24.enums.types.AndroidPrivacyInteractionTypeEnum.AndroidPrivacyInteractionType): + Output only. The interaction type enum used + in the share key encoding. + android_privacy_interaction_date (str): + Output only. The interaction date used in the + shared key encoding in the format of + "YYYY-MM-DD" in UTC timezone. + shared_campaign_key (str): + Output only. 128 bit hex string of the + encoded shared campaign key, including a '0x' + prefix. This key can be used to do a bitwise OR + operator with the aggregate conversion key to + create a full aggregation key to retrieve the + Aggregate API Report in Android Privacy Sandbox. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_id: int = proto.Field( + proto.INT64, + number=2, + ) + android_privacy_interaction_type: ( + gage_android_privacy_interaction_type.AndroidPrivacyInteractionTypeEnum.AndroidPrivacyInteractionType + ) = proto.Field( + proto.ENUM, + number=3, + enum=gage_android_privacy_interaction_type.AndroidPrivacyInteractionTypeEnum.AndroidPrivacyInteractionType, + ) + android_privacy_interaction_date: str = proto.Field( + proto.STRING, + number=4, + ) + shared_campaign_key: str = proto.Field( + proto.STRING, + number=5, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/android_privacy_shared_key_google_network_type.py b/google/ads/googleads/v24/resources/types/android_privacy_shared_key_google_network_type.py new file mode 100644 index 000000000..abe94ac36 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/android_privacy_shared_key_google_network_type.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + android_privacy_interaction_type as gage_android_privacy_interaction_type, +) +from google.ads.googleads.v24.enums.types import ( + android_privacy_network_type as gage_android_privacy_network_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AndroidPrivacySharedKeyGoogleNetworkType", + }, +) + + +class AndroidPrivacySharedKeyGoogleNetworkType(proto.Message): + r"""An Android privacy shared key view for Google network type + key. + + Attributes: + resource_name (str): + Output only. The resource name of the Android privacy shared + key. Android privacy shared key resource names have the + form: + + ``customers/{customer_id}/androidPrivacySharedKeyGoogleNetworkTypes/{campaign_id}~{android_privacy_interaction_type}~{android_privacy_network_type}~{android_privacy_interaction_date(yyyy-mm-dd)}`` + campaign_id (int): + Output only. The campaign ID used in the + share key encoding. + android_privacy_interaction_type (google.ads.googleads.v24.enums.types.AndroidPrivacyInteractionTypeEnum.AndroidPrivacyInteractionType): + Output only. The interaction type enum used + in the share key encoding. + android_privacy_interaction_date (str): + Output only. The interaction date used in the + shared key encoding in the format of + "YYYY-MM-DD" in UTC timezone. + android_privacy_network_type (google.ads.googleads.v24.enums.types.AndroidPrivacyNetworkTypeEnum.AndroidPrivacyNetworkType): + Output only. The network type enum used in + the share key encoding. + shared_network_type_key (str): + Output only. 128 bit hex string of the + encoded shared network type key, including a + '0x' prefix. This key can be used to do a + bitwise OR operator with the aggregate + conversion key to create a full aggregation key + to retrieve the Aggregate API Report in Android + Privacy Sandbox. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_id: int = proto.Field( + proto.INT64, + number=2, + ) + android_privacy_interaction_type: ( + gage_android_privacy_interaction_type.AndroidPrivacyInteractionTypeEnum.AndroidPrivacyInteractionType + ) = proto.Field( + proto.ENUM, + number=3, + enum=gage_android_privacy_interaction_type.AndroidPrivacyInteractionTypeEnum.AndroidPrivacyInteractionType, + ) + android_privacy_interaction_date: str = proto.Field( + proto.STRING, + number=4, + ) + android_privacy_network_type: ( + gage_android_privacy_network_type.AndroidPrivacyNetworkTypeEnum.AndroidPrivacyNetworkType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_android_privacy_network_type.AndroidPrivacyNetworkTypeEnum.AndroidPrivacyNetworkType, + ) + shared_network_type_key: str = proto.Field( + proto.STRING, + number=6, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/app_top_combination_view.py b/google/ads/googleads/v24/resources/types/app_top_combination_view.py new file mode 100644 index 000000000..08ca8d19a --- /dev/null +++ b/google/ads/googleads/v24/resources/types/app_top_combination_view.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import asset_usage + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AppTopCombinationView", + "AdGroupCreativeAssetCombinationData", + }, +) + + +class AppTopCombinationView(proto.Message): + r"""A view resource in the App Top Combination Report. + + Attributes: + resource_name (str): + Output only. The resource name of the app top combination + view. App Top Combination view resource names have the form: + ``customers/{customer_id}/appTopCombinationViews/{ad_group_id}~{ad_id}~{asset_combination_category}`` + ad_group_top_combinations (MutableSequence[google.ads.googleads.v24.resources.types.AdGroupCreativeAssetCombinationData]): + Output only. The top combinations of assets + that served together. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_top_combinations: MutableSequence[ + "AdGroupCreativeAssetCombinationData" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupCreativeAssetCombinationData", + ) + + +class AdGroupCreativeAssetCombinationData(proto.Message): + r"""Ad group asset combination data + + Attributes: + asset_combination_served_assets (MutableSequence[google.ads.googleads.v24.common.types.AssetUsage]): + Output only. Served assets. + """ + + asset_combination_served_assets: MutableSequence[asset_usage.AssetUsage] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=asset_usage.AssetUsage, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/applied_incentive.py b/google/ads/googleads/v24/resources/types/applied_incentive.py new file mode 100644 index 000000000..f668a5e27 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/applied_incentive.py @@ -0,0 +1,186 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + incentive_state as gage_incentive_state, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AppliedIncentive", + }, +) + + +class AppliedIncentive(proto.Message): + r"""Represents an applied incentive. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the incentive. Incentive + resource names have the form: + + ``customers/{customer_id}/appliedIncentives/{coupon_code}`` + coupon_code (str): + Output only. The coupon code of the + incentive. + + This field is a member of `oneof`_ ``_coupon_code``. + incentive_state (google.ads.googleads.v24.enums.types.IncentiveStateEnum.IncentiveState): + Output only. The current state of the + incentive. + + This field is a member of `oneof`_ ``_incentive_state``. + redemption_date_time (str): + Output only. The redemption time of the + incentive in "YYYY-MM-DD HH:MM:SS" format in + UTC. + + This field is a member of `oneof`_ ``_redemption_date_time``. + fulfillment_expiration_date_time (str): + Output only. The time by which the + incentive's fulfillment requirements must be + met, in "YYYY-MM-DD HH:MM:SS" format in UTC. + + This field is a member of `oneof`_ ``_fulfillment_expiration_date_time``. + reward_grant_date_time (str): + Output only. The time when the reward was + granted in "YYYY-MM-DD HH:MM:SS" format in UTC. + This field is not set if the reward has not been + granted. + + This field is a member of `oneof`_ ``_reward_grant_date_time``. + reward_expiration_date_time (str): + Output only. The time when the granted reward + expires in "YYYY-MM-DD HH:MM:SS" format in UTC. + This field is not set if the reward has not been + granted. + + This field is a member of `oneof`_ ``_reward_expiration_date_time``. + currency_code (str): + Output only. The currency code for all + monetary amounts (for example, "USD"). + + This field is a member of `oneof`_ ``_currency_code``. + reward_amount_micros (int): + Output only. The maximum potential reward + amount in micros for the incentive. + + This field is a member of `oneof`_ ``_reward_amount_micros``. + granted_amount_micros (int): + Output only. The amount of the reward granted + in micros. This field is not set if the reward + has not been granted. + + This field is a member of `oneof`_ ``_granted_amount_micros``. + required_min_spend_micros (int): + Output only. The minimum amount that must be + spent to fulfill the coupon requirements, in + micros. + + This field is a member of `oneof`_ ``_required_min_spend_micros``. + current_spend_towards_fulfillment_micros (int): + Output only. The current amount spent towards + the fulfillment requirements, in micros. + + This field is a member of `oneof`_ ``_current_spend_towards_fulfillment_micros``. + reward_balance_remaining_micros (int): + Output only. The remaining balance of the + granted reward in micros. This field is not set + if the reward has not been granted. + + This field is a member of `oneof`_ ``_reward_balance_remaining_micros``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + coupon_code: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + incentive_state: gage_incentive_state.IncentiveStateEnum.IncentiveState = ( + proto.Field( + proto.ENUM, + number=3, + optional=True, + enum=gage_incentive_state.IncentiveStateEnum.IncentiveState, + ) + ) + redemption_date_time: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + fulfillment_expiration_date_time: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + reward_grant_date_time: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + reward_expiration_date_time: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + currency_code: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + reward_amount_micros: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + granted_amount_micros: int = proto.Field( + proto.INT64, + number=10, + optional=True, + ) + required_min_spend_micros: int = proto.Field( + proto.INT64, + number=11, + optional=True, + ) + current_spend_towards_fulfillment_micros: int = proto.Field( + proto.INT64, + number=12, + optional=True, + ) + reward_balance_remaining_micros: int = proto.Field( + proto.INT64, + number=13, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/asset.py b/google/ads/googleads/v24/resources/types/asset.py new file mode 100644 index 000000000..8ee481dbc --- /dev/null +++ b/google/ads/googleads/v24/resources/types/asset.py @@ -0,0 +1,570 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import asset_types +from google.ads.googleads.v24.common.types import custom_parameter +from google.ads.googleads.v24.common.types import policy +from google.ads.googleads.v24.enums.types import ( + asset_field_type as gage_asset_field_type, +) +from google.ads.googleads.v24.enums.types import asset_orientation +from google.ads.googleads.v24.enums.types import ( + asset_source as gage_asset_source, +) +from google.ads.googleads.v24.enums.types import asset_type +from google.ads.googleads.v24.enums.types import policy_approval_status +from google.ads.googleads.v24.enums.types import policy_review_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "Asset", + "AssetFieldTypePolicySummary", + "AssetPolicySummary", + }, +) + + +class Asset(proto.Message): + r"""Asset is a part of an ad which can be shared across multiple + ads. It can be an image (ImageAsset), a video + (YoutubeVideoAsset), etc. Assets are immutable and cannot be + removed. To stop an asset from serving, remove the asset from + the entity that is using it. + + 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: + resource_name (str): + Immutable. The resource name of the asset. Asset resource + names have the form: + + ``customers/{customer_id}/assets/{asset_id}`` + id (int): + Output only. The ID of the asset. + + This field is a member of `oneof`_ ``_id``. + name (str): + Optional name of the asset. + + This field is a member of `oneof`_ ``_name``. + type_ (google.ads.googleads.v24.enums.types.AssetTypeEnum.AssetType): + Output only. Type of the asset. + final_urls (MutableSequence[str]): + A list of possible final URLs after all cross + domain redirects. + final_mobile_urls (MutableSequence[str]): + A list of possible final mobile URLs after + all cross domain redirects. + tracking_url_template (str): + URL template for constructing a tracking URL. + + This field is a member of `oneof`_ ``_tracking_url_template``. + url_custom_parameters (MutableSequence[google.ads.googleads.v24.common.types.CustomParameter]): + A list of mappings to be used for substituting URL custom + parameter tags in the tracking_url_template, final_urls, + and/or final_mobile_urls. + final_url_suffix (str): + URL template for appending params to landing + page URLs served with parallel tracking. + + This field is a member of `oneof`_ ``_final_url_suffix``. + source (google.ads.googleads.v24.enums.types.AssetSourceEnum.AssetSource): + Output only. Source of the asset. + policy_summary (google.ads.googleads.v24.resources.types.AssetPolicySummary): + Output only. Policy information for the + asset. + field_type_policy_summaries (MutableSequence[google.ads.googleads.v24.resources.types.AssetFieldTypePolicySummary]): + Output only. Policy information for the asset + for each FieldType. + orientation (google.ads.googleads.v24.enums.types.AssetOrientationEnum.AssetOrientation): + Output only. Orientation of the asset. This + is only supported for image and video assets. + + This field is a member of `oneof`_ ``_orientation``. + youtube_video_asset (google.ads.googleads.v24.common.types.YoutubeVideoAsset): + Immutable. A YouTube video asset. + + This field is a member of `oneof`_ ``asset_data``. + media_bundle_asset (google.ads.googleads.v24.common.types.MediaBundleAsset): + Immutable. A media bundle asset. + + This field is a member of `oneof`_ ``asset_data``. + image_asset (google.ads.googleads.v24.common.types.ImageAsset): + Output only. An image asset. + + This field is a member of `oneof`_ ``asset_data``. + text_asset (google.ads.googleads.v24.common.types.TextAsset): + Immutable. A text asset. + + This field is a member of `oneof`_ ``asset_data``. + lead_form_asset (google.ads.googleads.v24.common.types.LeadFormAsset): + A lead form asset. + + This field is a member of `oneof`_ ``asset_data``. + book_on_google_asset (google.ads.googleads.v24.common.types.BookOnGoogleAsset): + A book on google asset. + + This field is a member of `oneof`_ ``asset_data``. + promotion_asset (google.ads.googleads.v24.common.types.PromotionAsset): + A promotion asset. + + This field is a member of `oneof`_ ``asset_data``. + callout_asset (google.ads.googleads.v24.common.types.CalloutAsset): + A callout asset. + + This field is a member of `oneof`_ ``asset_data``. + structured_snippet_asset (google.ads.googleads.v24.common.types.StructuredSnippetAsset): + A structured snippet asset. + + This field is a member of `oneof`_ ``asset_data``. + sitelink_asset (google.ads.googleads.v24.common.types.SitelinkAsset): + A sitelink asset. + + This field is a member of `oneof`_ ``asset_data``. + page_feed_asset (google.ads.googleads.v24.common.types.PageFeedAsset): + A page feed asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_education_asset (google.ads.googleads.v24.common.types.DynamicEducationAsset): + A dynamic education asset. + + This field is a member of `oneof`_ ``asset_data``. + mobile_app_asset (google.ads.googleads.v24.common.types.MobileAppAsset): + A mobile app asset. + + This field is a member of `oneof`_ ``asset_data``. + hotel_callout_asset (google.ads.googleads.v24.common.types.HotelCalloutAsset): + A hotel callout asset. + + This field is a member of `oneof`_ ``asset_data``. + call_asset (google.ads.googleads.v24.common.types.CallAsset): + A call asset. + + This field is a member of `oneof`_ ``asset_data``. + price_asset (google.ads.googleads.v24.common.types.PriceAsset): + A price asset. + + This field is a member of `oneof`_ ``asset_data``. + call_to_action_asset (google.ads.googleads.v24.common.types.CallToActionAsset): + Immutable. A call to action asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_real_estate_asset (google.ads.googleads.v24.common.types.DynamicRealEstateAsset): + A dynamic real estate asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_custom_asset (google.ads.googleads.v24.common.types.DynamicCustomAsset): + A dynamic custom asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_hotels_and_rentals_asset (google.ads.googleads.v24.common.types.DynamicHotelsAndRentalsAsset): + A dynamic hotels and rentals asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_flights_asset (google.ads.googleads.v24.common.types.DynamicFlightsAsset): + A dynamic flights asset. + + This field is a member of `oneof`_ ``asset_data``. + demand_gen_carousel_card_asset (google.ads.googleads.v24.common.types.DemandGenCarouselCardAsset): + Immutable. A Demand Gen carousel card asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_travel_asset (google.ads.googleads.v24.common.types.DynamicTravelAsset): + A dynamic travel asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_local_asset (google.ads.googleads.v24.common.types.DynamicLocalAsset): + A dynamic local asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_jobs_asset (google.ads.googleads.v24.common.types.DynamicJobsAsset): + A dynamic jobs asset. + + This field is a member of `oneof`_ ``asset_data``. + location_asset (google.ads.googleads.v24.common.types.LocationAsset): + Output only. A location asset. + + This field is a member of `oneof`_ ``asset_data``. + hotel_property_asset (google.ads.googleads.v24.common.types.HotelPropertyAsset): + Immutable. A hotel property asset. + + This field is a member of `oneof`_ ``asset_data``. + business_message_asset (google.ads.googleads.v24.common.types.BusinessMessageAsset): + A business message asset. + + This field is a member of `oneof`_ ``asset_data``. + app_deep_link_asset (google.ads.googleads.v24.common.types.AppDeepLinkAsset): + Immutable. An app deep link asset. + + This field is a member of `oneof`_ ``asset_data``. + youtube_video_list_asset (google.ads.googleads.v24.common.types.YouTubeVideoListAsset): + Immutable. A YouTube video list asset. + + This field is a member of `oneof`_ ``asset_data``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=11, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + type_: asset_type.AssetTypeEnum.AssetType = proto.Field( + proto.ENUM, + number=4, + enum=asset_type.AssetTypeEnum.AssetType, + ) + final_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=14, + ) + final_mobile_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=16, + ) + tracking_url_template: str = proto.Field( + proto.STRING, + number=17, + optional=True, + ) + url_custom_parameters: MutableSequence[custom_parameter.CustomParameter] = ( + proto.RepeatedField( + proto.MESSAGE, + number=18, + message=custom_parameter.CustomParameter, + ) + ) + final_url_suffix: str = proto.Field( + proto.STRING, + number=19, + optional=True, + ) + source: gage_asset_source.AssetSourceEnum.AssetSource = proto.Field( + proto.ENUM, + number=38, + enum=gage_asset_source.AssetSourceEnum.AssetSource, + ) + policy_summary: "AssetPolicySummary" = proto.Field( + proto.MESSAGE, + number=13, + message="AssetPolicySummary", + ) + field_type_policy_summaries: MutableSequence[ + "AssetFieldTypePolicySummary" + ] = proto.RepeatedField( + proto.MESSAGE, + number=40, + message="AssetFieldTypePolicySummary", + ) + orientation: asset_orientation.AssetOrientationEnum.AssetOrientation = ( + proto.Field( + proto.ENUM, + number=54, + optional=True, + enum=asset_orientation.AssetOrientationEnum.AssetOrientation, + ) + ) + youtube_video_asset: asset_types.YoutubeVideoAsset = proto.Field( + proto.MESSAGE, + number=5, + oneof="asset_data", + message=asset_types.YoutubeVideoAsset, + ) + media_bundle_asset: asset_types.MediaBundleAsset = proto.Field( + proto.MESSAGE, + number=6, + oneof="asset_data", + message=asset_types.MediaBundleAsset, + ) + image_asset: asset_types.ImageAsset = proto.Field( + proto.MESSAGE, + number=7, + oneof="asset_data", + message=asset_types.ImageAsset, + ) + text_asset: asset_types.TextAsset = proto.Field( + proto.MESSAGE, + number=8, + oneof="asset_data", + message=asset_types.TextAsset, + ) + lead_form_asset: asset_types.LeadFormAsset = proto.Field( + proto.MESSAGE, + number=9, + oneof="asset_data", + message=asset_types.LeadFormAsset, + ) + book_on_google_asset: asset_types.BookOnGoogleAsset = proto.Field( + proto.MESSAGE, + number=10, + oneof="asset_data", + message=asset_types.BookOnGoogleAsset, + ) + promotion_asset: asset_types.PromotionAsset = proto.Field( + proto.MESSAGE, + number=15, + oneof="asset_data", + message=asset_types.PromotionAsset, + ) + callout_asset: asset_types.CalloutAsset = proto.Field( + proto.MESSAGE, + number=20, + oneof="asset_data", + message=asset_types.CalloutAsset, + ) + structured_snippet_asset: asset_types.StructuredSnippetAsset = proto.Field( + proto.MESSAGE, + number=21, + oneof="asset_data", + message=asset_types.StructuredSnippetAsset, + ) + sitelink_asset: asset_types.SitelinkAsset = proto.Field( + proto.MESSAGE, + number=22, + oneof="asset_data", + message=asset_types.SitelinkAsset, + ) + page_feed_asset: asset_types.PageFeedAsset = proto.Field( + proto.MESSAGE, + number=23, + oneof="asset_data", + message=asset_types.PageFeedAsset, + ) + dynamic_education_asset: asset_types.DynamicEducationAsset = proto.Field( + proto.MESSAGE, + number=24, + oneof="asset_data", + message=asset_types.DynamicEducationAsset, + ) + mobile_app_asset: asset_types.MobileAppAsset = proto.Field( + proto.MESSAGE, + number=25, + oneof="asset_data", + message=asset_types.MobileAppAsset, + ) + hotel_callout_asset: asset_types.HotelCalloutAsset = proto.Field( + proto.MESSAGE, + number=26, + oneof="asset_data", + message=asset_types.HotelCalloutAsset, + ) + call_asset: asset_types.CallAsset = proto.Field( + proto.MESSAGE, + number=27, + oneof="asset_data", + message=asset_types.CallAsset, + ) + price_asset: asset_types.PriceAsset = proto.Field( + proto.MESSAGE, + number=28, + oneof="asset_data", + message=asset_types.PriceAsset, + ) + call_to_action_asset: asset_types.CallToActionAsset = proto.Field( + proto.MESSAGE, + number=29, + oneof="asset_data", + message=asset_types.CallToActionAsset, + ) + dynamic_real_estate_asset: asset_types.DynamicRealEstateAsset = proto.Field( + proto.MESSAGE, + number=30, + oneof="asset_data", + message=asset_types.DynamicRealEstateAsset, + ) + dynamic_custom_asset: asset_types.DynamicCustomAsset = proto.Field( + proto.MESSAGE, + number=31, + oneof="asset_data", + message=asset_types.DynamicCustomAsset, + ) + dynamic_hotels_and_rentals_asset: ( + asset_types.DynamicHotelsAndRentalsAsset + ) = proto.Field( + proto.MESSAGE, + number=32, + oneof="asset_data", + message=asset_types.DynamicHotelsAndRentalsAsset, + ) + dynamic_flights_asset: asset_types.DynamicFlightsAsset = proto.Field( + proto.MESSAGE, + number=33, + oneof="asset_data", + message=asset_types.DynamicFlightsAsset, + ) + demand_gen_carousel_card_asset: asset_types.DemandGenCarouselCardAsset = ( + proto.Field( + proto.MESSAGE, + number=50, + oneof="asset_data", + message=asset_types.DemandGenCarouselCardAsset, + ) + ) + dynamic_travel_asset: asset_types.DynamicTravelAsset = proto.Field( + proto.MESSAGE, + number=35, + oneof="asset_data", + message=asset_types.DynamicTravelAsset, + ) + dynamic_local_asset: asset_types.DynamicLocalAsset = proto.Field( + proto.MESSAGE, + number=36, + oneof="asset_data", + message=asset_types.DynamicLocalAsset, + ) + dynamic_jobs_asset: asset_types.DynamicJobsAsset = proto.Field( + proto.MESSAGE, + number=37, + oneof="asset_data", + message=asset_types.DynamicJobsAsset, + ) + location_asset: asset_types.LocationAsset = proto.Field( + proto.MESSAGE, + number=39, + oneof="asset_data", + message=asset_types.LocationAsset, + ) + hotel_property_asset: asset_types.HotelPropertyAsset = proto.Field( + proto.MESSAGE, + number=41, + oneof="asset_data", + message=asset_types.HotelPropertyAsset, + ) + business_message_asset: asset_types.BusinessMessageAsset = proto.Field( + proto.MESSAGE, + number=51, + oneof="asset_data", + message=asset_types.BusinessMessageAsset, + ) + app_deep_link_asset: asset_types.AppDeepLinkAsset = proto.Field( + proto.MESSAGE, + number=52, + oneof="asset_data", + message=asset_types.AppDeepLinkAsset, + ) + youtube_video_list_asset: asset_types.YouTubeVideoListAsset = proto.Field( + proto.MESSAGE, + number=53, + oneof="asset_data", + message=asset_types.YouTubeVideoListAsset, + ) + + +class AssetFieldTypePolicySummary(proto.Message): + r"""Contains policy information for an asset under AssetFieldType + context. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + asset_field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + Output only. FieldType of this asset. + + This field is a member of `oneof`_ ``_asset_field_type``. + asset_source (google.ads.googleads.v24.enums.types.AssetSourceEnum.AssetSource): + Output only. Source of this asset. + + This field is a member of `oneof`_ ``_asset_source``. + policy_summary_info (google.ads.googleads.v24.resources.types.AssetPolicySummary): + Output only. Policy summary. + + This field is a member of `oneof`_ ``_policy_summary_info``. + """ + + asset_field_type: ( + gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType + ) = proto.Field( + proto.ENUM, + number=1, + optional=True, + enum=gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + asset_source: gage_asset_source.AssetSourceEnum.AssetSource = proto.Field( + proto.ENUM, + number=2, + optional=True, + enum=gage_asset_source.AssetSourceEnum.AssetSource, + ) + policy_summary_info: "AssetPolicySummary" = proto.Field( + proto.MESSAGE, + number=3, + optional=True, + message="AssetPolicySummary", + ) + + +class AssetPolicySummary(proto.Message): + r"""Contains policy information for an asset. + + Attributes: + policy_topic_entries (MutableSequence[google.ads.googleads.v24.common.types.PolicyTopicEntry]): + Output only. The list of policy findings for + this asset. + review_status (google.ads.googleads.v24.enums.types.PolicyReviewStatusEnum.PolicyReviewStatus): + Output only. Where in the review process this + asset is. + approval_status (google.ads.googleads.v24.enums.types.PolicyApprovalStatusEnum.PolicyApprovalStatus): + Output only. The overall approval status of + this asset, calculated based on the status of + its individual policy topic entries. + """ + + policy_topic_entries: MutableSequence[policy.PolicyTopicEntry] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=policy.PolicyTopicEntry, + ) + ) + review_status: ( + policy_review_status.PolicyReviewStatusEnum.PolicyReviewStatus + ) = proto.Field( + proto.ENUM, + number=2, + enum=policy_review_status.PolicyReviewStatusEnum.PolicyReviewStatus, + ) + approval_status: ( + policy_approval_status.PolicyApprovalStatusEnum.PolicyApprovalStatus + ) = proto.Field( + proto.ENUM, + number=3, + enum=policy_approval_status.PolicyApprovalStatusEnum.PolicyApprovalStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/asset_field_type_view.py b/google/ads/googleads/v24/resources/types/asset_field_type_view.py new file mode 100644 index 000000000..6e2438727 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/asset_field_type_view.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import asset_field_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AssetFieldTypeView", + }, +) + + +class AssetFieldTypeView(proto.Message): + r"""An asset field type view. + This view reports non-overcounted metrics for each asset field + type when the asset is used as extension. + + Attributes: + resource_name (str): + Output only. The resource name of the asset field type view. + Asset field type view resource names have the form: + + ``customers/{customer_id}/assetFieldTypeViews/{field_type}`` + field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + Output only. The asset field type of the + asset field type view. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + field_type: asset_field_type.AssetFieldTypeEnum.AssetFieldType = ( + proto.Field( + proto.ENUM, + number=3, + enum=asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/asset_group.py b/google/ads/googleads/v24/resources/types/asset_group.py new file mode 100644 index 000000000..7f39e5a36 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/asset_group.py @@ -0,0 +1,263 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ad_strength as gage_ad_strength +from google.ads.googleads.v24.enums.types import ad_strength_action_item_type +from google.ads.googleads.v24.enums.types import ( + asset_coverage_video_aspect_ratio_requirement, +) +from google.ads.googleads.v24.enums.types import ( + asset_field_type as gage_asset_field_type, +) +from google.ads.googleads.v24.enums.types import asset_group_primary_status +from google.ads.googleads.v24.enums.types import ( + asset_group_primary_status_reason, +) +from google.ads.googleads.v24.enums.types import asset_group_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGroup", + "AssetCoverage", + "AdStrengthActionItem", + }, +) + + +class AssetGroup(proto.Message): + r"""An asset group. + AssetGroupAsset is used to link an asset to the asset group. + AssetGroupSignal is used to associate a signal to an asset + group. + + Attributes: + resource_name (str): + Immutable. The resource name of the asset group. Asset group + resource names have the form: + + ``customers/{customer_id}/assetGroups/{asset_group_id}`` + id (int): + Output only. The ID of the asset group. + campaign (str): + Immutable. The campaign with which this asset + group is associated. The asset which is linked + to the asset group. + name (str): + Required. Name of the asset group. Required. + It must have a minimum length of 1 and maximum + length of 128. It must be unique under a + campaign. + final_urls (MutableSequence[str]): + A list of final URLs after all cross domain + redirects. In performance max, by default, the + urls are eligible for expansion unless opted + out. + final_mobile_urls (MutableSequence[str]): + A list of final mobile URLs after all cross + domain redirects. In performance max, by + default, the urls are eligible for expansion + unless opted out. + status (google.ads.googleads.v24.enums.types.AssetGroupStatusEnum.AssetGroupStatus): + The status of the asset group. + primary_status (google.ads.googleads.v24.enums.types.AssetGroupPrimaryStatusEnum.AssetGroupPrimaryStatus): + Output only. The primary status of the asset + group. Provides insights into why an asset group + is not serving or not serving optimally. + primary_status_reasons (MutableSequence[google.ads.googleads.v24.enums.types.AssetGroupPrimaryStatusReasonEnum.AssetGroupPrimaryStatusReason]): + Output only. Provides reasons into why an + asset group is not serving or not serving + optimally. It will be empty when the asset group + is serving without issues. + path1 (str): + First part of text that may appear appended + to the url displayed in the ad. + path2 (str): + Second part of text that may appear appended + to the url displayed in the ad. This field can + only be set when path1 is set. + ad_strength (google.ads.googleads.v24.enums.types.AdStrengthEnum.AdStrength): + Output only. Overall ad strength of this + asset group. + asset_coverage (google.ads.googleads.v24.resources.types.AssetCoverage): + Output only. The asset coverage of this asset + group. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=9, + ) + campaign: str = proto.Field( + proto.STRING, + number=2, + ) + name: str = proto.Field( + proto.STRING, + number=3, + ) + final_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=4, + ) + final_mobile_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=5, + ) + status: asset_group_status.AssetGroupStatusEnum.AssetGroupStatus = ( + proto.Field( + proto.ENUM, + number=6, + enum=asset_group_status.AssetGroupStatusEnum.AssetGroupStatus, + ) + ) + primary_status: ( + asset_group_primary_status.AssetGroupPrimaryStatusEnum.AssetGroupPrimaryStatus + ) = proto.Field( + proto.ENUM, + number=11, + enum=asset_group_primary_status.AssetGroupPrimaryStatusEnum.AssetGroupPrimaryStatus, + ) + primary_status_reasons: MutableSequence[ + asset_group_primary_status_reason.AssetGroupPrimaryStatusReasonEnum.AssetGroupPrimaryStatusReason + ] = proto.RepeatedField( + proto.ENUM, + number=12, + enum=asset_group_primary_status_reason.AssetGroupPrimaryStatusReasonEnum.AssetGroupPrimaryStatusReason, + ) + path1: str = proto.Field( + proto.STRING, + number=7, + ) + path2: str = proto.Field( + proto.STRING, + number=8, + ) + ad_strength: gage_ad_strength.AdStrengthEnum.AdStrength = proto.Field( + proto.ENUM, + number=10, + enum=gage_ad_strength.AdStrengthEnum.AdStrength, + ) + asset_coverage: "AssetCoverage" = proto.Field( + proto.MESSAGE, + number=13, + message="AssetCoverage", + ) + + +class AssetCoverage(proto.Message): + r"""Information about the asset coverage of an asset group. + + Attributes: + ad_strength_action_items (MutableSequence[google.ads.googleads.v24.resources.types.AdStrengthActionItem]): + Output only. A list of action items to + improve the ad strength of an asset group. + """ + + ad_strength_action_items: MutableSequence["AdStrengthActionItem"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="AdStrengthActionItem", + ) + ) + + +class AdStrengthActionItem(proto.Message): + r"""An action item to improve the ad strength of an asset group. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + action_item_type (google.ads.googleads.v24.enums.types.AdStrengthActionItemTypeEnum.AdStrengthActionItemType): + Output only. The action item type. + add_asset_details (google.ads.googleads.v24.resources.types.AdStrengthActionItem.AddAssetDetails): + Output only. The action item details for action item type + ADD_ASSET. + + This field is a member of `oneof`_ ``action_details``. + """ + + class AddAssetDetails(proto.Message): + r"""The details of the asset to add. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + asset_field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + Output only. The asset field type of the + asset(s) to add. + asset_count (int): + Output only. The number of assets to add. + + This field is a member of `oneof`_ ``_asset_count``. + video_aspect_ratio_requirement (google.ads.googleads.v24.enums.types.AssetCoverageVideoAspectRatioRequirementEnum.AssetCoverageVideoAspectRatioRequirement): + Output only. For video field types, the required aspect + ratio of the video. When unset and asset_field_type is + YOUTUBE_VIDEO, the system recommends the advertiser upload + any YouTube video, regardless of aspect ratio. + + This field is a member of `oneof`_ ``_video_aspect_ratio_requirement``. + """ + + asset_field_type: ( + gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType + ) = proto.Field( + proto.ENUM, + number=1, + enum=gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + asset_count: int = proto.Field( + proto.INT32, + number=2, + optional=True, + ) + video_aspect_ratio_requirement: ( + asset_coverage_video_aspect_ratio_requirement.AssetCoverageVideoAspectRatioRequirementEnum.AssetCoverageVideoAspectRatioRequirement + ) = proto.Field( + proto.ENUM, + number=3, + optional=True, + enum=asset_coverage_video_aspect_ratio_requirement.AssetCoverageVideoAspectRatioRequirementEnum.AssetCoverageVideoAspectRatioRequirement, + ) + + action_item_type: ( + ad_strength_action_item_type.AdStrengthActionItemTypeEnum.AdStrengthActionItemType + ) = proto.Field( + proto.ENUM, + number=1, + enum=ad_strength_action_item_type.AdStrengthActionItemTypeEnum.AdStrengthActionItemType, + ) + add_asset_details: AddAssetDetails = proto.Field( + proto.MESSAGE, + number=2, + oneof="action_details", + message=AddAssetDetails, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/asset_group_asset.py b/google/ads/googleads/v24/resources/types/asset_group_asset.py new file mode 100644 index 000000000..fa125c1a5 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/asset_group_asset.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import asset_policy +from google.ads.googleads.v24.common.types import ( + policy_summary as gagc_policy_summary, +) +from google.ads.googleads.v24.enums.types import asset_field_type +from google.ads.googleads.v24.enums.types import asset_link_primary_status +from google.ads.googleads.v24.enums.types import ( + asset_link_primary_status_reason, +) +from google.ads.googleads.v24.enums.types import asset_link_status +from google.ads.googleads.v24.enums.types import asset_source + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGroupAsset", + }, +) + + +class AssetGroupAsset(proto.Message): + r"""AssetGroupAsset is the link between an asset and an asset + group. Adding an AssetGroupAsset links an asset with an asset + group. + + Attributes: + resource_name (str): + Immutable. The resource name of the asset group asset. Asset + group asset resource name have the form: + + ``customers/{customer_id}/assetGroupAssets/{asset_group_id}~{asset_id}~{field_type}`` + asset_group (str): + Immutable. The asset group which this asset + group asset is linking. + asset (str): + Immutable. The asset which this asset group + asset is linking. + field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + The description of the placement of the asset within the + asset group. For example: HEADLINE, YOUTUBE_VIDEO etc + status (google.ads.googleads.v24.enums.types.AssetLinkStatusEnum.AssetLinkStatus): + The status of the link between an asset and + asset group. + primary_status (google.ads.googleads.v24.enums.types.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus): + Output only. Provides the PrimaryStatus of + this asset link. Primary status is meant + essentially to differentiate between the plain + "status" field, which has advertiser set values + of enabled, paused, or removed. The primary + status takes into account other signals (for + assets its mainly policy and quality approvals) + to come up with a more comprehensive status to + indicate its serving state. + primary_status_reasons (MutableSequence[google.ads.googleads.v24.enums.types.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason]): + Output only. Provides a list of reasons for + why an asset is not serving or not serving at + full capacity. + primary_status_details (MutableSequence[google.ads.googleads.v24.common.types.AssetLinkPrimaryStatusDetails]): + Output only. Provides the details of the + primary status and its associated reasons. + policy_summary (google.ads.googleads.v24.common.types.PolicySummary): + Output only. The policy information for this + asset group asset. + source (google.ads.googleads.v24.enums.types.AssetSourceEnum.AssetSource): + Output only. Source of the asset group asset. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + asset_group: str = proto.Field( + proto.STRING, + number=2, + ) + asset: str = proto.Field( + proto.STRING, + number=3, + ) + field_type: asset_field_type.AssetFieldTypeEnum.AssetFieldType = ( + proto.Field( + proto.ENUM, + number=4, + enum=asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + ) + status: asset_link_status.AssetLinkStatusEnum.AssetLinkStatus = proto.Field( + proto.ENUM, + number=5, + enum=asset_link_status.AssetLinkStatusEnum.AssetLinkStatus, + ) + primary_status: ( + asset_link_primary_status.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus + ) = proto.Field( + proto.ENUM, + number=8, + enum=asset_link_primary_status.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus, + ) + primary_status_reasons: MutableSequence[ + asset_link_primary_status_reason.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason + ] = proto.RepeatedField( + proto.ENUM, + number=9, + enum=asset_link_primary_status_reason.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason, + ) + primary_status_details: MutableSequence[ + asset_policy.AssetLinkPrimaryStatusDetails + ] = proto.RepeatedField( + proto.MESSAGE, + number=10, + message=asset_policy.AssetLinkPrimaryStatusDetails, + ) + policy_summary: gagc_policy_summary.PolicySummary = proto.Field( + proto.MESSAGE, + number=7, + message=gagc_policy_summary.PolicySummary, + ) + source: asset_source.AssetSourceEnum.AssetSource = proto.Field( + proto.ENUM, + number=11, + enum=asset_source.AssetSourceEnum.AssetSource, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/asset_group_listing_group_filter.py b/google/ads/googleads/v24/resources/types/asset_group_listing_group_filter.py new file mode 100644 index 000000000..6ecde7ead --- /dev/null +++ b/google/ads/googleads/v24/resources/types/asset_group_listing_group_filter.py @@ -0,0 +1,504 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + listing_group_filter_custom_attribute_index, +) +from google.ads.googleads.v24.enums.types import ( + listing_group_filter_listing_source, +) +from google.ads.googleads.v24.enums.types import ( + listing_group_filter_product_category_level, +) +from google.ads.googleads.v24.enums.types import ( + listing_group_filter_product_channel, +) +from google.ads.googleads.v24.enums.types import ( + listing_group_filter_product_condition, +) +from google.ads.googleads.v24.enums.types import ( + listing_group_filter_product_type_level, +) +from google.ads.googleads.v24.enums.types import listing_group_filter_type_enum + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGroupListingGroupFilter", + "ListingGroupFilterDimensionPath", + "ListingGroupFilterDimension", + }, +) + + +class AssetGroupListingGroupFilter(proto.Message): + r"""AssetGroupListingGroupFilter represents a listing group + filter tree node in an asset group. + + Attributes: + resource_name (str): + Immutable. The resource name of the asset group listing + group filter. Asset group listing group filter resource name + have the form: + + ``customers/{customer_id}/assetGroupListingGroupFilters/{asset_group_id}~{listing_group_filter_id}`` + asset_group (str): + Immutable. The asset group which this asset + group listing group filter is part of. + id (int): + Output only. The ID of the + ListingGroupFilter. + type_ (google.ads.googleads.v24.enums.types.ListingGroupFilterTypeEnum.ListingGroupFilterType): + Immutable. Type of a listing group filter + node. + listing_source (google.ads.googleads.v24.enums.types.ListingGroupFilterListingSourceEnum.ListingGroupFilterListingSource): + Immutable. The source of listings filtered by + this listing group filter. + case_value (google.ads.googleads.v24.resources.types.ListingGroupFilterDimension): + Dimension value with which this listing group + is refining its parent. Undefined for the root + group. + parent_listing_group_filter (str): + Immutable. Resource name of the parent + listing group subdivision. Null for the root + listing group filter node. + path (google.ads.googleads.v24.resources.types.ListingGroupFilterDimensionPath): + Output only. The path of dimensions defining + this listing group filter. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + asset_group: str = proto.Field( + proto.STRING, + number=2, + ) + id: int = proto.Field( + proto.INT64, + number=3, + ) + type_: ( + listing_group_filter_type_enum.ListingGroupFilterTypeEnum.ListingGroupFilterType + ) = proto.Field( + proto.ENUM, + number=4, + enum=listing_group_filter_type_enum.ListingGroupFilterTypeEnum.ListingGroupFilterType, + ) + listing_source: ( + listing_group_filter_listing_source.ListingGroupFilterListingSourceEnum.ListingGroupFilterListingSource + ) = proto.Field( + proto.ENUM, + number=9, + enum=listing_group_filter_listing_source.ListingGroupFilterListingSourceEnum.ListingGroupFilterListingSource, + ) + case_value: "ListingGroupFilterDimension" = proto.Field( + proto.MESSAGE, + number=6, + message="ListingGroupFilterDimension", + ) + parent_listing_group_filter: str = proto.Field( + proto.STRING, + number=7, + ) + path: "ListingGroupFilterDimensionPath" = proto.Field( + proto.MESSAGE, + number=8, + message="ListingGroupFilterDimensionPath", + ) + + +class ListingGroupFilterDimensionPath(proto.Message): + r"""The path defining of dimensions defining a listing group + filter. + + Attributes: + dimensions (MutableSequence[google.ads.googleads.v24.resources.types.ListingGroupFilterDimension]): + Output only. The complete path of dimensions + through the listing group filter hierarchy + (excluding the root node) to this listing group + filter. + """ + + dimensions: MutableSequence["ListingGroupFilterDimension"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ListingGroupFilterDimension", + ) + ) + + +class ListingGroupFilterDimension(proto.Message): + r"""Listing dimensions for the asset group listing group filter. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + product_category (google.ads.googleads.v24.resources.types.ListingGroupFilterDimension.ProductCategory): + Category of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_brand (google.ads.googleads.v24.resources.types.ListingGroupFilterDimension.ProductBrand): + Brand of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_channel (google.ads.googleads.v24.resources.types.ListingGroupFilterDimension.ProductChannel): + Locality of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_condition (google.ads.googleads.v24.resources.types.ListingGroupFilterDimension.ProductCondition): + Condition of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_custom_attribute (google.ads.googleads.v24.resources.types.ListingGroupFilterDimension.ProductCustomAttribute): + Custom attribute of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_item_id (google.ads.googleads.v24.resources.types.ListingGroupFilterDimension.ProductItemId): + Item id of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_type (google.ads.googleads.v24.resources.types.ListingGroupFilterDimension.ProductType): + Type of a product offer. + + This field is a member of `oneof`_ ``dimension``. + webpage (google.ads.googleads.v24.resources.types.ListingGroupFilterDimension.Webpage): + Filters for URLs in a page feed and URLs from + the advertiser web domain. + + This field is a member of `oneof`_ ``dimension``. + retail_filter_bundle (google.ads.googleads.v24.resources.types.ListingGroupFilterDimension.RetailFilterBundle): + Dimension for Retail Product Tags. + + This field is a member of `oneof`_ ``dimension``. + """ + + class ProductCategory(proto.Message): + r"""One element of a category at a certain level. Top-level + categories are at level 1, their children at level 2, and so on. + We currently support up to 5 levels. The user must specify a + dimension type that indicates the level of the category. All + cases of the same subdivision must have the same dimension type + (category level). + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + category_id (int): + ID of the product category. + + This ID is equivalent to the google_product_category ID as + described in this article: + https://support.google.com/merchants/answer/6324436 + + This field is a member of `oneof`_ ``_category_id``. + level (google.ads.googleads.v24.enums.types.ListingGroupFilterProductCategoryLevelEnum.ListingGroupFilterProductCategoryLevel): + Indicates the level of the category in the + taxonomy. + """ + + category_id: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + level: ( + listing_group_filter_product_category_level.ListingGroupFilterProductCategoryLevelEnum.ListingGroupFilterProductCategoryLevel + ) = proto.Field( + proto.ENUM, + number=2, + enum=listing_group_filter_product_category_level.ListingGroupFilterProductCategoryLevelEnum.ListingGroupFilterProductCategoryLevel, + ) + + class ProductBrand(proto.Message): + r"""Brand of the product. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + String value of the product brand. + + This field is a member of `oneof`_ ``_value``. + """ + + value: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + class ProductChannel(proto.Message): + r"""Locality of a product offer. + + Attributes: + channel (google.ads.googleads.v24.enums.types.ListingGroupFilterProductChannelEnum.ListingGroupFilterProductChannel): + Value of the locality. + """ + + channel: ( + listing_group_filter_product_channel.ListingGroupFilterProductChannelEnum.ListingGroupFilterProductChannel + ) = proto.Field( + proto.ENUM, + number=1, + enum=listing_group_filter_product_channel.ListingGroupFilterProductChannelEnum.ListingGroupFilterProductChannel, + ) + + class ProductCondition(proto.Message): + r"""Condition of a product offer. + + Attributes: + condition (google.ads.googleads.v24.enums.types.ListingGroupFilterProductConditionEnum.ListingGroupFilterProductCondition): + Value of the condition. + """ + + condition: ( + listing_group_filter_product_condition.ListingGroupFilterProductConditionEnum.ListingGroupFilterProductCondition + ) = proto.Field( + proto.ENUM, + number=1, + enum=listing_group_filter_product_condition.ListingGroupFilterProductConditionEnum.ListingGroupFilterProductCondition, + ) + + class ProductCustomAttribute(proto.Message): + r"""Custom attribute of a product offer. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + String value of the product custom attribute. + + This field is a member of `oneof`_ ``_value``. + index (google.ads.googleads.v24.enums.types.ListingGroupFilterCustomAttributeIndexEnum.ListingGroupFilterCustomAttributeIndex): + Indicates the index of the custom attribute. + """ + + value: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + index: ( + listing_group_filter_custom_attribute_index.ListingGroupFilterCustomAttributeIndexEnum.ListingGroupFilterCustomAttributeIndex + ) = proto.Field( + proto.ENUM, + number=2, + enum=listing_group_filter_custom_attribute_index.ListingGroupFilterCustomAttributeIndexEnum.ListingGroupFilterCustomAttributeIndex, + ) + + class ProductItemId(proto.Message): + r"""Item id of a product offer. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + Value of the id. + + This field is a member of `oneof`_ ``_value``. + """ + + value: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + class ProductType(proto.Message): + r"""Type of a product offer. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + value (str): + Value of the type. + + This field is a member of `oneof`_ ``_value``. + level (google.ads.googleads.v24.enums.types.ListingGroupFilterProductTypeLevelEnum.ListingGroupFilterProductTypeLevel): + Level of the type. + """ + + value: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + level: ( + listing_group_filter_product_type_level.ListingGroupFilterProductTypeLevelEnum.ListingGroupFilterProductTypeLevel + ) = proto.Field( + proto.ENUM, + number=2, + enum=listing_group_filter_product_type_level.ListingGroupFilterProductTypeLevelEnum.ListingGroupFilterProductTypeLevel, + ) + + class Webpage(proto.Message): + r"""Filters for URLs in a page feed and URLs from the advertiser + web domain. Several root nodes with this dimension are allowed + in an asset group and their conditions are considered in OR. + + Attributes: + conditions (MutableSequence[google.ads.googleads.v24.resources.types.ListingGroupFilterDimension.WebpageCondition]): + The webpage conditions are case sensitive and these are + and-ed together when evaluated for filtering. All the + conditions should be of same type. Example1: for URL1 = + www.ads.google.com?ocid=1&euid=2 and URL2 = + www.ads.google.com?ocid=1 and with "ocid" and "euid" as + url_contains conditions, URL1 will be matched, but URL2 not. + + Example2 : If URL1 has Label1, Label2 and URL2 has Label2, + Label3, then with Label1 and Label2 as custom_label + conditions, URL1 will be matched but not URL2. With Label2 + as the only custom_label condition then both URL1 and URL2 + will be matched. + """ + + conditions: MutableSequence[ + "ListingGroupFilterDimension.WebpageCondition" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ListingGroupFilterDimension.WebpageCondition", + ) + + class WebpageCondition(proto.Message): + r"""Matching condition for URL filtering. + + 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: + custom_label (str): + Filters the URLs in a page feed that have this custom label. + A custom label can be added to a campaign by creating an + AssetSet of type PAGE_FEED and linking it to the campaign + using CampaignAssetSet. + + This field is a member of `oneof`_ ``condition``. + url_contains (str): + Filters the URLs in a page feed and the URLs + from the advertiser web domain that contain this + string. + + This field is a member of `oneof`_ ``condition``. + """ + + custom_label: str = proto.Field( + proto.STRING, + number=1, + oneof="condition", + ) + url_contains: str = proto.Field( + proto.STRING, + number=2, + oneof="condition", + ) + + class RetailFilterBundle(proto.Message): + r"""Dimension for Retail Product Tags. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + shared_set (str): + The RetailFilterBundle shared set resource + name. + + This field is a member of `oneof`_ ``_shared_set``. + """ + + shared_set: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + product_category: ProductCategory = proto.Field( + proto.MESSAGE, + number=10, + oneof="dimension", + message=ProductCategory, + ) + product_brand: ProductBrand = proto.Field( + proto.MESSAGE, + number=2, + oneof="dimension", + message=ProductBrand, + ) + product_channel: ProductChannel = proto.Field( + proto.MESSAGE, + number=3, + oneof="dimension", + message=ProductChannel, + ) + product_condition: ProductCondition = proto.Field( + proto.MESSAGE, + number=4, + oneof="dimension", + message=ProductCondition, + ) + product_custom_attribute: ProductCustomAttribute = proto.Field( + proto.MESSAGE, + number=5, + oneof="dimension", + message=ProductCustomAttribute, + ) + product_item_id: ProductItemId = proto.Field( + proto.MESSAGE, + number=6, + oneof="dimension", + message=ProductItemId, + ) + product_type: ProductType = proto.Field( + proto.MESSAGE, + number=7, + oneof="dimension", + message=ProductType, + ) + webpage: Webpage = proto.Field( + proto.MESSAGE, + number=9, + oneof="dimension", + message=Webpage, + ) + retail_filter_bundle: RetailFilterBundle = proto.Field( + proto.MESSAGE, + number=11, + oneof="dimension", + message=RetailFilterBundle, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/asset_group_product_group_view.py b/google/ads/googleads/v24/resources/types/asset_group_product_group_view.py new file mode 100644 index 000000000..9eee285c1 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/asset_group_product_group_view.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGroupProductGroupView", + }, +) + + +class AssetGroupProductGroupView(proto.Message): + r"""An asset group product group view. + + Attributes: + resource_name (str): + Output only. The resource name of the asset group product + group view. Asset group product group view resource names + have the form: + + ``customers/{customer_id}/assetGroupProductGroupViews/{asset_group_id}~{listing_group_filter_id}`` + asset_group (str): + Output only. The asset group associated with + the listing group filter. + asset_group_listing_group_filter (str): + Output only. The resource name of the asset + group listing group filter. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + asset_group: str = proto.Field( + proto.STRING, + number=2, + ) + asset_group_listing_group_filter: str = proto.Field( + proto.STRING, + number=4, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/asset_group_signal.py b/google/ads/googleads/v24/resources/types/asset_group_signal.py new file mode 100644 index 000000000..b8290917a --- /dev/null +++ b/google/ads/googleads/v24/resources/types/asset_group_signal.py @@ -0,0 +1,121 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.enums.types import ( + asset_group_signal_approval_status, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGroupSignal", + }, +) + + +class AssetGroupSignal(proto.Message): + r"""AssetGroupSignal represents a signal in an asset group. The + existence of a signal tells the performance max campaign who's + most likely to convert. Performance Max uses the signal to look + for new people with similar or stronger intent to find + conversions across Search, Display, Video, and more. + + 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: + resource_name (str): + Immutable. The resource name of the asset group signal. + Asset group signal resource name have the form: + + ``customers/{customer_id}/assetGroupSignals/{asset_group_id}~{signal_id}`` + asset_group (str): + Immutable. The asset group which this asset + group signal belongs to. + approval_status (google.ads.googleads.v24.enums.types.AssetGroupSignalApprovalStatusEnum.AssetGroupSignalApprovalStatus): + Output only. Approval status is the output + value for search theme signal after Google ads + policy review. When using Audience signal, this + field is not used and will be absent. + disapproval_reasons (MutableSequence[str]): + Output only. Computed for SearchTheme + signals. When using Audience signal, this field + is not used and will be absent. + audience (google.ads.googleads.v24.common.types.AudienceInfo): + Immutable. The audience signal to be used by + the performance max campaign. + + This field is a member of `oneof`_ ``signal``. + search_theme (google.ads.googleads.v24.common.types.SearchThemeInfo): + Immutable. The search_theme signal to be used by the + performance max campaign. Mutate errors of search_theme + criterion includes AssetGroupSignalError.UNSPECIFIED + AssetGroupSignalError.UNKNOWN + AssetGroupSignalError.TOO_MANY_WORDS + AssetGroupSignalError.SEARCH_THEME_POLICY_VIOLATION + FieldError.REQUIRED StringFormatError.ILLEGAL_CHARS + StringLengthError.TOO_LONG + ResourceCountLimitExceededError.RESOURCE_LIMIT + + This field is a member of `oneof`_ ``signal``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + asset_group: str = proto.Field( + proto.STRING, + number=2, + ) + approval_status: ( + asset_group_signal_approval_status.AssetGroupSignalApprovalStatusEnum.AssetGroupSignalApprovalStatus + ) = proto.Field( + proto.ENUM, + number=6, + enum=asset_group_signal_approval_status.AssetGroupSignalApprovalStatusEnum.AssetGroupSignalApprovalStatus, + ) + disapproval_reasons: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=7, + ) + audience: criteria.AudienceInfo = proto.Field( + proto.MESSAGE, + number=4, + oneof="signal", + message=criteria.AudienceInfo, + ) + search_theme: criteria.SearchThemeInfo = proto.Field( + proto.MESSAGE, + number=5, + oneof="signal", + message=criteria.SearchThemeInfo, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/asset_group_top_combination_view.py b/google/ads/googleads/v24/resources/types/asset_group_top_combination_view.py new file mode 100644 index 000000000..f46a85812 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/asset_group_top_combination_view.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import asset_usage + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AssetGroupTopCombinationView", + "AssetGroupAssetCombinationData", + }, +) + + +class AssetGroupTopCombinationView(proto.Message): + r"""A view on the usage of asset group asset top combinations. + + Attributes: + resource_name (str): + Output only. The resource name of the asset group top + combination view. AssetGroup Top Combination view resource + names have the form: + \`"customers/{customer_id}/assetGroupTopCombinationViews/{asset_group_id}~{asset_combination_category}". + asset_group_top_combinations (MutableSequence[google.ads.googleads.v24.resources.types.AssetGroupAssetCombinationData]): + Output only. The top combinations of assets + that served together. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + asset_group_top_combinations: MutableSequence[ + "AssetGroupAssetCombinationData" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AssetGroupAssetCombinationData", + ) + + +class AssetGroupAssetCombinationData(proto.Message): + r"""Asset group asset combination data + + Attributes: + asset_combination_served_assets (MutableSequence[google.ads.googleads.v24.common.types.AssetUsage]): + Output only. Served assets. + """ + + asset_combination_served_assets: MutableSequence[asset_usage.AssetUsage] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=asset_usage.AssetUsage, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/asset_set.py b/google/ads/googleads/v24/resources/types/asset_set.py new file mode 100644 index 000000000..c01cf7f0f --- /dev/null +++ b/google/ads/googleads/v24/resources/types/asset_set.py @@ -0,0 +1,282 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import asset_set_types +from google.ads.googleads.v24.enums.types import asset_set_status +from google.ads.googleads.v24.enums.types import asset_set_type +from google.ads.googleads.v24.enums.types import vertical_ads_item_vertical_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AssetSet", + }, +) + + +class AssetSet(proto.Message): + r"""An asset set representing a collection of assets. + Use AssetSetAsset to link an asset to the asset set. + + 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: + id (int): + Output only. The ID of the asset set. + resource_name (str): + Immutable. The resource name of the asset set. Asset set + resource names have the form: + + ``customers/{customer_id}/assetSets/{asset_set_id}`` + name (str): + Required. Name of the asset set. Required. It + must have a minimum length of 1 and maximum + length of 128. + type_ (google.ads.googleads.v24.enums.types.AssetSetTypeEnum.AssetSetType): + Required. Immutable. The type of the asset + set. Required. + status (google.ads.googleads.v24.enums.types.AssetSetStatusEnum.AssetSetStatus): + Output only. The status of the asset set. + Read-only. + merchant_center_feed (google.ads.googleads.v24.resources.types.AssetSet.MerchantCenterFeed): + Merchant ID and Feed Label from Google + Merchant Center. + location_group_parent_asset_set_id (int): + Immutable. Parent asset set ID for the asset + set where the elements of this asset set come + from. For example: the sync level location + AssetSet id where the elements in LocationGroup + AssetSet come from. This field is required and + only applicable for Location Group typed + AssetSet. + hotel_property_data (google.ads.googleads.v24.resources.types.AssetSet.HotelPropertyData): + Output only. For Performance Max for travel + goals campaigns with a Hotel Center account + link. Read-only. + travel_feed_data (google.ads.googleads.v24.resources.types.AssetSet.TravelFeedData): + Output only. Travel Feed data. Read-only + location_set (google.ads.googleads.v24.common.types.LocationSet): + Location asset set data. This will be used for sync level + location set. This can only be set if AssetSet's type is + LOCATION_SYNC. + + This field is a member of `oneof`_ ``asset_set_source``. + business_profile_location_group (google.ads.googleads.v24.common.types.BusinessProfileLocationGroup): + Business Profile location group asset set + data. + + This field is a member of `oneof`_ ``asset_set_source``. + chain_location_group (google.ads.googleads.v24.common.types.ChainLocationGroup): + Represents information about a Chain dynamic location group. + Only applicable if the sync level AssetSet's type is + LOCATION_SYNC and sync source is chain. + + This field is a member of `oneof`_ ``asset_set_source``. + """ + + class MerchantCenterFeed(proto.Message): + r"""Merchant ID and Feed Label from Google Merchant Center. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + merchant_id (int): + Required. Merchant ID from Google Merchant + Center + feed_label (str): + Optional. Feed Label from Google Merchant + Center. + + This field is a member of `oneof`_ ``_feed_label``. + """ + + merchant_id: int = proto.Field( + proto.INT64, + number=1, + ) + feed_label: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + class HotelPropertyData(proto.Message): + r"""For Performance Max for travel goals campaigns with a Hotel + Center account link. Read-only. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + hotel_center_id (int): + Output only. The hotel center ID of the + partner. + + This field is a member of `oneof`_ ``_hotel_center_id``. + partner_name (str): + Output only. Name of the hotel partner. + + This field is a member of `oneof`_ ``_partner_name``. + """ + + hotel_center_id: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + partner_name: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + class TravelFeedData(proto.Message): + r"""Travel Feed data. Read-only + + 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: + subset_id (int): + Output only. Id representing a subset of the + travel feed. + travel_feed_vertical_type (google.ads.googleads.v24.enums.types.VerticalAdsItemVerticalTypeEnum.VerticalAdsItemVerticalType): + Output only. Indicates the vertical type of + the travel feed. + hotel_center_account_id (int): + Output only. The Hotel Center account ID used + for a Hotel or Vacation Rental feed. + + This field is a member of `oneof`_ ``travel_feed_id``. + merchant_center_id (int): + Output only. The Merchant Center account ID + used for a Things to Do feed. + + This field is a member of `oneof`_ ``travel_feed_id``. + partner_center_id (int): + Output only. The Partner Center ID used for a + travel vertical feed, except for Hotel, Vacation + Rental, and Things to Do feeds. + + This field is a member of `oneof`_ ``travel_feed_id``. + """ + + subset_id: int = proto.Field( + proto.INT64, + number=3, + ) + travel_feed_vertical_type: ( + vertical_ads_item_vertical_type.VerticalAdsItemVerticalTypeEnum.VerticalAdsItemVerticalType + ) = proto.Field( + proto.ENUM, + number=6, + enum=vertical_ads_item_vertical_type.VerticalAdsItemVerticalTypeEnum.VerticalAdsItemVerticalType, + ) + hotel_center_account_id: int = proto.Field( + proto.INT64, + number=1, + oneof="travel_feed_id", + ) + merchant_center_id: int = proto.Field( + proto.INT64, + number=2, + oneof="travel_feed_id", + ) + partner_center_id: int = proto.Field( + proto.INT64, + number=5, + oneof="travel_feed_id", + ) + + id: int = proto.Field( + proto.INT64, + number=6, + ) + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + name: str = proto.Field( + proto.STRING, + number=2, + ) + type_: asset_set_type.AssetSetTypeEnum.AssetSetType = proto.Field( + proto.ENUM, + number=3, + enum=asset_set_type.AssetSetTypeEnum.AssetSetType, + ) + status: asset_set_status.AssetSetStatusEnum.AssetSetStatus = proto.Field( + proto.ENUM, + number=4, + enum=asset_set_status.AssetSetStatusEnum.AssetSetStatus, + ) + merchant_center_feed: MerchantCenterFeed = proto.Field( + proto.MESSAGE, + number=5, + message=MerchantCenterFeed, + ) + location_group_parent_asset_set_id: int = proto.Field( + proto.INT64, + number=10, + ) + hotel_property_data: HotelPropertyData = proto.Field( + proto.MESSAGE, + number=11, + message=HotelPropertyData, + ) + travel_feed_data: TravelFeedData = proto.Field( + proto.MESSAGE, + number=12, + message=TravelFeedData, + ) + location_set: asset_set_types.LocationSet = proto.Field( + proto.MESSAGE, + number=7, + oneof="asset_set_source", + message=asset_set_types.LocationSet, + ) + business_profile_location_group: ( + asset_set_types.BusinessProfileLocationGroup + ) = proto.Field( + proto.MESSAGE, + number=8, + oneof="asset_set_source", + message=asset_set_types.BusinessProfileLocationGroup, + ) + chain_location_group: asset_set_types.ChainLocationGroup = proto.Field( + proto.MESSAGE, + number=9, + oneof="asset_set_source", + message=asset_set_types.ChainLocationGroup, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/asset_set_asset.py b/google/ads/googleads/v24/resources/types/asset_set_asset.py new file mode 100644 index 000000000..76f72469b --- /dev/null +++ b/google/ads/googleads/v24/resources/types/asset_set_asset.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import asset_set_asset_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AssetSetAsset", + }, +) + + +class AssetSetAsset(proto.Message): + r"""AssetSetAsset is the link between an asset and an asset set. + Adding an AssetSetAsset links an asset with an asset set. + + Attributes: + resource_name (str): + Immutable. The resource name of the asset set asset. Asset + set asset resource names have the form: + + ``customers/{customer_id}/assetSetAssets/{asset_set_id}~{asset_id}`` + asset_set (str): + Immutable. The asset set which this asset set + asset is linking to. + asset (str): + Immutable. The asset which this asset set + asset is linking to. + status (google.ads.googleads.v24.enums.types.AssetSetAssetStatusEnum.AssetSetAssetStatus): + Output only. The status of the asset set + asset. Read-only. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + asset_set: str = proto.Field( + proto.STRING, + number=2, + ) + asset: str = proto.Field( + proto.STRING, + number=3, + ) + status: ( + asset_set_asset_status.AssetSetAssetStatusEnum.AssetSetAssetStatus + ) = proto.Field( + proto.ENUM, + number=4, + enum=asset_set_asset_status.AssetSetAssetStatusEnum.AssetSetAssetStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/asset_set_type_view.py b/google/ads/googleads/v24/resources/types/asset_set_type_view.py new file mode 100644 index 000000000..3a068c465 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/asset_set_type_view.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + asset_set_type as gage_asset_set_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "AssetSetTypeView", + }, +) + + +class AssetSetTypeView(proto.Message): + r"""An asset set type view. + This view reports non-overcounted metrics for each asset set + type. Child asset set types are not included in this report. + Their stats are aggregated under the parent asset set type. + + Attributes: + resource_name (str): + Output only. The resource name of the asset set type view. + Asset set type view resource names have the form: + + ``customers/{customer_id}/assetSetTypeViews/{asset_set_type}`` + asset_set_type (google.ads.googleads.v24.enums.types.AssetSetTypeEnum.AssetSetType): + Output only. The asset set type of the asset + set type view. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + asset_set_type: gage_asset_set_type.AssetSetTypeEnum.AssetSetType = ( + proto.Field( + proto.ENUM, + number=3, + enum=gage_asset_set_type.AssetSetTypeEnum.AssetSetType, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/audience.py b/google/ads/googleads/v24/resources/types/audience.py new file mode 100644 index 000000000..93e47f33d --- /dev/null +++ b/google/ads/googleads/v24/resources/types/audience.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import audiences +from google.ads.googleads.v24.enums.types import audience_scope +from google.ads.googleads.v24.enums.types import audience_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "Audience", + }, +) + + +class Audience(proto.Message): + r"""Audience is an effective targeting option that lets you + intersect different segment attributes, such as detailed + demographics and affinities, to create audiences that represent + sections of your target segments. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the audience. Audience names + have the form: + + ``customers/{customer_id}/audiences/{audience_id}`` + id (int): + Output only. ID of the audience. + status (google.ads.googleads.v24.enums.types.AudienceStatusEnum.AudienceStatus): + Output only. Status of this audience. + Indicates whether the audience is enabled or + removed. + name (str): + Name of the audience. It should be unique across all + audiences within the account. It must have a minimum length + of 1 and maximum length of 255. Required when scope is not + set or is set to CUSTOMER. Cannot be set or updated when + scope is ASSET_GROUP. + + This field is a member of `oneof`_ ``_name``. + description (str): + Description of this audience. + dimensions (MutableSequence[google.ads.googleads.v24.common.types.AudienceDimension]): + Positive dimensions specifying the audience + composition. + exclusion_dimension (google.ads.googleads.v24.common.types.AudienceExclusionDimension): + Negative dimension specifying the audience + composition. + scope (google.ads.googleads.v24.enums.types.AudienceScopeEnum.AudienceScope): + Defines the scope this audience can be used in. By default, + the scope is CUSTOMER. Audiences can be created with a scope + of ASSET_GROUP for exclusive use by a single asset_group. + Scope may change from ASSET_GROUP to CUSTOMER but not from + CUSTOMER to ASSET_GROUP. + asset_group (str): + Immutable. The asset group that this audience is scoped + under. Must be set if and only if scope is ASSET_GROUP. + Immutable after creation. If an audience with ASSET_GROUP + scope is upgraded to CUSTOMER scope, this field will + automatically be cleared. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + ) + status: audience_status.AudienceStatusEnum.AudienceStatus = proto.Field( + proto.ENUM, + number=3, + enum=audience_status.AudienceStatusEnum.AudienceStatus, + ) + name: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + description: str = proto.Field( + proto.STRING, + number=5, + ) + dimensions: MutableSequence[audiences.AudienceDimension] = ( + proto.RepeatedField( + proto.MESSAGE, + number=6, + message=audiences.AudienceDimension, + ) + ) + exclusion_dimension: audiences.AudienceExclusionDimension = proto.Field( + proto.MESSAGE, + number=7, + message=audiences.AudienceExclusionDimension, + ) + scope: audience_scope.AudienceScopeEnum.AudienceScope = proto.Field( + proto.ENUM, + number=8, + enum=audience_scope.AudienceScopeEnum.AudienceScope, + ) + asset_group: str = proto.Field( + proto.STRING, + number=9, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/batch_job.py b/google/ads/googleads/v24/resources/types/batch_job.py new file mode 100644 index 000000000..c68921bf4 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/batch_job.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import batch_job_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "BatchJob", + }, +) + + +class BatchJob(proto.Message): + r"""A list of mutates being processed asynchronously. The mutates + are uploaded by the user. The mutates themselves aren't readable + and the results of the job can only be read using + BatchJobService.ListBatchJobResults. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the batch job. Batch job + resource names have the form: + + ``customers/{customer_id}/batchJobs/{batch_job_id}`` + id (int): + Output only. ID of this batch job. + + This field is a member of `oneof`_ ``_id``. + next_add_sequence_token (str): + Output only. The next sequence token to use + when adding operations. Only set when the batch + job status is PENDING. + + This field is a member of `oneof`_ ``_next_add_sequence_token``. + metadata (google.ads.googleads.v24.resources.types.BatchJob.BatchJobMetadata): + Output only. Contains additional information + about this batch job. + status (google.ads.googleads.v24.enums.types.BatchJobStatusEnum.BatchJobStatus): + Output only. Status of this batch job. + long_running_operation (str): + Output only. The resource name of the + long-running operation that can be used to poll + for completion. Only set when the batch job + status is RUNNING or DONE. + + This field is a member of `oneof`_ ``_long_running_operation``. + """ + + class BatchJobMetadata(proto.Message): + r"""Additional information about the batch job. This message is + also used as metadata returned in batch job Long Running + Operations. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + creation_date_time (str): + Output only. The time when this batch job was + created. Formatted as yyyy-mm-dd hh:mm:ss. + Example: "2018-03-05 09:15:00". + + This field is a member of `oneof`_ ``_creation_date_time``. + start_date_time (str): + Output only. The time when this batch job + started running. Formatted as yyyy-mm-dd + hh:mm:ss. Example: "2018-03-05 09:15:30". + + This field is a member of `oneof`_ ``_start_date_time``. + completion_date_time (str): + Output only. The time when this batch job was + completed. Formatted as yyyy-MM-dd HH:mm:ss. + Example: "2018-03-05 09:16:00". + + This field is a member of `oneof`_ ``_completion_date_time``. + estimated_completion_ratio (float): + Output only. The fraction (between 0.0 and + 1.0) of mutates that have been processed. This + is empty if the job hasn't started running yet. + + This field is a member of `oneof`_ ``_estimated_completion_ratio``. + operation_count (int): + Output only. The number of mutate operations + in the batch job. + + This field is a member of `oneof`_ ``_operation_count``. + executed_operation_count (int): + Output only. The number of mutate operations + executed by the batch job. Present only if the + job has started running. + + This field is a member of `oneof`_ ``_executed_operation_count``. + execution_limit_seconds (int): + Immutable. The approximate upper bound for + how long a batch job can be executed, in + seconds. If the job runs more than the given + upper bound, the job will be canceled. + + This field is a member of `oneof`_ ``_execution_limit_seconds``. + """ + + creation_date_time: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + start_date_time: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + completion_date_time: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + estimated_completion_ratio: float = proto.Field( + proto.DOUBLE, + number=10, + optional=True, + ) + operation_count: int = proto.Field( + proto.INT64, + number=11, + optional=True, + ) + executed_operation_count: int = proto.Field( + proto.INT64, + number=12, + optional=True, + ) + execution_limit_seconds: int = proto.Field( + proto.INT32, + number=13, + optional=True, + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + next_add_sequence_token: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + metadata: BatchJobMetadata = proto.Field( + proto.MESSAGE, + number=4, + message=BatchJobMetadata, + ) + status: batch_job_status.BatchJobStatusEnum.BatchJobStatus = proto.Field( + proto.ENUM, + number=5, + enum=batch_job_status.BatchJobStatusEnum.BatchJobStatus, + ) + long_running_operation: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/bidding_data_exclusion.py b/google/ads/googleads/v24/resources/types/bidding_data_exclusion.py new file mode 100644 index 000000000..64071048b --- /dev/null +++ b/google/ads/googleads/v24/resources/types/bidding_data_exclusion.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import advertising_channel_type +from google.ads.googleads.v24.enums.types import device +from google.ads.googleads.v24.enums.types import seasonality_event_scope +from google.ads.googleads.v24.enums.types import seasonality_event_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "BiddingDataExclusion", + }, +) + + +class BiddingDataExclusion(proto.Message): + r"""Represents a bidding data exclusion. Bidding data exclusions + can be set in client accounts only, and cannot be used in + manager accounts. + + See "About data exclusions" at + https://support.google.com/google-ads/answer/10370710. + + Note: A customer account can have a maximum of 500 active + bidding data exclusions. + + Attributes: + resource_name (str): + Immutable. The resource name of the data exclusion. Data + exclusion resource names have the form: + + ``customers/{customer_id}/biddingDataExclusions/{data_exclusion_id}`` + data_exclusion_id (int): + Output only. The ID of the data exclusion. + scope (google.ads.googleads.v24.enums.types.SeasonalityEventScopeEnum.SeasonalityEventScope): + The scope of the data exclusion. + status (google.ads.googleads.v24.enums.types.SeasonalityEventStatusEnum.SeasonalityEventStatus): + Output only. The status of the data + exclusion. + start_date_time (str): + Required. The inclusive start time of the + data exclusion in yyyy-MM-dd HH:mm:ss format. + + A data exclusion is backward looking and should + be used for events that start in the past and + end either in the past or future. + end_date_time (str): + Required. The exclusive end time of the data exclusion in + yyyy-MM-dd HH:mm:ss format. + + The length of [start_date_time, end_date_time) interval must + be within (0, 14 days]. + name (str): + The name of the data exclusion. The name can + be at most 255 characters. + description (str): + The description of the data exclusion. The + description can be at most 2048 characters. + devices (MutableSequence[google.ads.googleads.v24.enums.types.DeviceEnum.Device]): + If not specified, all devices will be + included in this exclusion. Otherwise, only the + specified targeted devices will be included in + this exclusion. + campaigns (MutableSequence[str]): + The data exclusion will apply to the campaigns listed when + the scope of this exclusion is CAMPAIGN. The maximum number + of campaigns per event is 2000. Note: a data exclusion with + both advertising_channel_types and campaign_ids is not + supported. + advertising_channel_types (MutableSequence[google.ads.googleads.v24.enums.types.AdvertisingChannelTypeEnum.AdvertisingChannelType]): + The data_exclusion will apply to all the campaigns under the + listed channels retroactively as well as going forward when + the scope of this exclusion is CHANNEL. The supported + advertising channel types are DISPLAY, SEARCH and SHOPPING. + Note: a data exclusion with both advertising_channel_types + and campaign_ids is not supported. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + data_exclusion_id: int = proto.Field( + proto.INT64, + number=2, + ) + scope: ( + seasonality_event_scope.SeasonalityEventScopeEnum.SeasonalityEventScope + ) = proto.Field( + proto.ENUM, + number=3, + enum=seasonality_event_scope.SeasonalityEventScopeEnum.SeasonalityEventScope, + ) + status: ( + seasonality_event_status.SeasonalityEventStatusEnum.SeasonalityEventStatus + ) = proto.Field( + proto.ENUM, + number=4, + enum=seasonality_event_status.SeasonalityEventStatusEnum.SeasonalityEventStatus, + ) + start_date_time: str = proto.Field( + proto.STRING, + number=5, + ) + end_date_time: str = proto.Field( + proto.STRING, + number=6, + ) + name: str = proto.Field( + proto.STRING, + number=7, + ) + description: str = proto.Field( + proto.STRING, + number=8, + ) + devices: MutableSequence[device.DeviceEnum.Device] = proto.RepeatedField( + proto.ENUM, + number=9, + enum=device.DeviceEnum.Device, + ) + campaigns: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=10, + ) + advertising_channel_types: MutableSequence[ + advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType + ] = proto.RepeatedField( + proto.ENUM, + number=11, + enum=advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/bidding_seasonality_adjustment.py b/google/ads/googleads/v24/resources/types/bidding_seasonality_adjustment.py new file mode 100644 index 000000000..373300ffc --- /dev/null +++ b/google/ads/googleads/v24/resources/types/bidding_seasonality_adjustment.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import advertising_channel_type +from google.ads.googleads.v24.enums.types import device +from google.ads.googleads.v24.enums.types import seasonality_event_scope +from google.ads.googleads.v24.enums.types import seasonality_event_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "BiddingSeasonalityAdjustment", + }, +) + + +class BiddingSeasonalityAdjustment(proto.Message): + r"""Represents a bidding seasonality adjustment. Cannot be used + in manager accounts. + + See "About seasonality adjustments" at + https://support.google.com/google-ads/answer/10369906. + + Attributes: + resource_name (str): + Immutable. The resource name of the seasonality adjustment. + Seasonality adjustment resource names have the form: + + ``customers/{customer_id}/biddingSeasonalityAdjustments/{seasonality_adjustment_id}`` + seasonality_adjustment_id (int): + Output only. The ID of the seasonality + adjustment. + scope (google.ads.googleads.v24.enums.types.SeasonalityEventScopeEnum.SeasonalityEventScope): + The scope of the seasonality adjustment. + status (google.ads.googleads.v24.enums.types.SeasonalityEventStatusEnum.SeasonalityEventStatus): + Output only. The status of the seasonality + adjustment. + start_date_time (str): + Required. The inclusive start time of the + seasonality adjustment in yyyy-MM-dd HH:mm:ss + format. + + A seasonality adjustment is forward looking and + should be used for events that start and end in + the future. + end_date_time (str): + Required. The exclusive end time of the seasonality + adjustment in yyyy-MM-dd HH:mm:ss format. + + The length of [start_date_time, end_date_time) interval must + be within (0, 14 days]. + name (str): + The name of the seasonality adjustment. The + name can be at most 255 characters. + description (str): + The description of the seasonality + adjustment. The description can be at most 2048 + characters. + devices (MutableSequence[google.ads.googleads.v24.enums.types.DeviceEnum.Device]): + If not specified, all devices will be + included in this adjustment. Otherwise, only the + specified targeted devices will be included in + this adjustment. + conversion_rate_modifier (float): + Conversion rate modifier estimated based on + expected conversion rate changes. When this + field is unset or set to 1.0 no adjustment will + be applied to traffic. The allowed range is 0.1 + to 10.0. + campaigns (MutableSequence[str]): + The seasonality adjustment will apply to the campaigns + listed when the scope of this adjustment is CAMPAIGN. The + maximum number of campaigns per event is 2000. Note: a + seasonality adjustment with both advertising_channel_types + and campaign_ids is not supported. + advertising_channel_types (MutableSequence[google.ads.googleads.v24.enums.types.AdvertisingChannelTypeEnum.AdvertisingChannelType]): + The seasonality adjustment will apply to all the campaigns + under the listed channels retroactively as well as going + forward when the scope of this adjustment is CHANNEL. The + supported advertising channel types are DISPLAY, SEARCH and + SHOPPING. Note: a seasonality adjustment with both + advertising_channel_types and campaign_ids is not supported. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + seasonality_adjustment_id: int = proto.Field( + proto.INT64, + number=2, + ) + scope: ( + seasonality_event_scope.SeasonalityEventScopeEnum.SeasonalityEventScope + ) = proto.Field( + proto.ENUM, + number=3, + enum=seasonality_event_scope.SeasonalityEventScopeEnum.SeasonalityEventScope, + ) + status: ( + seasonality_event_status.SeasonalityEventStatusEnum.SeasonalityEventStatus + ) = proto.Field( + proto.ENUM, + number=4, + enum=seasonality_event_status.SeasonalityEventStatusEnum.SeasonalityEventStatus, + ) + start_date_time: str = proto.Field( + proto.STRING, + number=5, + ) + end_date_time: str = proto.Field( + proto.STRING, + number=6, + ) + name: str = proto.Field( + proto.STRING, + number=7, + ) + description: str = proto.Field( + proto.STRING, + number=8, + ) + devices: MutableSequence[device.DeviceEnum.Device] = proto.RepeatedField( + proto.ENUM, + number=9, + enum=device.DeviceEnum.Device, + ) + conversion_rate_modifier: float = proto.Field( + proto.DOUBLE, + number=10, + ) + campaigns: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=11, + ) + advertising_channel_types: MutableSequence[ + advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType + ] = proto.RepeatedField( + proto.ENUM, + number=12, + enum=advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/bidding_strategy.py b/google/ads/googleads/v24/resources/types/bidding_strategy.py new file mode 100644 index 000000000..c9915b440 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/bidding_strategy.py @@ -0,0 +1,260 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import bidding +from google.ads.googleads.v24.enums.types import bidding_strategy_status +from google.ads.googleads.v24.enums.types import bidding_strategy_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "BiddingStrategy", + }, +) + + +class BiddingStrategy(proto.Message): + r"""A bidding strategy. + + 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: + resource_name (str): + Immutable. The resource name of the bidding strategy. + Bidding strategy resource names have the form: + + ``customers/{customer_id}/biddingStrategies/{bidding_strategy_id}`` + id (int): + Output only. The ID of the bidding strategy. + + This field is a member of `oneof`_ ``_id``. + name (str): + The name of the bidding strategy. + All bidding strategies within an account must be + named distinctly. + + The length of this string should be between 1 + and 255, inclusive, in UTF-8 bytes, (trimmed). + + This field is a member of `oneof`_ ``_name``. + status (google.ads.googleads.v24.enums.types.BiddingStrategyStatusEnum.BiddingStrategyStatus): + Output only. The status of the bidding + strategy. + This field is read-only. + type_ (google.ads.googleads.v24.enums.types.BiddingStrategyTypeEnum.BiddingStrategyType): + Output only. The type of the bidding + strategy. Create a bidding strategy by setting + the bidding scheme. + + This field is read-only. + currency_code (str): + Immutable. The currency used by the bidding strategy (ISO + 4217 three-letter code). + + For bidding strategies in manager customers, this currency + can be set on creation and defaults to the manager + customer's currency. For serving customers, this field + cannot be set; all strategies in a serving customer + implicitly use the serving customer's currency. In all cases + the effective_currency_code field returns the currency used + by the strategy. + effective_currency_code (str): + Output only. The currency used by the bidding strategy (ISO + 4217 three-letter code). + + For bidding strategies in manager customers, this is the + currency set by the advertiser when creating the strategy. + For serving customers, this is the customer's currency_code. + + Bidding strategy metrics are reported in this currency. + + This field is read-only. + + This field is a member of `oneof`_ ``_effective_currency_code``. + aligned_campaign_budget_id (int): + ID of the campaign budget that this portfolio + bidding strategy is aligned with. When a + portfolio and a campaign budget are aligned, + that means that they are attached to the same + set of campaigns. After a bidding strategy is + aligned with a campaign budget, campaigns that + are added to the bidding strategy must also use + the aligned campaign budget. + campaign_count (int): + Output only. The number of campaigns attached + to this bidding strategy. + This field is read-only. + + This field is a member of `oneof`_ ``_campaign_count``. + non_removed_campaign_count (int): + Output only. The number of non-removed + campaigns attached to this bidding strategy. + + This field is read-only. + + This field is a member of `oneof`_ ``_non_removed_campaign_count``. + enhanced_cpc (google.ads.googleads.v24.common.types.EnhancedCpc): + A bidding strategy that raises bids for + clicks that seem more likely to lead to a + conversion and lowers them for clicks where they + seem less likely. + + This field is a member of `oneof`_ ``scheme``. + maximize_conversion_value (google.ads.googleads.v24.common.types.MaximizeConversionValue): + An automated bidding strategy to help get the + most conversion value for your campaigns while + spending your budget. + + This field is a member of `oneof`_ ``scheme``. + maximize_conversions (google.ads.googleads.v24.common.types.MaximizeConversions): + An automated bidding strategy to help get the + most conversions for your campaigns while + spending your budget. + + This field is a member of `oneof`_ ``scheme``. + target_cpa (google.ads.googleads.v24.common.types.TargetCpa): + A bidding strategy that sets bids to help get + as many conversions as possible at the target + cost-per-acquisition (CPA) you set. + + This field is a member of `oneof`_ ``scheme``. + target_impression_share (google.ads.googleads.v24.common.types.TargetImpressionShare): + A bidding strategy that automatically + optimizes towards a chosen percentage of + impressions. + + This field is a member of `oneof`_ ``scheme``. + target_roas (google.ads.googleads.v24.common.types.TargetRoas): + A bidding strategy that helps you maximize + revenue while averaging a specific target Return + On Ad Spend (ROAS). + + This field is a member of `oneof`_ ``scheme``. + target_spend (google.ads.googleads.v24.common.types.TargetSpend): + A bid strategy that sets your bids to help + get as many clicks as possible within your + budget. + + This field is a member of `oneof`_ ``scheme``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=16, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=17, + optional=True, + ) + status: ( + bidding_strategy_status.BiddingStrategyStatusEnum.BiddingStrategyStatus + ) = proto.Field( + proto.ENUM, + number=15, + enum=bidding_strategy_status.BiddingStrategyStatusEnum.BiddingStrategyStatus, + ) + type_: bidding_strategy_type.BiddingStrategyTypeEnum.BiddingStrategyType = ( + proto.Field( + proto.ENUM, + number=5, + enum=bidding_strategy_type.BiddingStrategyTypeEnum.BiddingStrategyType, + ) + ) + currency_code: str = proto.Field( + proto.STRING, + number=23, + ) + effective_currency_code: str = proto.Field( + proto.STRING, + number=20, + optional=True, + ) + aligned_campaign_budget_id: int = proto.Field( + proto.INT64, + number=25, + ) + campaign_count: int = proto.Field( + proto.INT64, + number=18, + optional=True, + ) + non_removed_campaign_count: int = proto.Field( + proto.INT64, + number=19, + optional=True, + ) + enhanced_cpc: bidding.EnhancedCpc = proto.Field( + proto.MESSAGE, + number=7, + oneof="scheme", + message=bidding.EnhancedCpc, + ) + maximize_conversion_value: bidding.MaximizeConversionValue = proto.Field( + proto.MESSAGE, + number=21, + oneof="scheme", + message=bidding.MaximizeConversionValue, + ) + maximize_conversions: bidding.MaximizeConversions = proto.Field( + proto.MESSAGE, + number=22, + oneof="scheme", + message=bidding.MaximizeConversions, + ) + target_cpa: bidding.TargetCpa = proto.Field( + proto.MESSAGE, + number=9, + oneof="scheme", + message=bidding.TargetCpa, + ) + target_impression_share: bidding.TargetImpressionShare = proto.Field( + proto.MESSAGE, + number=48, + oneof="scheme", + message=bidding.TargetImpressionShare, + ) + target_roas: bidding.TargetRoas = proto.Field( + proto.MESSAGE, + number=11, + oneof="scheme", + message=bidding.TargetRoas, + ) + target_spend: bidding.TargetSpend = proto.Field( + proto.MESSAGE, + number=12, + oneof="scheme", + message=bidding.TargetSpend, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/bidding_strategy_simulation.py b/google/ads/googleads/v24/resources/types/bidding_strategy_simulation.py new file mode 100644 index 000000000..bf97c9b1e --- /dev/null +++ b/google/ads/googleads/v24/resources/types/bidding_strategy_simulation.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import simulation +from google.ads.googleads.v24.enums.types import simulation_modification_method +from google.ads.googleads.v24.enums.types import simulation_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "BiddingStrategySimulation", + }, +) + + +class BiddingStrategySimulation(proto.Message): + r"""A bidding strategy simulation. Supported combinations of simulation + type and simulation modification method are detailed below + respectively. + + 1. TARGET_CPA - UNIFORM + 2. TARGET_ROAS - UNIFORM + + 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: + resource_name (str): + Output only. The resource name of the bidding strategy + simulation. Bidding strategy simulation resource names have + the form: + + ``customers/{customer_id}/biddingStrategySimulations/{bidding_strategy_id}~{type}~{modification_method}~{start_date}~{end_date}`` + bidding_strategy_id (int): + Output only. Bidding strategy shared set id + of the simulation. + type_ (google.ads.googleads.v24.enums.types.SimulationTypeEnum.SimulationType): + Output only. The field that the simulation + modifies. + modification_method (google.ads.googleads.v24.enums.types.SimulationModificationMethodEnum.SimulationModificationMethod): + Output only. How the simulation modifies the + field. + start_date (str): + Output only. First day on which the + simulation is based, in YYYY-MM-DD format. + end_date (str): + Output only. Last day on which the simulation + is based, in YYYY-MM-DD format + target_cpa_point_list (google.ads.googleads.v24.common.types.TargetCpaSimulationPointList): + Output only. Simulation points if the simulation type is + TARGET_CPA. + + This field is a member of `oneof`_ ``point_list``. + target_roas_point_list (google.ads.googleads.v24.common.types.TargetRoasSimulationPointList): + Output only. Simulation points if the simulation type is + TARGET_ROAS. + + This field is a member of `oneof`_ ``point_list``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + bidding_strategy_id: int = proto.Field( + proto.INT64, + number=2, + ) + type_: simulation_type.SimulationTypeEnum.SimulationType = proto.Field( + proto.ENUM, + number=3, + enum=simulation_type.SimulationTypeEnum.SimulationType, + ) + modification_method: ( + simulation_modification_method.SimulationModificationMethodEnum.SimulationModificationMethod + ) = proto.Field( + proto.ENUM, + number=4, + enum=simulation_modification_method.SimulationModificationMethodEnum.SimulationModificationMethod, + ) + start_date: str = proto.Field( + proto.STRING, + number=5, + ) + end_date: str = proto.Field( + proto.STRING, + number=6, + ) + target_cpa_point_list: simulation.TargetCpaSimulationPointList = ( + proto.Field( + proto.MESSAGE, + number=7, + oneof="point_list", + message=simulation.TargetCpaSimulationPointList, + ) + ) + target_roas_point_list: simulation.TargetRoasSimulationPointList = ( + proto.Field( + proto.MESSAGE, + number=8, + oneof="point_list", + message=simulation.TargetRoasSimulationPointList, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/billing_setup.py b/google/ads/googleads/v24/resources/types/billing_setup.py new file mode 100644 index 000000000..69c1ba591 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/billing_setup.py @@ -0,0 +1,224 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import billing_setup_status +from google.ads.googleads.v24.enums.types import time_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "BillingSetup", + }, +) + + +class BillingSetup(proto.Message): + r"""A billing setup, which associates a payments account and an + advertiser. A billing setup is specific to one advertiser. + + 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: + resource_name (str): + Immutable. The resource name of the billing setup. + BillingSetup resource names have the form: + + ``customers/{customer_id}/billingSetups/{billing_setup_id}`` + id (int): + Output only. The ID of the billing setup. + + This field is a member of `oneof`_ ``_id``. + status (google.ads.googleads.v24.enums.types.BillingSetupStatusEnum.BillingSetupStatus): + Output only. The status of the billing setup. + payments_account (str): + Immutable. The resource name of the payments account + associated with this billing setup. Payments resource names + have the form: + + ``customers/{customer_id}/paymentsAccounts/{payments_account_id}`` + When setting up billing, this is used to signup with an + existing payments account (and then payments_account_info + should not be set). When getting a billing setup, this and + payments_account_info will be populated. + + This field is a member of `oneof`_ ``_payments_account``. + payments_account_info (google.ads.googleads.v24.resources.types.BillingSetup.PaymentsAccountInfo): + Immutable. The payments account information associated with + this billing setup. When setting up billing, this is used to + signup with a new payments account (and then + payments_account should not be set). When getting a billing + setup, this and payments_account will be populated. + start_date_time (str): + Immutable. The start date time in yyyy-MM-dd + or yyyy-MM-dd HH:mm:ss format. Only a future + time is allowed. + + This field is a member of `oneof`_ ``start_time``. + start_time_type (google.ads.googleads.v24.enums.types.TimeTypeEnum.TimeType): + Immutable. The start time as a type. Only NOW + is allowed. + + This field is a member of `oneof`_ ``start_time``. + end_date_time (str): + Output only. The end date time in yyyy-MM-dd + or yyyy-MM-dd HH:mm:ss format. + + This field is a member of `oneof`_ ``end_time``. + end_time_type (google.ads.googleads.v24.enums.types.TimeTypeEnum.TimeType): + Output only. The end time as a type. The + only possible value is FOREVER. + + This field is a member of `oneof`_ ``end_time``. + """ + + class PaymentsAccountInfo(proto.Message): + r"""Container of payments account information for this billing. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + payments_account_id (str): + Output only. A 16 digit id used to identify + the payments account associated with the billing + setup. + + This must be passed as a string with dashes, for + example, "1234-5678-9012-3456". + + This field is a member of `oneof`_ ``_payments_account_id``. + payments_account_name (str): + Immutable. The name of the payments account + associated with the billing setup. + + This enables the user to specify a meaningful + name for a payments account to aid in + reconciling monthly invoices. + + This name will be printed in the monthly + invoices. + + This field is a member of `oneof`_ ``_payments_account_name``. + payments_profile_id (str): + Immutable. A 12 digit id used to identify the + payments profile associated with the billing + setup. + + This must be passed in as a string with dashes, + for example, "1234-5678-9012". + + This field is a member of `oneof`_ ``_payments_profile_id``. + payments_profile_name (str): + Output only. The name of the payments profile + associated with the billing setup. + + This field is a member of `oneof`_ ``_payments_profile_name``. + secondary_payments_profile_id (str): + Output only. A secondary payments profile id + present in uncommon situations, for example, + when a sequential liability agreement has been + arranged. + + This field is a member of `oneof`_ ``_secondary_payments_profile_id``. + """ + + payments_account_id: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + payments_account_name: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + payments_profile_id: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + payments_profile_name: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + secondary_payments_profile_id: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=15, + optional=True, + ) + status: billing_setup_status.BillingSetupStatusEnum.BillingSetupStatus = ( + proto.Field( + proto.ENUM, + number=3, + enum=billing_setup_status.BillingSetupStatusEnum.BillingSetupStatus, + ) + ) + payments_account: str = proto.Field( + proto.STRING, + number=18, + optional=True, + ) + payments_account_info: PaymentsAccountInfo = proto.Field( + proto.MESSAGE, + number=12, + message=PaymentsAccountInfo, + ) + start_date_time: str = proto.Field( + proto.STRING, + number=16, + oneof="start_time", + ) + start_time_type: time_type.TimeTypeEnum.TimeType = proto.Field( + proto.ENUM, + number=10, + oneof="start_time", + enum=time_type.TimeTypeEnum.TimeType, + ) + end_date_time: str = proto.Field( + proto.STRING, + number=17, + oneof="end_time", + ) + end_time_type: time_type.TimeTypeEnum.TimeType = proto.Field( + proto.ENUM, + number=14, + oneof="end_time", + enum=time_type.TimeTypeEnum.TimeType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/call_view.py b/google/ads/googleads/v24/resources/types/call_view.py new file mode 100644 index 000000000..c6799580b --- /dev/null +++ b/google/ads/googleads/v24/resources/types/call_view.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + call_tracking_display_location as gage_call_tracking_display_location, +) +from google.ads.googleads.v24.enums.types import call_type +from google.ads.googleads.v24.enums.types import google_voice_call_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CallView", + }, +) + + +class CallView(proto.Message): + r"""A call view that includes data for call tracking of call-only + ads or call extensions. + + Attributes: + resource_name (str): + Output only. The resource name of the call view. Call view + resource names have the form: + + ``customers/{customer_id}/callViews/{call_detail_id}`` + caller_country_code (str): + Output only. Country code of the caller. + caller_area_code (str): + Output only. Area code of the caller. Null if + the call duration is shorter than 15 seconds. + call_duration_seconds (int): + Output only. The advertiser-provided call + duration in seconds. + start_call_date_time (str): + Output only. The advertiser-provided call + start date time. + end_call_date_time (str): + Output only. The advertiser-provided call end + date time. + call_tracking_display_location (google.ads.googleads.v24.enums.types.CallTrackingDisplayLocationEnum.CallTrackingDisplayLocation): + Output only. The call tracking display + location. + type_ (google.ads.googleads.v24.enums.types.CallTypeEnum.CallType): + Output only. The type of the call. + call_status (google.ads.googleads.v24.enums.types.GoogleVoiceCallStatusEnum.GoogleVoiceCallStatus): + Output only. The status of the call. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + caller_country_code: str = proto.Field( + proto.STRING, + number=2, + ) + caller_area_code: str = proto.Field( + proto.STRING, + number=3, + ) + call_duration_seconds: int = proto.Field( + proto.INT64, + number=4, + ) + start_call_date_time: str = proto.Field( + proto.STRING, + number=5, + ) + end_call_date_time: str = proto.Field( + proto.STRING, + number=6, + ) + call_tracking_display_location: ( + gage_call_tracking_display_location.CallTrackingDisplayLocationEnum.CallTrackingDisplayLocation + ) = proto.Field( + proto.ENUM, + number=7, + enum=gage_call_tracking_display_location.CallTrackingDisplayLocationEnum.CallTrackingDisplayLocation, + ) + type_: call_type.CallTypeEnum.CallType = proto.Field( + proto.ENUM, + number=8, + enum=call_type.CallTypeEnum.CallType, + ) + call_status: ( + google_voice_call_status.GoogleVoiceCallStatusEnum.GoogleVoiceCallStatus + ) = proto.Field( + proto.ENUM, + number=9, + enum=google_voice_call_status.GoogleVoiceCallStatusEnum.GoogleVoiceCallStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign.py b/google/ads/googleads/v24/resources/types/campaign.py new file mode 100644 index 000000000..41eb2a05a --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign.py @@ -0,0 +1,2113 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import bidding +from google.ads.googleads.v24.common.types import custom_parameter +from google.ads.googleads.v24.common.types import frequency_cap +from google.ads.googleads.v24.common.types import ( + real_time_bidding_setting as gagc_real_time_bidding_setting, +) +from google.ads.googleads.v24.common.types import ( + targeting_setting as gagc_targeting_setting, +) +from google.ads.googleads.v24.common.types import ( + third_party_integration_partners as gagc_third_party_integration_partners, +) +from google.ads.googleads.v24.enums.types import ( + ad_group_type as gage_ad_group_type, +) +from google.ads.googleads.v24.enums.types import ( + ad_serving_optimization_status as gage_ad_serving_optimization_status, +) +from google.ads.googleads.v24.enums.types import ( + advertising_channel_sub_type as gage_advertising_channel_sub_type, +) +from google.ads.googleads.v24.enums.types import ( + advertising_channel_type as gage_advertising_channel_type, +) +from google.ads.googleads.v24.enums.types import app_campaign_app_store +from google.ads.googleads.v24.enums.types import ( + app_campaign_bidding_strategy_goal_type, +) +from google.ads.googleads.v24.enums.types import ( + asset_automation_status as gage_asset_automation_status, +) +from google.ads.googleads.v24.enums.types import ( + asset_automation_type as gage_asset_automation_type, +) +from google.ads.googleads.v24.enums.types import asset_field_type +from google.ads.googleads.v24.enums.types import asset_set_type +from google.ads.googleads.v24.enums.types import ( + bidding_strategy_system_status as gage_bidding_strategy_system_status, +) +from google.ads.googleads.v24.enums.types import ( + bidding_strategy_type as gage_bidding_strategy_type, +) +from google.ads.googleads.v24.enums.types import booking_status +from google.ads.googleads.v24.enums.types import campaign_experiment_type +from google.ads.googleads.v24.enums.types import campaign_keyword_match_type +from google.ads.googleads.v24.enums.types import campaign_primary_status +from google.ads.googleads.v24.enums.types import campaign_primary_status_reason +from google.ads.googleads.v24.enums.types import campaign_serving_status +from google.ads.googleads.v24.enums.types import campaign_status +from google.ads.googleads.v24.enums.types import eu_political_advertising_status +from google.ads.googleads.v24.enums.types import ( + listing_type as gage_listing_type, +) +from google.ads.googleads.v24.enums.types import ( + location_source_type as gage_location_source_type, +) +from google.ads.googleads.v24.enums.types import messaging_restriction_type +from google.ads.googleads.v24.enums.types import ( + negative_geo_target_type as gage_negative_geo_target_type, +) +from google.ads.googleads.v24.enums.types import non_skippable_max_duration +from google.ads.googleads.v24.enums.types import non_skippable_min_duration +from google.ads.googleads.v24.enums.types import optimization_goal_type +from google.ads.googleads.v24.enums.types import ( + payment_mode as gage_payment_mode, +) +from google.ads.googleads.v24.enums.types import performance_max_upgrade_status +from google.ads.googleads.v24.enums.types import ( + positive_geo_target_type as gage_positive_geo_target_type, +) +from google.ads.googleads.v24.enums.types import ( + vanity_pharma_display_url_mode as gage_vanity_pharma_display_url_mode, +) +from google.ads.googleads.v24.enums.types import ( + vanity_pharma_text as gage_vanity_pharma_text, +) +from google.ads.googleads.v24.enums.types import video_ad_format_restriction +from google.ads.googleads.v24.enums.types import ( + video_ad_sequence_interaction_type, +) +from google.ads.googleads.v24.enums.types import ( + video_ad_sequence_minimum_duration, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "Campaign", + }, +) + + +class Campaign(proto.Message): + r"""A campaign. + + 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: + resource_name (str): + Immutable. The resource name of the campaign. Campaign + resource names have the form: + + ``customers/{customer_id}/campaigns/{campaign_id}`` + id (int): + Output only. The ID of the campaign. + + This field is a member of `oneof`_ ``_id``. + name (str): + The name of the campaign. + + This field is required and should not be empty + when creating new campaigns. + + It must not contain any null (code point 0x0), + NL line feed (code point 0xA) or carriage return + (code point 0xD) characters. + + This field is a member of `oneof`_ ``_name``. + primary_status (google.ads.googleads.v24.enums.types.CampaignPrimaryStatusEnum.CampaignPrimaryStatus): + Output only. The primary status of the + campaign. + Provides insight into why a campaign is not + serving or not serving optimally. Modification + to the campaign and its related entities might + take a while to be reflected in this status. + primary_status_reasons (MutableSequence[google.ads.googleads.v24.enums.types.CampaignPrimaryStatusReasonEnum.CampaignPrimaryStatusReason]): + Output only. The primary status reasons of + the campaign. + Provides insight into why a campaign is not + serving or not serving optimally. These reasons + are aggregated to determine an overall + CampaignPrimaryStatus. + status (google.ads.googleads.v24.enums.types.CampaignStatusEnum.CampaignStatus): + The status of the campaign. + + When a new campaign is added, the status + defaults to ENABLED. + serving_status (google.ads.googleads.v24.enums.types.CampaignServingStatusEnum.CampaignServingStatus): + Output only. The ad serving status of the + campaign. + bidding_strategy_system_status (google.ads.googleads.v24.enums.types.BiddingStrategySystemStatusEnum.BiddingStrategySystemStatus): + Output only. The system status of the + campaign's bidding strategy. + ad_serving_optimization_status (google.ads.googleads.v24.enums.types.AdServingOptimizationStatusEnum.AdServingOptimizationStatus): + The ad serving optimization status of the + campaign. + advertising_channel_type (google.ads.googleads.v24.enums.types.AdvertisingChannelTypeEnum.AdvertisingChannelType): + Immutable. The primary serving target for ads within the + campaign. The targeting options can be refined in + ``network_settings``. + + This field is required and should not be empty when creating + new campaigns. + + Can be set only when creating campaigns. After the campaign + is created, the field can not be changed. + advertising_channel_sub_type (google.ads.googleads.v24.enums.types.AdvertisingChannelSubTypeEnum.AdvertisingChannelSubType): + Immutable. Optional refinement to + ``advertising_channel_type``. Must be a valid sub-type of + the parent channel type. + + Can be set only when creating campaigns. After campaign is + created, the field can not be changed. + tracking_url_template (str): + The URL template for constructing a tracking + URL. + + This field is a member of `oneof`_ ``_tracking_url_template``. + url_custom_parameters (MutableSequence[google.ads.googleads.v24.common.types.CustomParameter]): + The list of mappings used to substitute custom parameter + tags in a ``tracking_url_template``, ``final_urls``, or + ``mobile_final_urls``. + local_services_campaign_settings (google.ads.googleads.v24.resources.types.Campaign.LocalServicesCampaignSettings): + The Local Services Campaign related settings. + travel_campaign_settings (google.ads.googleads.v24.resources.types.Campaign.TravelCampaignSettings): + Settings for Travel campaign. + demand_gen_campaign_settings (google.ads.googleads.v24.resources.types.Campaign.DemandGenCampaignSettings): + Settings for Demand Gen campaign. + video_campaign_settings (google.ads.googleads.v24.resources.types.Campaign.VideoCampaignSettings): + Settings for Video campaign. + pmax_campaign_settings (google.ads.googleads.v24.resources.types.Campaign.PmaxCampaignSettings): + Settings for Performance Max campaign. + real_time_bidding_setting (google.ads.googleads.v24.common.types.RealTimeBiddingSetting): + Settings for Real-Time Bidding, a feature + only available for campaigns targeting the Ad + Exchange network. + network_settings (google.ads.googleads.v24.resources.types.Campaign.NetworkSettings): + The network settings for the campaign. + hotel_setting (google.ads.googleads.v24.resources.types.Campaign.HotelSettingInfo): + The hotel setting for the campaign. + dynamic_search_ads_setting (google.ads.googleads.v24.resources.types.Campaign.DynamicSearchAdsSetting): + The setting for controlling Dynamic Search + Ads (DSA). + shopping_setting (google.ads.googleads.v24.resources.types.Campaign.ShoppingSetting): + The setting for controlling Shopping + campaigns. + targeting_setting (google.ads.googleads.v24.common.types.TargetingSetting): + Setting for targeting related features. + audience_setting (google.ads.googleads.v24.resources.types.Campaign.AudienceSetting): + Immutable. Setting for audience related + features. + + This field is a member of `oneof`_ ``_audience_setting``. + geo_target_type_setting (google.ads.googleads.v24.resources.types.Campaign.GeoTargetTypeSetting): + The setting for ads geotargeting. + local_campaign_setting (google.ads.googleads.v24.resources.types.Campaign.LocalCampaignSetting): + The setting for local campaign. + app_campaign_setting (google.ads.googleads.v24.resources.types.Campaign.AppCampaignSetting): + The setting related to App Campaign. + labels (MutableSequence[str]): + Output only. The resource names of labels + attached to this campaign. + experiment_type (google.ads.googleads.v24.enums.types.CampaignExperimentTypeEnum.CampaignExperimentType): + Output only. The type of campaign: normal, + draft, or experiment. + base_campaign (str): + Output only. The resource name of the base campaign of a + draft or experiment campaign. For base campaigns, this is + equal to ``resource_name``. + + This field is read-only. + + This field is a member of `oneof`_ ``_base_campaign``. + campaign_budget (str): + The resource name of the campaign budget of + the campaign. + + This field is a member of `oneof`_ ``_campaign_budget``. + bidding_strategy_type (google.ads.googleads.v24.enums.types.BiddingStrategyTypeEnum.BiddingStrategyType): + Output only. The type of bidding strategy. + + A bidding strategy can be created by setting either the + bidding scheme to create a standard bidding strategy or the + ``bidding_strategy`` field to create a portfolio bidding + strategy. + + This field is read-only. + accessible_bidding_strategy (str): + Output only. Resource name of AccessibleBiddingStrategy, a + read-only view of the unrestricted attributes of the + attached portfolio bidding strategy identified by + 'bidding_strategy'. Empty, if the campaign does not use a + portfolio strategy. Unrestricted strategy attributes are + available to all customers with whom the strategy is shared + and are read from the AccessibleBiddingStrategy resource. In + contrast, restricted attributes are only available to the + owner customer of the strategy and their managers. + Restricted attributes can only be read from the + BiddingStrategy resource. + campaign_group (str): + The resource name of the campaign group that + this campaign belongs to. + + This field is a member of `oneof`_ ``_campaign_group``. + start_date_time (str): + The date and time when campaign started in + serving. The timestamp is in the customer's time + zone and in "yyyy-MM-dd HH:mm:ss" format. Set + the time component to 00:00:00 for daily + granularity, time granularity is only supported + for some campaign types. + + This field is a member of `oneof`_ ``_start_date_time``. + end_date_time (str): + The last day and time of the campaign in + serving customer's timezone in "yyyy-MM-dd + HH:mm:ss" format. Set the time component to + 23:59:59 for daily granularity, time granularity + is only supported for some campaign types. On + create, defaults to running indefinitely. To set + an existing campaign to run indefinitely, clear + this field. + + This field is a member of `oneof`_ ``_end_date_time``. + final_url_suffix (str): + Suffix used to append query parameters to + landing pages that are served with parallel + tracking. + + This field is a member of `oneof`_ ``_final_url_suffix``. + frequency_caps (MutableSequence[google.ads.googleads.v24.common.types.FrequencyCapEntry]): + A list that limits how often each user will + see this campaign's ads. + vanity_pharma (google.ads.googleads.v24.resources.types.Campaign.VanityPharma): + Describes how unbranded pharma ads will be + displayed. + selective_optimization (google.ads.googleads.v24.resources.types.Campaign.SelectiveOptimization): + Selective optimization setting for this campaign, which + includes a set of conversion actions to optimize this + campaign towards. This feature only applies to app campaigns + that use MULTI_CHANNEL as AdvertisingChannelType and + APP_CAMPAIGN or APP_CAMPAIGN_FOR_ENGAGEMENT as + AdvertisingChannelSubType. + optimization_goal_setting (google.ads.googleads.v24.resources.types.Campaign.OptimizationGoalSetting): + Optimization goal setting for this campaign, + which includes a set of optimization goal types. + tracking_setting (google.ads.googleads.v24.resources.types.Campaign.TrackingSetting): + Output only. Campaign-level settings for + tracking information. + payment_mode (google.ads.googleads.v24.enums.types.PaymentModeEnum.PaymentMode): + Payment mode for the campaign. + optimization_score (float): + Output only. Optimization score of the + campaign. + Optimization score is an estimate of how well a + campaign is set to perform. It ranges from 0% + (0.0) to 100% (1.0), with 100% indicating that + the campaign is performing at full potential. + This field is null for unscored campaigns. + + See "About optimization score" at + https://support.google.com/google-ads/answer/9061546. + + This field is read-only. + + This field is a member of `oneof`_ ``_optimization_score``. + excluded_parent_asset_field_types (MutableSequence[google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType]): + The asset field types that should be excluded + from this campaign. Asset links with these field + types will not be inherited by this campaign + from the upper level. + excluded_parent_asset_set_types (MutableSequence[google.ads.googleads.v24.enums.types.AssetSetTypeEnum.AssetSetType]): + The asset set types that should be excluded from this + campaign. Asset set links with these types will not be + inherited by this campaign from the upper level. Location + group types (GMB_DYNAMIC_LOCATION_GROUP, + CHAIN_DYNAMIC_LOCATION_GROUP, and STATIC_LOCATION_GROUP) are + child types of LOCATION_SYNC. Therefore, if LOCATION_SYNC is + set for this field, all location group asset sets are not + allowed to be linked to this campaign, and all Location + Extension (LE) and Affiliate Location Extensions (ALE) will + not be served under this campaign. Only LOCATION_SYNC is + currently supported. + performance_max_upgrade (google.ads.googleads.v24.resources.types.Campaign.PerformanceMaxUpgrade): + Output only. Information about campaigns + being upgraded to Performance Max. + hotel_property_asset_set (str): + Immutable. The resource name for a set of + hotel properties for Performance Max for travel + goals campaigns. + + This field is a member of `oneof`_ ``_hotel_property_asset_set``. + listing_type (google.ads.googleads.v24.enums.types.ListingTypeEnum.ListingType): + Immutable. Listing type of ads served for + this campaign. Field is restricted for usage + with Performance Max campaigns. + + This field is a member of `oneof`_ ``_listing_type``. + asset_automation_settings (MutableSequence[google.ads.googleads.v24.resources.types.Campaign.AssetAutomationSetting]): + Contains the opt-in/out status of each + AssetAutomationType. See documentation of each + asset automation type enum for default opt + in/out behavior. + keyword_match_type (google.ads.googleads.v24.enums.types.CampaignKeywordMatchTypeEnum.CampaignKeywordMatchType): + Keyword match type of Campaign. Set to BROAD + to set broad matching for all keywords in a + campaign. + brand_guidelines_enabled (bool): + Immutable. Whether Brand Guidelines are + enabled for this Campaign. Only applicable to + Performance Max campaigns. If enabled, business + name and logo assets must be linked as + CampaignAssets instead of AssetGroupAssets. + + Writable only at campaign creation. Set to true + to enable Brand Guidelines when creating a new + Performance Max campaign. + + Immutable after creation. This field cannot be + modified using standard update operations after + the campaign has been created. + + For existing campaigns: To enable Brand + Guidelines on a campaign after it has been + created, use the + CampaignService.EnablePMaxBrandGuidelines + method, which is a separate operation. It is not + possible to disable Brand Guidelines for an + existing campaign. + + Incompatible with Travel Goals: This feature is + not supported for Performance Max campaigns with + Travel Goals. Attempting to set this field to + true for a Travel Goals campaign will result in + an error. + + This field is a member of `oneof`_ ``_brand_guidelines_enabled``. + brand_guidelines (google.ads.googleads.v24.resources.types.Campaign.BrandGuidelines): + These settings control how your brand appears + in automatically generated assets and formats + within this campaign. Note: These settings can + only be used for Performance Max campaigns that + have Brand Guidelines enabled. + text_guidelines (google.ads.googleads.v24.resources.types.Campaign.TextGuidelines): + Settings to control automatically generated + text assets. Only available in Performance Max + and Search campaigns (Brand Guidelines does not + need to be enabled). + third_party_integration_partners (google.ads.googleads.v24.common.types.CampaignThirdPartyIntegrationPartners): + Third-Party integration partners. + ai_max_setting (google.ads.googleads.v24.resources.types.Campaign.AiMaxSetting): + Settings for AI Max in search campaigns. + contains_eu_political_advertising (google.ads.googleads.v24.enums.types.EuPoliticalAdvertisingStatusEnum.EuPoliticalAdvertisingStatus): + The advertiser should self-declare whether + this campaign contains political advertising + content targeted towards the European Union. + feed_types (MutableSequence[google.ads.googleads.v24.enums.types.AssetSetTypeEnum.AssetSetType]): + Output only. Types of feeds that are attached + directly to this campaign. + view_through_conversion_optimization_enabled (bool): + Whether VTC (View-through Conversion) + optimization is enabled for this campaign. Only + allowed for certain Demand Gen and App + Campaigns. + + This field is a member of `oneof`_ ``_view_through_conversion_optimization_enabled``. + missing_eu_political_advertising_declaration (bool): + Output only. Indicates whether this campaign is missing a + declaration about whether it contains political advertising + targeted towards the EU and is ineligible for any + exemptions. If this field is true, use the + contains_eu_political_advertising field to add the required + declaration. + + This field is read-only. + bidding_strategy (str): + The resource name of the portfolio bidding + strategy used by the campaign. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + commission (google.ads.googleads.v24.common.types.Commission): + Commission is an automatic bidding strategy + in which the advertiser pays a certain portion + of the conversion value. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + manual_cpa (google.ads.googleads.v24.common.types.ManualCpa): + Standard Manual CPA bidding strategy. + Manual bidding strategy that allows advertiser + to set the bid per advertiser-specified action. + Supported only for Local Services campaigns. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + manual_cpc (google.ads.googleads.v24.common.types.ManualCpc): + Standard Manual CPC bidding strategy. + Manual click-based bidding where user pays per + click. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + manual_cpm (google.ads.googleads.v24.common.types.ManualCpm): + Standard Manual CPM bidding strategy. + Manual impression-based bidding where user pays + per thousand impressions. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + manual_cpv (google.ads.googleads.v24.common.types.ManualCpv): + A bidding strategy that pays a configurable + amount per video view. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + maximize_conversions (google.ads.googleads.v24.common.types.MaximizeConversions): + Standard Maximize Conversions bidding + strategy that automatically maximizes number of + conversions while spending your budget. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + maximize_conversion_value (google.ads.googleads.v24.common.types.MaximizeConversionValue): + Standard Maximize Conversion Value bidding + strategy that automatically sets bids to + maximize revenue while spending your budget. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + target_cpa (google.ads.googleads.v24.common.types.TargetCpa): + Standard Target CPA bidding strategy that + automatically sets bids to help get as many + conversions as possible at the target + cost-per-acquisition (CPA) you set. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + target_impression_share (google.ads.googleads.v24.common.types.TargetImpressionShare): + Target Impression Share bidding strategy. An + automated bidding strategy that sets bids to + achieve a chosen percentage of impressions. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + target_roas (google.ads.googleads.v24.common.types.TargetRoas): + Standard Target ROAS bidding strategy that + automatically maximizes revenue while averaging + a specific target return on ad spend (ROAS). + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + target_spend (google.ads.googleads.v24.common.types.TargetSpend): + Standard Target Spend bidding strategy that + automatically sets your bids to help get as many + clicks as possible within your budget. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + percent_cpc (google.ads.googleads.v24.common.types.PercentCpc): + Standard Percent Cpc bidding strategy where + bids are a fraction of the advertised price for + some good or service. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + target_cpm (google.ads.googleads.v24.common.types.TargetCpm): + A bidding strategy that automatically + optimizes cost per thousand impressions. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + fixed_cpm (google.ads.googleads.v24.common.types.FixedCpm): + A manual bidding strategy with a fixed CPM. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + target_cpv (google.ads.googleads.v24.common.types.TargetCpv): + An automated bidding strategy that sets bids + to optimize performance given the target CPV you + set. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + target_cpc (google.ads.googleads.v24.common.types.TargetCpc): + An automated bidding strategy that sets bids + to help get as many clicks as possible at the + target cost-per-click (CPC) you set. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + """ + + class PerformanceMaxUpgrade(proto.Message): + r"""Information about a campaign being upgraded to Performance + Max. + + Attributes: + performance_max_campaign (str): + Output only. The resource name of the + Performance Max campaign the campaign is + upgraded to. + pre_upgrade_campaign (str): + Output only. The resource name of the legacy + campaign upgraded to Performance Max. + status (google.ads.googleads.v24.enums.types.PerformanceMaxUpgradeStatusEnum.PerformanceMaxUpgradeStatus): + Output only. The upgrade status of a campaign + requested to be upgraded to Performance Max. + """ + + performance_max_campaign: str = proto.Field( + proto.STRING, + number=1, + ) + pre_upgrade_campaign: str = proto.Field( + proto.STRING, + number=2, + ) + status: ( + performance_max_upgrade_status.PerformanceMaxUpgradeStatusEnum.PerformanceMaxUpgradeStatus + ) = proto.Field( + proto.ENUM, + number=3, + enum=performance_max_upgrade_status.PerformanceMaxUpgradeStatusEnum.PerformanceMaxUpgradeStatus, + ) + + class NetworkSettings(proto.Message): + r"""The network settings for the campaign. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_google_search (bool): + Whether ads will be served with google.com + search results. + + This field is a member of `oneof`_ ``_target_google_search``. + target_search_network (bool): + Whether ads will be served on sites in the Google Search + Partners Network (requires ``target_google_search`` to also + be ``true``). + + This field is a member of `oneof`_ ``_target_search_network``. + target_content_network (bool): + Whether ads will be served on specified + placements in the Google Display Network. + Placements are specified using the Placement + criterion. + + This field is a member of `oneof`_ ``_target_content_network``. + target_partner_search_network (bool): + Whether ads will be served on the partner network. This is + available only to some select partner accounts. Unless you + have been instructed to use this field, it likely does not + apply to your account. This does not control whether ads + will be served on Google Search Partners Network; use + ``target_search_network`` for that instead. + + This field is a member of `oneof`_ ``_target_partner_search_network``. + target_youtube (bool): + Whether ads will be served on YouTube. + + This field is a member of `oneof`_ ``_target_youtube``. + target_google_tv_network (bool): + Whether ads will be served on the Google TV + network. + + This field is a member of `oneof`_ ``_target_google_tv_network``. + """ + + target_google_search: bool = proto.Field( + proto.BOOL, + number=5, + optional=True, + ) + target_search_network: bool = proto.Field( + proto.BOOL, + number=6, + optional=True, + ) + target_content_network: bool = proto.Field( + proto.BOOL, + number=7, + optional=True, + ) + target_partner_search_network: bool = proto.Field( + proto.BOOL, + number=8, + optional=True, + ) + target_youtube: bool = proto.Field( + proto.BOOL, + number=9, + optional=True, + ) + target_google_tv_network: bool = proto.Field( + proto.BOOL, + number=10, + optional=True, + ) + + class HotelSettingInfo(proto.Message): + r"""Campaign-level settings for hotel ads. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + hotel_center_id (int): + The linked Hotel Center account. + + This field is a member of `oneof`_ ``_hotel_center_id``. + disable_hotel_setting (bool): + Disable the optional hotel setting. This + field is currently supported only for Demand Gen + campaigns. + + This field is a member of `oneof`_ ``_disable_hotel_setting``. + """ + + hotel_center_id: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + disable_hotel_setting: bool = proto.Field( + proto.BOOL, + number=3, + optional=True, + ) + + class DynamicSearchAdsSetting(proto.Message): + r"""The setting for controlling Dynamic Search Ads (DSA). + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + domain_name (str): + Required. The Internet domain name that this + setting represents, for example, "google.com" or + "www.google.com". + language_code (str): + Required. The language code specifying the + language of the domain, for example, "en". + use_supplied_urls_only (bool): + Whether the campaign uses advertiser supplied + URLs exclusively. + + This field is a member of `oneof`_ ``_use_supplied_urls_only``. + """ + + domain_name: str = proto.Field( + proto.STRING, + number=6, + ) + language_code: str = proto.Field( + proto.STRING, + number=7, + ) + use_supplied_urls_only: bool = proto.Field( + proto.BOOL, + number=8, + optional=True, + ) + + class ShoppingSetting(proto.Message): + r"""The setting for Shopping campaigns. Defines the universe of + products that can be advertised by the campaign, and how this + campaign interacts with other Shopping campaigns. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + merchant_id (int): + ID of the Merchant Center account. + This field is required for create operations. + This field is immutable for Shopping campaigns. + + This field is a member of `oneof`_ ``_merchant_id``. + feed_label (str): + Feed label of products to include in the campaign. Valid + feed labels may contain a maximum of 20 characters including + uppercase letters, numbers, hyphens, and underscores. If you + previously used the deprecated ``sales_country`` in the + two-letter country code (``XX``) format, the ``feed_label`` + field should be used instead. For more information see the + `feed + label `__ + support article. + campaign_priority (int): + Priority of the campaign. Campaigns with + numerically higher priorities take precedence + over those with lower priorities. This field is + required for Shopping campaigns, with values + between 0 and 2, inclusive. + This field is optional for Smart Shopping + campaigns, but must be equal to 3 if set. + + This field is a member of `oneof`_ ``_campaign_priority``. + enable_local (bool): + Whether to include local products. + + This field is a member of `oneof`_ ``_enable_local``. + use_vehicle_inventory (bool): + Immutable. Whether to target Vehicle Listing inventory. This + field is supported only in Smart Shopping Campaigns. For + setting Vehicle Listing inventory in Performance Max + campaigns, use ``listing_type`` instead. + advertising_partner_ids (MutableSequence[int]): + The list of Google Ads accounts IDs of + advertising partners cooperating within the + campaign. This feature is currently available + only for accounts having an advertising partner + link. Once set, the field is immutable. This + feature is currently supported only for + Performance Max, Shopping, Search and Demand Gen + campaign types. + disable_product_feed (bool): + Disable the optional product feed. This field + is currently supported only for Demand Gen + campaigns. See + https://support.google.com/google-ads/answer/13721750 + to learn more about this feature. + + This field is a member of `oneof`_ ``_disable_product_feed``. + """ + + merchant_id: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + feed_label: str = proto.Field( + proto.STRING, + number=10, + ) + campaign_priority: int = proto.Field( + proto.INT32, + number=7, + optional=True, + ) + enable_local: bool = proto.Field( + proto.BOOL, + number=8, + optional=True, + ) + use_vehicle_inventory: bool = proto.Field( + proto.BOOL, + number=9, + ) + advertising_partner_ids: MutableSequence[int] = proto.RepeatedField( + proto.INT64, + number=11, + ) + disable_product_feed: bool = proto.Field( + proto.BOOL, + number=12, + optional=True, + ) + + class TrackingSetting(proto.Message): + r"""Campaign-level settings for tracking information. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + tracking_url (str): + Output only. The url used for dynamic + tracking. + + This field is a member of `oneof`_ ``_tracking_url``. + """ + + tracking_url: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + class GeoTargetTypeSetting(proto.Message): + r"""Represents a collection of settings related to ads + geotargeting. + + Attributes: + positive_geo_target_type (google.ads.googleads.v24.enums.types.PositiveGeoTargetTypeEnum.PositiveGeoTargetType): + The setting used for positive geotargeting in + this particular campaign. + negative_geo_target_type (google.ads.googleads.v24.enums.types.NegativeGeoTargetTypeEnum.NegativeGeoTargetType): + The setting used for negative geotargeting in + this particular campaign. + """ + + positive_geo_target_type: ( + gage_positive_geo_target_type.PositiveGeoTargetTypeEnum.PositiveGeoTargetType + ) = proto.Field( + proto.ENUM, + number=1, + enum=gage_positive_geo_target_type.PositiveGeoTargetTypeEnum.PositiveGeoTargetType, + ) + negative_geo_target_type: ( + gage_negative_geo_target_type.NegativeGeoTargetTypeEnum.NegativeGeoTargetType + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_negative_geo_target_type.NegativeGeoTargetTypeEnum.NegativeGeoTargetType, + ) + + class LocalCampaignSetting(proto.Message): + r"""Campaign setting for local campaigns. + + Attributes: + location_source_type (google.ads.googleads.v24.enums.types.LocationSourceTypeEnum.LocationSourceType): + The location source type for this local + campaign. + """ + + location_source_type: ( + gage_location_source_type.LocationSourceTypeEnum.LocationSourceType + ) = proto.Field( + proto.ENUM, + number=1, + enum=gage_location_source_type.LocationSourceTypeEnum.LocationSourceType, + ) + + class AppCampaignSetting(proto.Message): + r"""Campaign-level settings for App Campaigns. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + bidding_strategy_goal_type (google.ads.googleads.v24.enums.types.AppCampaignBiddingStrategyGoalTypeEnum.AppCampaignBiddingStrategyGoalType): + Represents the goal which the bidding + strategy of this app campaign should optimize + towards. + app_id (str): + Immutable. A string that uniquely identifies + a mobile application. + + This field is a member of `oneof`_ ``_app_id``. + app_store (google.ads.googleads.v24.enums.types.AppCampaignAppStoreEnum.AppCampaignAppStore): + Immutable. The application store that + distributes this specific app. + """ + + bidding_strategy_goal_type: ( + app_campaign_bidding_strategy_goal_type.AppCampaignBiddingStrategyGoalTypeEnum.AppCampaignBiddingStrategyGoalType + ) = proto.Field( + proto.ENUM, + number=1, + enum=app_campaign_bidding_strategy_goal_type.AppCampaignBiddingStrategyGoalTypeEnum.AppCampaignBiddingStrategyGoalType, + ) + app_id: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + app_store: ( + app_campaign_app_store.AppCampaignAppStoreEnum.AppCampaignAppStore + ) = proto.Field( + proto.ENUM, + number=3, + enum=app_campaign_app_store.AppCampaignAppStoreEnum.AppCampaignAppStore, + ) + + class VanityPharma(proto.Message): + r"""Describes how unbranded pharma ads will be displayed. + + Attributes: + vanity_pharma_display_url_mode (google.ads.googleads.v24.enums.types.VanityPharmaDisplayUrlModeEnum.VanityPharmaDisplayUrlMode): + The display mode for vanity pharma URLs. + vanity_pharma_text (google.ads.googleads.v24.enums.types.VanityPharmaTextEnum.VanityPharmaText): + The text that will be displayed in display + URL of the text ad when website description is + the selected display mode for vanity pharma + URLs. + """ + + vanity_pharma_display_url_mode: ( + gage_vanity_pharma_display_url_mode.VanityPharmaDisplayUrlModeEnum.VanityPharmaDisplayUrlMode + ) = proto.Field( + proto.ENUM, + number=1, + enum=gage_vanity_pharma_display_url_mode.VanityPharmaDisplayUrlModeEnum.VanityPharmaDisplayUrlMode, + ) + vanity_pharma_text: ( + gage_vanity_pharma_text.VanityPharmaTextEnum.VanityPharmaText + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_vanity_pharma_text.VanityPharmaTextEnum.VanityPharmaText, + ) + + class SelectiveOptimization(proto.Message): + r"""Selective optimization setting for this campaign, which includes a + set of conversion actions to optimize this campaign towards. This + feature only applies to app campaigns that use MULTI_CHANNEL as + AdvertisingChannelType and APP_CAMPAIGN or + APP_CAMPAIGN_FOR_ENGAGEMENT as AdvertisingChannelSubType. + + Attributes: + conversion_actions (MutableSequence[str]): + The selected set of resource names for + conversion actions for optimizing this campaign. + """ + + conversion_actions: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + + class OptimizationGoalSetting(proto.Message): + r"""Optimization goal setting for this campaign, which includes a + set of optimization goal types. + + Attributes: + optimization_goal_types (MutableSequence[google.ads.googleads.v24.enums.types.OptimizationGoalTypeEnum.OptimizationGoalType]): + The list of optimization goal types. + """ + + optimization_goal_types: MutableSequence[ + optimization_goal_type.OptimizationGoalTypeEnum.OptimizationGoalType + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum=optimization_goal_type.OptimizationGoalTypeEnum.OptimizationGoalType, + ) + + class AudienceSetting(proto.Message): + r"""Settings for the audience targeting. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + use_audience_grouped (bool): + Immutable. If true, this campaign uses an + Audience resource for audience targeting. If + false, this campaign may use audience segment + criteria instead. + + This field is a member of `oneof`_ ``_use_audience_grouped``. + """ + + use_audience_grouped: bool = proto.Field( + proto.BOOL, + number=1, + optional=True, + ) + + class LocalServicesCampaignSettings(proto.Message): + r"""Settings for LocalServicesCampaign subresource. + + Attributes: + category_bids (MutableSequence[google.ads.googleads.v24.resources.types.Campaign.CategoryBid]): + Categorical level bids associated with MANUAL_CPA bidding + strategy. + """ + + category_bids: MutableSequence["Campaign.CategoryBid"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="Campaign.CategoryBid", + ) + ) + + class CategoryBid(proto.Message): + r"""Category bids in LocalServicesReportingCampaignSettings. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + category_id (str): + Category for which the bid will be associated with. For + example, xcat:service_area_business_plumber. + + This field is a member of `oneof`_ ``_category_id``. + manual_cpa_bid_micros (int): + Manual CPA bid for the category. Bid must be + greater than the reserve price associated for + that category. Value is in micros and in the + advertiser's currency. + + This field is a member of `oneof`_ ``_manual_cpa_bid_micros``. + target_cpa_bid_micros (int): + Target CPA bid for the category. Value is in + micros and in the advertiser's currency. + + This field is a member of `oneof`_ ``_target_cpa_bid_micros``. + """ + + category_id: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + manual_cpa_bid_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + target_cpa_bid_micros: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + + class TravelCampaignSettings(proto.Message): + r"""Settings for Travel campaign. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + travel_account_id (int): + Immutable. The Travel account ID associated + with the Travel campaign. + + This field is a member of `oneof`_ ``_travel_account_id``. + """ + + travel_account_id: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + + class DemandGenCampaignSettings(proto.Message): + r"""Settings for Demand Gen campaign. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + upgraded_targeting (bool): + Immutable. Specifies whether this campaign uses upgraded + targeting options. When this field is set to ``true``, you + can use location and language targeting at the ad group + level as opposed to the standard campaign-level targeting. + This field defaults to ``true``, and can only be set when + creating a campaign. + + This field is a member of `oneof`_ ``_upgraded_targeting``. + """ + + upgraded_targeting: bool = proto.Field( + proto.BOOL, + number=1, + optional=True, + ) + + class VideoCampaignSettings(proto.Message): + r"""Settings for Video campaign. + + 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: + video_ad_sequence (google.ads.googleads.v24.resources.types.Campaign.VideoCampaignSettings.VideoAdSequence): + Container for video ads sequencing + definition. + reservation_ad_category_self_disclosure (google.ads.googleads.v24.resources.types.Campaign.VideoCampaignSettings.ReservationAdCategorySelfDisclosure): + Ad category self-disclosure for campaigns with the FIXED_CPM + or FIXED_SHARE_OF_VOICE bidding strategies. + booking_details (google.ads.googleads.v24.resources.types.Campaign.VideoCampaignSettings.BookingDetails): + Output only. Booking information for campaigns with the + FIXED_CPM or FIXED_SHARE_OF_VOICE bidding strategies. + video_ad_inventory_control (google.ads.googleads.v24.resources.types.Campaign.VideoCampaignSettings.VideoAdInventoryControl): + Inventory control for video responsive ads in + reach campaigns. + + This field is a member of `oneof`_ ``fluidity_control``. + video_ad_format_control (google.ads.googleads.v24.resources.types.Campaign.VideoCampaignSettings.VideoAdFormatControl): + Format-restricting control enabling usage of + video responsive ads in format defined Video + campaigns (for example, non-skippable). + + This field is a member of `oneof`_ ``fluidity_control``. + """ + + class VideoAdInventoryControl(proto.Message): + r"""For campaigns using video responsive ads inventory controls + determine on which inventories the ads can be shown. This only + applies for campaigns with the bidding strategies TARGET_CPM and + FIXED_CPM. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + allow_in_stream (bool): + Determine if video responsive ads can be used + for in-stream video ads. + + This field is a member of `oneof`_ ``_allow_in_stream``. + allow_in_feed (bool): + Determine if video responsive ads can be used + for in-feed video ads. + + This field is a member of `oneof`_ ``_allow_in_feed``. + allow_shorts (bool): + Determine if video responsive ads can be used + as shorts format. + + This field is a member of `oneof`_ ``_allow_shorts``. + allow_non_skippable_in_stream (bool): + Determine if video responsive ads can be used + for non-skippable in-stream ads. This is only + available for campaigns that allow mixing of + non-skippable with other formats (Video reach + campaign with Target Frequency bidding strategy + goal). + + This field is a member of `oneof`_ ``_allow_non_skippable_in_stream``. + """ + + allow_in_stream: bool = proto.Field( + proto.BOOL, + number=1, + optional=True, + ) + allow_in_feed: bool = proto.Field( + proto.BOOL, + number=2, + optional=True, + ) + allow_shorts: bool = proto.Field( + proto.BOOL, + number=3, + optional=True, + ) + allow_non_skippable_in_stream: bool = proto.Field( + proto.BOOL, + number=4, + optional=True, + ) + + class VideoAdFormatControl(proto.Message): + r"""Format-restricting control enabling usage of video responsive + ads in format defined Video campaigns (for example, + non-skippable). + + Attributes: + format_restriction (google.ads.googleads.v24.enums.types.VideoAdFormatRestrictionEnum.VideoAdFormatRestriction): + All contained responsive ads are expected to + respect this restriction. + non_skippable_in_stream_restrictions (google.ads.googleads.v24.resources.types.Campaign.VideoCampaignSettings.NonSkippableInStreamRestrictions): + Restrictions for non-skippable format. + """ + + format_restriction: ( + video_ad_format_restriction.VideoAdFormatRestrictionEnum.VideoAdFormatRestriction + ) = proto.Field( + proto.ENUM, + number=1, + enum=video_ad_format_restriction.VideoAdFormatRestrictionEnum.VideoAdFormatRestriction, + ) + non_skippable_in_stream_restrictions: "Campaign.VideoCampaignSettings.NonSkippableInStreamRestrictions" = proto.Field( + proto.MESSAGE, + number=2, + message="Campaign.VideoCampaignSettings.NonSkippableInStreamRestrictions", + ) + + class NonSkippableInStreamRestrictions(proto.Message): + r"""Restrictions for non-skippable format. + + Attributes: + min_duration (google.ads.googleads.v24.enums.types.NonSkippableMinDurationEnum.NonSkippableMinDuration): + The minimum allowed duration for + non-skippable ads. + max_duration (google.ads.googleads.v24.enums.types.NonSkippableMaxDurationEnum.NonSkippableMaxDuration): + The maximum allowed duration for + non-skippable ads. + """ + + min_duration: ( + non_skippable_min_duration.NonSkippableMinDurationEnum.NonSkippableMinDuration + ) = proto.Field( + proto.ENUM, + number=1, + enum=non_skippable_min_duration.NonSkippableMinDurationEnum.NonSkippableMinDuration, + ) + max_duration: ( + non_skippable_max_duration.NonSkippableMaxDurationEnum.NonSkippableMaxDuration + ) = proto.Field( + proto.ENUM, + number=2, + enum=non_skippable_max_duration.NonSkippableMaxDurationEnum.NonSkippableMaxDuration, + ) + + class VideoAdSequence(proto.Message): + r"""Container for video ads sequencing definition. + + Attributes: + steps (MutableSequence[google.ads.googleads.v24.resources.types.Campaign.VideoCampaignSettings.VideoAdSequenceStep]): + The list of sequence steps and data + associated with them. + minimum_duration (google.ads.googleads.v24.enums.types.VideoAdSequenceMinimumDurationEnum.VideoAdSequenceMinimumDuration): + Users are eligible to repeat sequence after + this period. Defaults to WEEK if not specified. + """ + + steps: MutableSequence[ + "Campaign.VideoCampaignSettings.VideoAdSequenceStep" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="Campaign.VideoCampaignSettings.VideoAdSequenceStep", + ) + minimum_duration: ( + video_ad_sequence_minimum_duration.VideoAdSequenceMinimumDurationEnum.VideoAdSequenceMinimumDuration + ) = proto.Field( + proto.ENUM, + number=2, + enum=video_ad_sequence_minimum_duration.VideoAdSequenceMinimumDurationEnum.VideoAdSequenceMinimumDuration, + ) + + class VideoAdSequenceStep(proto.Message): + r"""Information about a step within a video sequence. + + Attributes: + video_ad_sequence_step_id (int): + The ID of this sequence step. + asset_id (int): + The ID of the Asset for this step. The asset must be type + YOUTUBE_VIDEO. + ad_group_type (google.ads.googleads.v24.enums.types.AdGroupTypeEnum.AdGroupType): + The ad group type for this step (denoting the + video format). + previous_step_id (int): + The ID of the previous step. This field is + required for all steps except the first one. It + must point to a step that appears in the step + definition list before this step. + previous_step_interaction_type (google.ads.googleads.v24.enums.types.VideoAdSequenceInteractionTypeEnum.VideoAdSequenceInteractionType): + Type of interaction *on the previous step* required in order + for the user to advance to this step. As with the previous + step ID, it's required for every step except for the first + one. + """ + + video_ad_sequence_step_id: int = proto.Field( + proto.INT64, + number=1, + ) + asset_id: int = proto.Field( + proto.INT64, + number=2, + ) + ad_group_type: gage_ad_group_type.AdGroupTypeEnum.AdGroupType = ( + proto.Field( + proto.ENUM, + number=3, + enum=gage_ad_group_type.AdGroupTypeEnum.AdGroupType, + ) + ) + previous_step_id: int = proto.Field( + proto.INT64, + number=4, + ) + previous_step_interaction_type: ( + video_ad_sequence_interaction_type.VideoAdSequenceInteractionTypeEnum.VideoAdSequenceInteractionType + ) = proto.Field( + proto.ENUM, + number=5, + enum=video_ad_sequence_interaction_type.VideoAdSequenceInteractionTypeEnum.VideoAdSequenceInteractionType, + ) + + class ReservationAdCategorySelfDisclosure(proto.Message): + r"""Container for ad category self-disclosure for campaigns with the + FIXED_CPM or FIXED_SHARE_OF_VOICE bidding strategies. + + Attributes: + gambling (bool): + The campaign is expected to contain + gambling-related ads. + alcohol (bool): + The campaign is expected to contain + alcohol-related ads. + politics (bool): + The campaign is expected to contain + politics-related ads. + """ + + gambling: bool = proto.Field( + proto.BOOL, + number=1, + ) + alcohol: bool = proto.Field( + proto.BOOL, + number=2, + ) + politics: bool = proto.Field( + proto.BOOL, + number=3, + ) + + class BookingDetails(proto.Message): + r"""Container for booking details for campaigns with the FIXED_CPM or + FIXED_SHARE_OF_VOICE bidding strategies. + + Attributes: + status (google.ads.googleads.v24.enums.types.BookingStatusEnum.BookingStatus): + Output only. The status of the booking. + hold_expiration_date_time (str): + Output only. Time until which booked inventory will be held + or has been held for this campaign. Available for status + HELD and HOLD_EXPIRED. Format is "yyyy-MM-dd HH:mm:ss" in + the customer's time zone. + cancellation_date_time (str): + Output only. Time when the booked inventory of this campaign + will be cancelled or has been cancelled. Available for + primary status NOT_ELIGIBLE if the campaign will be + cancelled and for primary status reason BOOKING_CANCELLED. + Format is "yyyy-MM-dd HH:mm:ss" in the customer's time zone. + """ + + status: booking_status.BookingStatusEnum.BookingStatus = ( + proto.Field( + proto.ENUM, + number=1, + enum=booking_status.BookingStatusEnum.BookingStatus, + ) + ) + hold_expiration_date_time: str = proto.Field( + proto.STRING, + number=2, + ) + cancellation_date_time: str = proto.Field( + proto.STRING, + number=3, + ) + + video_ad_sequence: "Campaign.VideoCampaignSettings.VideoAdSequence" = ( + proto.Field( + proto.MESSAGE, + number=4, + message="Campaign.VideoCampaignSettings.VideoAdSequence", + ) + ) + reservation_ad_category_self_disclosure: ( + "Campaign.VideoCampaignSettings.ReservationAdCategorySelfDisclosure" + ) = proto.Field( + proto.MESSAGE, + number=5, + message="Campaign.VideoCampaignSettings.ReservationAdCategorySelfDisclosure", + ) + booking_details: "Campaign.VideoCampaignSettings.BookingDetails" = ( + proto.Field( + proto.MESSAGE, + number=6, + message="Campaign.VideoCampaignSettings.BookingDetails", + ) + ) + video_ad_inventory_control: ( + "Campaign.VideoCampaignSettings.VideoAdInventoryControl" + ) = proto.Field( + proto.MESSAGE, + number=2, + oneof="fluidity_control", + message="Campaign.VideoCampaignSettings.VideoAdInventoryControl", + ) + video_ad_format_control: ( + "Campaign.VideoCampaignSettings.VideoAdFormatControl" + ) = proto.Field( + proto.MESSAGE, + number=3, + oneof="fluidity_control", + message="Campaign.VideoCampaignSettings.VideoAdFormatControl", + ) + + class PmaxCampaignSettings(proto.Message): + r"""Settings for Performance Max campaigns. + + Attributes: + brand_targeting_overrides (google.ads.googleads.v24.resources.types.Campaign.PmaxCampaignSettings.BrandTargetingOverrides): + Overrides of brand targeting for various ad + types. + """ + + class BrandTargetingOverrides(proto.Message): + r"""Overrides of brand targeting for various ad types. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + ignore_exclusions_for_shopping_ads (bool): + If true, brand exclusions are ignored for + Shopping ads. + + This field is a member of `oneof`_ ``_ignore_exclusions_for_shopping_ads``. + """ + + ignore_exclusions_for_shopping_ads: bool = proto.Field( + proto.BOOL, + number=1, + optional=True, + ) + + brand_targeting_overrides: ( + "Campaign.PmaxCampaignSettings.BrandTargetingOverrides" + ) = proto.Field( + proto.MESSAGE, + number=1, + message="Campaign.PmaxCampaignSettings.BrandTargetingOverrides", + ) + + class AssetAutomationSetting(proto.Message): + r"""Asset automation setting contains pair of AssetAutomationType + and the asset automation opt-in/out status + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + asset_automation_type (google.ads.googleads.v24.enums.types.AssetAutomationTypeEnum.AssetAutomationType): + The asset automation type advertiser would + like to opt-in/out. + + This field is a member of `oneof`_ ``_asset_automation_type``. + asset_automation_status (google.ads.googleads.v24.enums.types.AssetAutomationStatusEnum.AssetAutomationStatus): + The opt-in/out status of asset automation + type. + + This field is a member of `oneof`_ ``_asset_automation_status``. + """ + + asset_automation_type: ( + gage_asset_automation_type.AssetAutomationTypeEnum.AssetAutomationType + ) = proto.Field( + proto.ENUM, + number=1, + optional=True, + enum=gage_asset_automation_type.AssetAutomationTypeEnum.AssetAutomationType, + ) + asset_automation_status: ( + gage_asset_automation_status.AssetAutomationStatusEnum.AssetAutomationStatus + ) = proto.Field( + proto.ENUM, + number=2, + optional=True, + enum=gage_asset_automation_status.AssetAutomationStatusEnum.AssetAutomationStatus, + ) + + class BrandGuidelines(proto.Message): + r"""Settings that control the visual appearance of your brand in + a campaign's automatically generated assets and formats. Only + applicable to Performance Max campaigns. + + Attributes: + main_color (str): + The main brand color, entered as a hex code (e.g., #00ff00). + You must provide the main_color if you provide an + accent_color. + accent_color (str): + The accent brand color, entered as a hex code (e.g., + #00ff00). You must provide the accent_color if you provide a + main_color. + predefined_font_family (str): + The brand's font family. Must be one of the + following Google Fonts (case sensitive): Open + Sans, Roboto, Montserrat, Poppins, Lato, Oswald, + Playfair Display, Roboto Slab. + """ + + main_color: str = proto.Field( + proto.STRING, + number=1, + ) + accent_color: str = proto.Field( + proto.STRING, + number=2, + ) + predefined_font_family: str = proto.Field( + proto.STRING, + number=3, + ) + + class TextGuidelines(proto.Message): + r"""Settings to control automatically generated text assets. + + Attributes: + term_exclusions (MutableSequence[str]): + Exact words or phrases that will be excluded + from generated text assets. At most 25 + exclusions may be provided. Valid exclusions may + contain a maximum of 30 characters. + messaging_restrictions (MutableSequence[google.ads.googleads.v24.resources.types.Campaign.MessagingRestriction]): + Freeform instructions that will be used to + guide text asset generation using LLM inference. + At most 40 restrictions may be provided. + """ + + term_exclusions: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + messaging_restrictions: MutableSequence[ + "Campaign.MessagingRestriction" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="Campaign.MessagingRestriction", + ) + + class MessagingRestriction(proto.Message): + r"""Freeform instructions that will be used to guide text asset + generation using LLM inference. + + Attributes: + restriction_text (str): + Freeform instructions to guide text asset + generation using LLM inference. Valid + instructions may contain a maximum of 300 + characters. + restriction_type (google.ads.googleads.v24.enums.types.MessagingRestrictionTypeEnum.MessagingRestrictionType): + Determines how the guideline is applied. Only + ``RESTRICTION_BASED_EXCLUSION`` is currently supported. + """ + + restriction_text: str = proto.Field( + proto.STRING, + number=1, + ) + restriction_type: ( + messaging_restriction_type.MessagingRestrictionTypeEnum.MessagingRestrictionType + ) = proto.Field( + proto.ENUM, + number=2, + enum=messaging_restriction_type.MessagingRestrictionTypeEnum.MessagingRestrictionType, + ) + + class AiMaxSetting(proto.Message): + r"""Settings for AI Max in search campaigns. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + enable_ai_max (bool): + Controls whether or not AI Max features are served for this + campaign. + + Individual AI Max features are enabled or disabled by their + respective settings. But if enable_ai_max is set to false or + cleared, then no AI Max features will serve for this + campaign, regardless of the other settings. + + Search Term Matching is enabled by default when AI Max is + enabled, and can be disabled at the ad group level. + + This field is a member of `oneof`_ ``_enable_ai_max``. + bundling_required (google.ads.googleads.v24.resources.types.Campaign.AiMaxSetting.AiMaxBundlingRequired): + Output only. Indicates whether a search + campaign has adopted AI Max before, and is + required to have AI Max enabled to adopt + campaign-level text asset automation and brand + list targeting in all API versions. + + This field is a member of `oneof`_ ``_bundling_required``. + """ + + class AiMaxBundlingRequired(proto.Enum): + r"""Enum describing whether AI Max must be enabled to serve and + update text asset automation and brand list features newly + bundled with AI Max. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + NOT_REQUIRED (2): + Search campaign is using text asset + automation or brand list targeting, and AI Max + is not required to be enabled to serve these + features. + REQUIRED (3): + AI Max is required to be enabled for this + search campaign to serve existing text asset + automation and brand list targeting, or to add + new text asset automation and brand list + targeting settings. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NOT_REQUIRED = 2 + REQUIRED = 3 + + enable_ai_max: bool = proto.Field( + proto.BOOL, + number=1, + optional=True, + ) + bundling_required: "Campaign.AiMaxSetting.AiMaxBundlingRequired" = ( + proto.Field( + proto.ENUM, + number=2, + optional=True, + enum="Campaign.AiMaxSetting.AiMaxBundlingRequired", + ) + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=59, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=58, + optional=True, + ) + primary_status: ( + campaign_primary_status.CampaignPrimaryStatusEnum.CampaignPrimaryStatus + ) = proto.Field( + proto.ENUM, + number=81, + enum=campaign_primary_status.CampaignPrimaryStatusEnum.CampaignPrimaryStatus, + ) + primary_status_reasons: MutableSequence[ + campaign_primary_status_reason.CampaignPrimaryStatusReasonEnum.CampaignPrimaryStatusReason + ] = proto.RepeatedField( + proto.ENUM, + number=82, + enum=campaign_primary_status_reason.CampaignPrimaryStatusReasonEnum.CampaignPrimaryStatusReason, + ) + status: campaign_status.CampaignStatusEnum.CampaignStatus = proto.Field( + proto.ENUM, + number=5, + enum=campaign_status.CampaignStatusEnum.CampaignStatus, + ) + serving_status: ( + campaign_serving_status.CampaignServingStatusEnum.CampaignServingStatus + ) = proto.Field( + proto.ENUM, + number=21, + enum=campaign_serving_status.CampaignServingStatusEnum.CampaignServingStatus, + ) + bidding_strategy_system_status: ( + gage_bidding_strategy_system_status.BiddingStrategySystemStatusEnum.BiddingStrategySystemStatus + ) = proto.Field( + proto.ENUM, + number=78, + enum=gage_bidding_strategy_system_status.BiddingStrategySystemStatusEnum.BiddingStrategySystemStatus, + ) + ad_serving_optimization_status: ( + gage_ad_serving_optimization_status.AdServingOptimizationStatusEnum.AdServingOptimizationStatus + ) = proto.Field( + proto.ENUM, + number=8, + enum=gage_ad_serving_optimization_status.AdServingOptimizationStatusEnum.AdServingOptimizationStatus, + ) + advertising_channel_type: ( + gage_advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType + ) = proto.Field( + proto.ENUM, + number=9, + enum=gage_advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType, + ) + advertising_channel_sub_type: ( + gage_advertising_channel_sub_type.AdvertisingChannelSubTypeEnum.AdvertisingChannelSubType + ) = proto.Field( + proto.ENUM, + number=10, + enum=gage_advertising_channel_sub_type.AdvertisingChannelSubTypeEnum.AdvertisingChannelSubType, + ) + tracking_url_template: str = proto.Field( + proto.STRING, + number=60, + optional=True, + ) + url_custom_parameters: MutableSequence[custom_parameter.CustomParameter] = ( + proto.RepeatedField( + proto.MESSAGE, + number=12, + message=custom_parameter.CustomParameter, + ) + ) + local_services_campaign_settings: LocalServicesCampaignSettings = ( + proto.Field( + proto.MESSAGE, + number=75, + message=LocalServicesCampaignSettings, + ) + ) + travel_campaign_settings: TravelCampaignSettings = proto.Field( + proto.MESSAGE, + number=85, + message=TravelCampaignSettings, + ) + demand_gen_campaign_settings: DemandGenCampaignSettings = proto.Field( + proto.MESSAGE, + number=91, + message=DemandGenCampaignSettings, + ) + video_campaign_settings: VideoCampaignSettings = proto.Field( + proto.MESSAGE, + number=94, + message=VideoCampaignSettings, + ) + pmax_campaign_settings: PmaxCampaignSettings = proto.Field( + proto.MESSAGE, + number=97, + message=PmaxCampaignSettings, + ) + real_time_bidding_setting: ( + gagc_real_time_bidding_setting.RealTimeBiddingSetting + ) = proto.Field( + proto.MESSAGE, + number=39, + message=gagc_real_time_bidding_setting.RealTimeBiddingSetting, + ) + network_settings: NetworkSettings = proto.Field( + proto.MESSAGE, + number=14, + message=NetworkSettings, + ) + hotel_setting: HotelSettingInfo = proto.Field( + proto.MESSAGE, + number=32, + message=HotelSettingInfo, + ) + dynamic_search_ads_setting: DynamicSearchAdsSetting = proto.Field( + proto.MESSAGE, + number=33, + message=DynamicSearchAdsSetting, + ) + shopping_setting: ShoppingSetting = proto.Field( + proto.MESSAGE, + number=36, + message=ShoppingSetting, + ) + targeting_setting: gagc_targeting_setting.TargetingSetting = proto.Field( + proto.MESSAGE, + number=43, + message=gagc_targeting_setting.TargetingSetting, + ) + audience_setting: AudienceSetting = proto.Field( + proto.MESSAGE, + number=73, + optional=True, + message=AudienceSetting, + ) + geo_target_type_setting: GeoTargetTypeSetting = proto.Field( + proto.MESSAGE, + number=47, + message=GeoTargetTypeSetting, + ) + local_campaign_setting: LocalCampaignSetting = proto.Field( + proto.MESSAGE, + number=50, + message=LocalCampaignSetting, + ) + app_campaign_setting: AppCampaignSetting = proto.Field( + proto.MESSAGE, + number=51, + message=AppCampaignSetting, + ) + labels: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=61, + ) + experiment_type: ( + campaign_experiment_type.CampaignExperimentTypeEnum.CampaignExperimentType + ) = proto.Field( + proto.ENUM, + number=17, + enum=campaign_experiment_type.CampaignExperimentTypeEnum.CampaignExperimentType, + ) + base_campaign: str = proto.Field( + proto.STRING, + number=56, + optional=True, + ) + campaign_budget: str = proto.Field( + proto.STRING, + number=62, + optional=True, + ) + bidding_strategy_type: ( + gage_bidding_strategy_type.BiddingStrategyTypeEnum.BiddingStrategyType + ) = proto.Field( + proto.ENUM, + number=22, + enum=gage_bidding_strategy_type.BiddingStrategyTypeEnum.BiddingStrategyType, + ) + accessible_bidding_strategy: str = proto.Field( + proto.STRING, + number=71, + ) + campaign_group: str = proto.Field( + proto.STRING, + number=76, + optional=True, + ) + start_date_time: str = proto.Field( + proto.STRING, + number=104, + optional=True, + ) + end_date_time: str = proto.Field( + proto.STRING, + number=105, + optional=True, + ) + final_url_suffix: str = proto.Field( + proto.STRING, + number=65, + optional=True, + ) + frequency_caps: MutableSequence[frequency_cap.FrequencyCapEntry] = ( + proto.RepeatedField( + proto.MESSAGE, + number=40, + message=frequency_cap.FrequencyCapEntry, + ) + ) + vanity_pharma: VanityPharma = proto.Field( + proto.MESSAGE, + number=44, + message=VanityPharma, + ) + selective_optimization: SelectiveOptimization = proto.Field( + proto.MESSAGE, + number=45, + message=SelectiveOptimization, + ) + optimization_goal_setting: OptimizationGoalSetting = proto.Field( + proto.MESSAGE, + number=54, + message=OptimizationGoalSetting, + ) + tracking_setting: TrackingSetting = proto.Field( + proto.MESSAGE, + number=46, + message=TrackingSetting, + ) + payment_mode: gage_payment_mode.PaymentModeEnum.PaymentMode = proto.Field( + proto.ENUM, + number=52, + enum=gage_payment_mode.PaymentModeEnum.PaymentMode, + ) + optimization_score: float = proto.Field( + proto.DOUBLE, + number=66, + optional=True, + ) + excluded_parent_asset_field_types: MutableSequence[ + asset_field_type.AssetFieldTypeEnum.AssetFieldType + ] = proto.RepeatedField( + proto.ENUM, + number=69, + enum=asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + excluded_parent_asset_set_types: MutableSequence[ + asset_set_type.AssetSetTypeEnum.AssetSetType + ] = proto.RepeatedField( + proto.ENUM, + number=80, + enum=asset_set_type.AssetSetTypeEnum.AssetSetType, + ) + performance_max_upgrade: PerformanceMaxUpgrade = proto.Field( + proto.MESSAGE, + number=77, + message=PerformanceMaxUpgrade, + ) + hotel_property_asset_set: str = proto.Field( + proto.STRING, + number=83, + optional=True, + ) + listing_type: gage_listing_type.ListingTypeEnum.ListingType = proto.Field( + proto.ENUM, + number=86, + optional=True, + enum=gage_listing_type.ListingTypeEnum.ListingType, + ) + asset_automation_settings: MutableSequence[AssetAutomationSetting] = ( + proto.RepeatedField( + proto.MESSAGE, + number=88, + message=AssetAutomationSetting, + ) + ) + keyword_match_type: ( + campaign_keyword_match_type.CampaignKeywordMatchTypeEnum.CampaignKeywordMatchType + ) = proto.Field( + proto.ENUM, + number=90, + enum=campaign_keyword_match_type.CampaignKeywordMatchTypeEnum.CampaignKeywordMatchType, + ) + brand_guidelines_enabled: bool = proto.Field( + proto.BOOL, + number=96, + optional=True, + ) + brand_guidelines: BrandGuidelines = proto.Field( + proto.MESSAGE, + number=98, + message=BrandGuidelines, + ) + text_guidelines: TextGuidelines = proto.Field( + proto.MESSAGE, + number=107, + message=TextGuidelines, + ) + third_party_integration_partners: ( + gagc_third_party_integration_partners.CampaignThirdPartyIntegrationPartners + ) = proto.Field( + proto.MESSAGE, + number=100, + message=gagc_third_party_integration_partners.CampaignThirdPartyIntegrationPartners, + ) + ai_max_setting: AiMaxSetting = proto.Field( + proto.MESSAGE, + number=101, + message=AiMaxSetting, + ) + contains_eu_political_advertising: ( + eu_political_advertising_status.EuPoliticalAdvertisingStatusEnum.EuPoliticalAdvertisingStatus + ) = proto.Field( + proto.ENUM, + number=102, + enum=eu_political_advertising_status.EuPoliticalAdvertisingStatusEnum.EuPoliticalAdvertisingStatus, + ) + feed_types: MutableSequence[ + asset_set_type.AssetSetTypeEnum.AssetSetType + ] = proto.RepeatedField( + proto.ENUM, + number=103, + enum=asset_set_type.AssetSetTypeEnum.AssetSetType, + ) + view_through_conversion_optimization_enabled: bool = proto.Field( + proto.BOOL, + number=106, + optional=True, + ) + missing_eu_political_advertising_declaration: bool = proto.Field( + proto.BOOL, + number=108, + ) + bidding_strategy: str = proto.Field( + proto.STRING, + number=67, + oneof="campaign_bidding_strategy", + ) + commission: bidding.Commission = proto.Field( + proto.MESSAGE, + number=49, + oneof="campaign_bidding_strategy", + message=bidding.Commission, + ) + manual_cpa: bidding.ManualCpa = proto.Field( + proto.MESSAGE, + number=74, + oneof="campaign_bidding_strategy", + message=bidding.ManualCpa, + ) + manual_cpc: bidding.ManualCpc = proto.Field( + proto.MESSAGE, + number=24, + oneof="campaign_bidding_strategy", + message=bidding.ManualCpc, + ) + manual_cpm: bidding.ManualCpm = proto.Field( + proto.MESSAGE, + number=25, + oneof="campaign_bidding_strategy", + message=bidding.ManualCpm, + ) + manual_cpv: bidding.ManualCpv = proto.Field( + proto.MESSAGE, + number=37, + oneof="campaign_bidding_strategy", + message=bidding.ManualCpv, + ) + maximize_conversions: bidding.MaximizeConversions = proto.Field( + proto.MESSAGE, + number=30, + oneof="campaign_bidding_strategy", + message=bidding.MaximizeConversions, + ) + maximize_conversion_value: bidding.MaximizeConversionValue = proto.Field( + proto.MESSAGE, + number=31, + oneof="campaign_bidding_strategy", + message=bidding.MaximizeConversionValue, + ) + target_cpa: bidding.TargetCpa = proto.Field( + proto.MESSAGE, + number=26, + oneof="campaign_bidding_strategy", + message=bidding.TargetCpa, + ) + target_impression_share: bidding.TargetImpressionShare = proto.Field( + proto.MESSAGE, + number=48, + oneof="campaign_bidding_strategy", + message=bidding.TargetImpressionShare, + ) + target_roas: bidding.TargetRoas = proto.Field( + proto.MESSAGE, + number=29, + oneof="campaign_bidding_strategy", + message=bidding.TargetRoas, + ) + target_spend: bidding.TargetSpend = proto.Field( + proto.MESSAGE, + number=27, + oneof="campaign_bidding_strategy", + message=bidding.TargetSpend, + ) + percent_cpc: bidding.PercentCpc = proto.Field( + proto.MESSAGE, + number=34, + oneof="campaign_bidding_strategy", + message=bidding.PercentCpc, + ) + target_cpm: bidding.TargetCpm = proto.Field( + proto.MESSAGE, + number=41, + oneof="campaign_bidding_strategy", + message=bidding.TargetCpm, + ) + fixed_cpm: bidding.FixedCpm = proto.Field( + proto.MESSAGE, + number=92, + oneof="campaign_bidding_strategy", + message=bidding.FixedCpm, + ) + target_cpv: bidding.TargetCpv = proto.Field( + proto.MESSAGE, + number=93, + oneof="campaign_bidding_strategy", + message=bidding.TargetCpv, + ) + target_cpc: bidding.TargetCpc = proto.Field( + proto.MESSAGE, + number=99, + oneof="campaign_bidding_strategy", + message=bidding.TargetCpc, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_aggregate_asset_view.py b/google/ads/googleads/v24/resources/types/campaign_aggregate_asset_view.py new file mode 100644 index 000000000..e21eaa0ac --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_aggregate_asset_view.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import asset_field_type +from google.ads.googleads.v24.enums.types import ( + asset_source as gage_asset_source, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignAggregateAssetView", + }, +) + + +class CampaignAggregateAssetView(proto.Message): + r"""A campaign-level aggregate asset view that shows where the + asset is linked, performamce of the asset and stats. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the campaign aggregate + asset view. Campaign aggregate asset view resource names + have the form: + + ``customers/{customer_id}/campaignAggregateAssetViews/{Campaign.campaign_id}~{Asset.asset_id}~{AssetLinkSource.asset_link_source}~{AssetFieldType.field_type}`` + campaign (str): + Output only. Campaign in which the asset + served. + + This field is a member of `oneof`_ ``_campaign``. + asset (str): + Output only. The ID of the asset. + + This field is a member of `oneof`_ ``_asset``. + asset_source (google.ads.googleads.v24.enums.types.AssetSourceEnum.AssetSource): + Output only. Source of the asset link. + + This field is a member of `oneof`_ ``_asset_source``. + field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + Output only. FieldType of the asset. + + This field is a member of `oneof`_ ``_field_type``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + asset: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + asset_source: gage_asset_source.AssetSourceEnum.AssetSource = proto.Field( + proto.ENUM, + number=4, + optional=True, + enum=gage_asset_source.AssetSourceEnum.AssetSource, + ) + field_type: asset_field_type.AssetFieldTypeEnum.AssetFieldType = ( + proto.Field( + proto.ENUM, + number=5, + optional=True, + enum=asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_asset.py b/google/ads/googleads/v24/resources/types/campaign_asset.py new file mode 100644 index 000000000..8236576bd --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_asset.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import asset_policy +from google.ads.googleads.v24.enums.types import asset_field_type +from google.ads.googleads.v24.enums.types import asset_link_primary_status +from google.ads.googleads.v24.enums.types import ( + asset_link_primary_status_reason, +) +from google.ads.googleads.v24.enums.types import asset_link_status +from google.ads.googleads.v24.enums.types import asset_source + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignAsset", + }, +) + + +class CampaignAsset(proto.Message): + r"""A link between a Campaign and an Asset. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the campaign asset. + CampaignAsset resource names have the form: + + ``customers/{customer_id}/campaignAssets/{campaign_id}~{asset_id}~{field_type}`` + campaign (str): + Immutable. The campaign to which the asset is + linked. + + This field is a member of `oneof`_ ``_campaign``. + asset (str): + Immutable. The asset which is linked to the + campaign. + + This field is a member of `oneof`_ ``_asset``. + field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + Immutable. Role that the asset takes under + the linked campaign. Required. + source (google.ads.googleads.v24.enums.types.AssetSourceEnum.AssetSource): + Output only. Source of the campaign asset + link. + status (google.ads.googleads.v24.enums.types.AssetLinkStatusEnum.AssetLinkStatus): + Status of the campaign asset. + primary_status (google.ads.googleads.v24.enums.types.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus): + Output only. Provides the PrimaryStatus of + this asset link. Primary status is meant + essentially to differentiate between the plain + "status" field, which has advertiser set values + of enabled, paused, or removed. The primary + status takes into account other signals (for + assets its mainly policy and quality approvals) + to come up with a more comprehensive status to + indicate its serving state. + primary_status_details (MutableSequence[google.ads.googleads.v24.common.types.AssetLinkPrimaryStatusDetails]): + Output only. Provides the details of the + primary status and its associated reasons. + primary_status_reasons (MutableSequence[google.ads.googleads.v24.enums.types.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason]): + Output only. Provides a list of reasons for + why an asset is not serving or not serving at + full capacity. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + asset: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + field_type: asset_field_type.AssetFieldTypeEnum.AssetFieldType = ( + proto.Field( + proto.ENUM, + number=4, + enum=asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + ) + source: asset_source.AssetSourceEnum.AssetSource = proto.Field( + proto.ENUM, + number=8, + enum=asset_source.AssetSourceEnum.AssetSource, + ) + status: asset_link_status.AssetLinkStatusEnum.AssetLinkStatus = proto.Field( + proto.ENUM, + number=5, + enum=asset_link_status.AssetLinkStatusEnum.AssetLinkStatus, + ) + primary_status: ( + asset_link_primary_status.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus + ) = proto.Field( + proto.ENUM, + number=9, + enum=asset_link_primary_status.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus, + ) + primary_status_details: MutableSequence[ + asset_policy.AssetLinkPrimaryStatusDetails + ] = proto.RepeatedField( + proto.MESSAGE, + number=10, + message=asset_policy.AssetLinkPrimaryStatusDetails, + ) + primary_status_reasons: MutableSequence[ + asset_link_primary_status_reason.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason + ] = proto.RepeatedField( + proto.ENUM, + number=11, + enum=asset_link_primary_status_reason.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_asset_set.py b/google/ads/googleads/v24/resources/types/campaign_asset_set.py new file mode 100644 index 000000000..1a0b3d000 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_asset_set.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import asset_set_link_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignAssetSet", + }, +) + + +class CampaignAssetSet(proto.Message): + r"""CampaignAssetSet is the linkage between a campaign and an + asset set. Adding a CampaignAssetSet links an asset set with a + campaign. + + Attributes: + resource_name (str): + Immutable. The resource name of the campaign asset set. + Asset set asset resource names have the form: + + ``customers/{customer_id}/campaignAssetSets/{campaign_id}~{asset_set_id}`` + campaign (str): + Immutable. The campaign to which this asset + set is linked. + asset_set (str): + Immutable. The asset set which is linked to + the campaign. + status (google.ads.googleads.v24.enums.types.AssetSetLinkStatusEnum.AssetSetLinkStatus): + Output only. The status of the campaign asset + set asset. Read-only. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=2, + ) + asset_set: str = proto.Field( + proto.STRING, + number=3, + ) + status: asset_set_link_status.AssetSetLinkStatusEnum.AssetSetLinkStatus = ( + proto.Field( + proto.ENUM, + number=4, + enum=asset_set_link_status.AssetSetLinkStatusEnum.AssetSetLinkStatus, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_audience_view.py b/google/ads/googleads/v24/resources/types/campaign_audience_view.py new file mode 100644 index 000000000..5d8e3ef08 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_audience_view.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignAudienceView", + }, +) + + +class CampaignAudienceView(proto.Message): + r"""A campaign audience view. + Includes performance data from interests and remarketing lists + for Display Network and YouTube Network ads, and remarketing + lists for search ads (RLSA), aggregated by campaign and audience + criterion. This view only includes audiences attached at the + campaign level. + + Attributes: + resource_name (str): + Output only. The resource name of the campaign audience + view. Campaign audience view resource names have the form: + + ``customers/{customer_id}/campaignAudienceViews/{campaign_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_bid_modifier.py b/google/ads/googleads/v24/resources/types/campaign_bid_modifier.py new file mode 100644 index 000000000..0cd491081 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_bid_modifier.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import criteria + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignBidModifier", + }, +) + + +class CampaignBidModifier(proto.Message): + r"""Represents a bid-modifiable only criterion at the campaign + level. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the campaign bid modifier. + Campaign bid modifier resource names have the form: + + ``customers/{customer_id}/campaignBidModifiers/{campaign_id}~{criterion_id}`` + campaign (str): + Output only. The campaign to which this + criterion belongs. + + This field is a member of `oneof`_ ``_campaign``. + criterion_id (int): + Output only. The ID of the criterion to bid + modify. + This field is ignored for mutates. + + This field is a member of `oneof`_ ``_criterion_id``. + bid_modifier (float): + The modifier for the bid when the criterion + matches. + + This field is a member of `oneof`_ ``_bid_modifier``. + interaction_type (google.ads.googleads.v24.common.types.InteractionTypeInfo): + Immutable. Criterion for interaction type. + Only supported for search campaigns. + + This field is a member of `oneof`_ ``criterion``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + criterion_id: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + bid_modifier: float = proto.Field( + proto.DOUBLE, + number=8, + optional=True, + ) + interaction_type: criteria.InteractionTypeInfo = proto.Field( + proto.MESSAGE, + number=5, + oneof="criterion", + message=criteria.InteractionTypeInfo, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_budget.py b/google/ads/googleads/v24/resources/types/campaign_budget.py new file mode 100644 index 000000000..cdcfe9981 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_budget.py @@ -0,0 +1,295 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import budget_delivery_method +from google.ads.googleads.v24.enums.types import budget_period +from google.ads.googleads.v24.enums.types import budget_status +from google.ads.googleads.v24.enums.types import budget_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignBudget", + }, +) + + +class CampaignBudget(proto.Message): + r"""A campaign budget. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the campaign budget. + Campaign budget resource names have the form: + + ``customers/{customer_id}/campaignBudgets/{campaign_budget_id}`` + id (int): + Output only. The ID of the campaign budget. + + A campaign budget is created using the + CampaignBudgetService create operation and is + assigned a budget ID. A budget ID can be shared + across different campaigns; the system will then + allocate the campaign budget among different + campaigns to get optimum results. + + This field is a member of `oneof`_ ``_id``. + name (str): + The name of the campaign budget. + + When creating a campaign budget through + CampaignBudgetService, every explicitly shared + campaign budget must have a non-null, non-empty + name. Campaign budgets that are not explicitly + shared derive their name from the attached + campaign's name. + + The length of this string must be between 1 and + 255, inclusive, in UTF-8 bytes, (trimmed). + + This field is a member of `oneof`_ ``_name``. + amount_micros (int): + The average daily amount to be spent by the campaign. This + field is used when the CampaignBudget ``period`` is set to + ``DAILY``, which is the default. + + Amount is specified in micros in the account's local + currency. One million micros is equivalent to one currency + unit. The effective monthly spend is capped at 30.4 times + this daily amount. + + This field is mutually exclusive with 'total_amount_micros'. + Only one of 'amount_micros' or 'total_amount_micros' should + be set. + + This field is a member of `oneof`_ ``_amount_micros``. + total_amount_micros (int): + The total amount to be spent by the campaign over its entire + duration. This field is used *only* when the CampaignBudget + ``period`` is set to ``CUSTOM_PERIOD``. It represents the + budget cap for the campaign's lifetime, rather than a daily + limit. The amount is specified in micros in the account's + local currency. One million micros is equivalent to one + currency unit. + + This field is mutually exclusive with 'amount_micros'. Only + one of 'total_amount_micros' or 'amount_micros' should be + set. + + This field is a member of `oneof`_ ``_total_amount_micros``. + status (google.ads.googleads.v24.enums.types.BudgetStatusEnum.BudgetStatus): + Output only. The status of this campaign + budget. This field is read-only. + delivery_method (google.ads.googleads.v24.enums.types.BudgetDeliveryMethodEnum.BudgetDeliveryMethod): + The delivery method that determines the rate + at which the campaign budget is spent. + + Defaults to STANDARD if unspecified in a create + operation. + explicitly_shared (bool): + Specifies whether the budget is explicitly + shared. Defaults to true if unspecified in a + create operation. + + If true, the budget was created with the purpose + of sharing across one or more campaigns. + + If false, the budget was created with the + intention of only being used with a single + campaign. The budget's name and status will stay + in sync with the campaign's name and status. + Attempting to share the budget with a second + campaign will result in an error. + + A non-shared budget can become an explicitly + shared. The same operation must also assign the + budget a name. + + A shared campaign budget can never become + non-shared. + + This field is a member of `oneof`_ ``_explicitly_shared``. + reference_count (int): + Output only. The number of campaigns actively + using the budget. + This field is read-only. + + This field is a member of `oneof`_ ``_reference_count``. + has_recommended_budget (bool): + Output only. Indicates whether there is a + recommended budget for this campaign budget. + + This field is read-only. + + This field is a member of `oneof`_ ``_has_recommended_budget``. + recommended_budget_amount_micros (int): + Output only. The recommended budget amount. + If no recommendation is available, this will be + set to the budget amount. Amount is specified in + micros, where one million is equivalent to one + currency unit. + + This field is read-only. + + This field is a member of `oneof`_ ``_recommended_budget_amount_micros``. + period (google.ads.googleads.v24.enums.types.BudgetPeriodEnum.BudgetPeriod): + Immutable. Period over which to spend the + budget. Defaults to DAILY if not specified. + recommended_budget_estimated_change_weekly_clicks (int): + Output only. The estimated change in weekly + clicks if the recommended budget is applied. + + This field is read-only. + + This field is a member of `oneof`_ ``_recommended_budget_estimated_change_weekly_clicks``. + recommended_budget_estimated_change_weekly_cost_micros (int): + Output only. The estimated change in weekly + cost in micros if the recommended budget is + applied. One million is equivalent to one + currency unit. + + This field is read-only. + + This field is a member of `oneof`_ ``_recommended_budget_estimated_change_weekly_cost_micros``. + recommended_budget_estimated_change_weekly_interactions (int): + Output only. The estimated change in weekly + interactions if the recommended budget is + applied. + + This field is read-only. + + This field is a member of `oneof`_ ``_recommended_budget_estimated_change_weekly_interactions``. + recommended_budget_estimated_change_weekly_views (int): + Output only. The estimated change in weekly + views if the recommended budget is applied. + + This field is read-only. + + This field is a member of `oneof`_ ``_recommended_budget_estimated_change_weekly_views``. + type_ (google.ads.googleads.v24.enums.types.BudgetTypeEnum.BudgetType): + Immutable. The type of the campaign budget. + aligned_bidding_strategy_id (int): + ID of the portfolio bidding strategy that + this shared campaign budget is aligned with. + When a bidding strategy and a campaign budget + are aligned, they are attached to the same set + of campaigns. After a campaign budget is aligned + with a bidding strategy, campaigns that are + added to the campaign budget must also use the + aligned bidding strategy. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=19, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=20, + optional=True, + ) + amount_micros: int = proto.Field( + proto.INT64, + number=21, + optional=True, + ) + total_amount_micros: int = proto.Field( + proto.INT64, + number=22, + optional=True, + ) + status: budget_status.BudgetStatusEnum.BudgetStatus = proto.Field( + proto.ENUM, + number=6, + enum=budget_status.BudgetStatusEnum.BudgetStatus, + ) + delivery_method: ( + budget_delivery_method.BudgetDeliveryMethodEnum.BudgetDeliveryMethod + ) = proto.Field( + proto.ENUM, + number=7, + enum=budget_delivery_method.BudgetDeliveryMethodEnum.BudgetDeliveryMethod, + ) + explicitly_shared: bool = proto.Field( + proto.BOOL, + number=23, + optional=True, + ) + reference_count: int = proto.Field( + proto.INT64, + number=24, + optional=True, + ) + has_recommended_budget: bool = proto.Field( + proto.BOOL, + number=25, + optional=True, + ) + recommended_budget_amount_micros: int = proto.Field( + proto.INT64, + number=26, + optional=True, + ) + period: budget_period.BudgetPeriodEnum.BudgetPeriod = proto.Field( + proto.ENUM, + number=13, + enum=budget_period.BudgetPeriodEnum.BudgetPeriod, + ) + recommended_budget_estimated_change_weekly_clicks: int = proto.Field( + proto.INT64, + number=27, + optional=True, + ) + recommended_budget_estimated_change_weekly_cost_micros: int = proto.Field( + proto.INT64, + number=28, + optional=True, + ) + recommended_budget_estimated_change_weekly_interactions: int = proto.Field( + proto.INT64, + number=29, + optional=True, + ) + recommended_budget_estimated_change_weekly_views: int = proto.Field( + proto.INT64, + number=30, + optional=True, + ) + type_: budget_type.BudgetTypeEnum.BudgetType = proto.Field( + proto.ENUM, + number=18, + enum=budget_type.BudgetTypeEnum.BudgetType, + ) + aligned_bidding_strategy_id: int = proto.Field( + proto.INT64, + number=31, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_conversion_goal.py b/google/ads/googleads/v24/resources/types/campaign_conversion_goal.py new file mode 100644 index 000000000..82fa4d0e0 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_conversion_goal.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import conversion_action_category +from google.ads.googleads.v24.enums.types import conversion_origin + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignConversionGoal", + }, +) + + +class CampaignConversionGoal(proto.Message): + r"""The biddability setting for the specified campaign only for + all conversion actions with a matching category and origin. + + Attributes: + resource_name (str): + Immutable. The resource name of the campaign conversion + goal. Campaign conversion goal resource names have the form: + + ``customers/{customer_id}/campaignConversionGoals/{campaign_id}~{category}~{origin}`` + campaign (str): + Immutable. The campaign with which this + campaign conversion goal is associated. + category (google.ads.googleads.v24.enums.types.ConversionActionCategoryEnum.ConversionActionCategory): + The conversion category of this campaign + conversion goal. + origin (google.ads.googleads.v24.enums.types.ConversionOriginEnum.ConversionOrigin): + The conversion origin of this campaign + conversion goal. + biddable (bool): + The biddability of the campaign conversion + goal. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=2, + ) + category: ( + conversion_action_category.ConversionActionCategoryEnum.ConversionActionCategory + ) = proto.Field( + proto.ENUM, + number=3, + enum=conversion_action_category.ConversionActionCategoryEnum.ConversionActionCategory, + ) + origin: conversion_origin.ConversionOriginEnum.ConversionOrigin = ( + proto.Field( + proto.ENUM, + number=4, + enum=conversion_origin.ConversionOriginEnum.ConversionOrigin, + ) + ) + biddable: bool = proto.Field( + proto.BOOL, + number=5, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_criterion.py b/google/ads/googleads/v24/resources/types/campaign_criterion.py new file mode 100644 index 000000000..d80c446ab --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_criterion.py @@ -0,0 +1,490 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.enums.types import campaign_criterion_status +from google.ads.googleads.v24.enums.types import criterion_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignCriterion", + }, +) + + +class CampaignCriterion(proto.Message): + r"""A campaign criterion. + + 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: + resource_name (str): + Immutable. The resource name of the campaign criterion. + Campaign criterion resource names have the form: + + ``customers/{customer_id}/campaignCriteria/{campaign_id}~{criterion_id}`` + campaign (str): + Immutable. The campaign to which the + criterion belongs. + + This field is a member of `oneof`_ ``_campaign``. + criterion_id (int): + Output only. The ID of the criterion. + + This field is ignored during mutate. + + This field is a member of `oneof`_ ``_criterion_id``. + display_name (str): + Output only. The display name of the + criterion. + This field is ignored for mutates. + bid_modifier (float): + The modifier for the bids when the criterion + matches. The modifier must be in the range: 0.1 + - 10.0. Most targetable criteria types support + modifiers. Use 0 to opt out of a Device type. + + This field is a member of `oneof`_ ``_bid_modifier``. + negative (bool): + Immutable. Whether to target (``false``) or exclude + (``true``) the criterion. + + This field is a member of `oneof`_ ``_negative``. + type_ (google.ads.googleads.v24.enums.types.CriterionTypeEnum.CriterionType): + Output only. The type of the criterion. + status (google.ads.googleads.v24.enums.types.CampaignCriterionStatusEnum.CampaignCriterionStatus): + The status of the criterion. + keyword (google.ads.googleads.v24.common.types.KeywordInfo): + Immutable. Keyword. + + This field is a member of `oneof`_ ``criterion``. + placement (google.ads.googleads.v24.common.types.PlacementInfo): + Immutable. Placement. + + This field is a member of `oneof`_ ``criterion``. + mobile_app_category (google.ads.googleads.v24.common.types.MobileAppCategoryInfo): + Immutable. Mobile app category. + + This field is a member of `oneof`_ ``criterion``. + mobile_application (google.ads.googleads.v24.common.types.MobileApplicationInfo): + Immutable. Mobile application. + + This field is a member of `oneof`_ ``criterion``. + location (google.ads.googleads.v24.common.types.LocationInfo): + Immutable. Location. + + This field is a member of `oneof`_ ``criterion``. + device (google.ads.googleads.v24.common.types.DeviceInfo): + Immutable. Device. + + This field is a member of `oneof`_ ``criterion``. + ad_schedule (google.ads.googleads.v24.common.types.AdScheduleInfo): + Immutable. Ad Schedule. + + This field is a member of `oneof`_ ``criterion``. + age_range (google.ads.googleads.v24.common.types.AgeRangeInfo): + Immutable. Age range. + + This field is a member of `oneof`_ ``criterion``. + gender (google.ads.googleads.v24.common.types.GenderInfo): + Immutable. Gender. + + This field is a member of `oneof`_ ``criterion``. + income_range (google.ads.googleads.v24.common.types.IncomeRangeInfo): + Immutable. Income range. + + This field is a member of `oneof`_ ``criterion``. + parental_status (google.ads.googleads.v24.common.types.ParentalStatusInfo): + Immutable. Parental status. + + This field is a member of `oneof`_ ``criterion``. + user_list (google.ads.googleads.v24.common.types.UserListInfo): + Immutable. User List. + + This field is a member of `oneof`_ ``criterion``. + youtube_video (google.ads.googleads.v24.common.types.YouTubeVideoInfo): + Immutable. YouTube Video. + + This field is a member of `oneof`_ ``criterion``. + youtube_channel (google.ads.googleads.v24.common.types.YouTubeChannelInfo): + Immutable. YouTube Channel. + + This field is a member of `oneof`_ ``criterion``. + proximity (google.ads.googleads.v24.common.types.ProximityInfo): + Immutable. Proximity. + + This field is a member of `oneof`_ ``criterion``. + topic (google.ads.googleads.v24.common.types.TopicInfo): + Immutable. Topic. + + This field is a member of `oneof`_ ``criterion``. + listing_scope (google.ads.googleads.v24.common.types.ListingScopeInfo): + Immutable. Listing scope. + + This field is a member of `oneof`_ ``criterion``. + language (google.ads.googleads.v24.common.types.LanguageInfo): + Immutable. Language. + + This field is a member of `oneof`_ ``criterion``. + ip_block (google.ads.googleads.v24.common.types.IpBlockInfo): + Immutable. IpBlock. + + You can exclude up to 500 IP addresses per + campaign. + + This field is a member of `oneof`_ ``criterion``. + content_label (google.ads.googleads.v24.common.types.ContentLabelInfo): + Immutable. ContentLabel. + + This field is a member of `oneof`_ ``criterion``. + carrier (google.ads.googleads.v24.common.types.CarrierInfo): + Immutable. Carrier. + + This field is a member of `oneof`_ ``criterion``. + user_interest (google.ads.googleads.v24.common.types.UserInterestInfo): + Immutable. User Interest. + + This field is a member of `oneof`_ ``criterion``. + webpage (google.ads.googleads.v24.common.types.WebpageInfo): + Immutable. Webpage. + + This field is a member of `oneof`_ ``criterion``. + operating_system_version (google.ads.googleads.v24.common.types.OperatingSystemVersionInfo): + Immutable. Operating system version. + + This field is a member of `oneof`_ ``criterion``. + mobile_device (google.ads.googleads.v24.common.types.MobileDeviceInfo): + Immutable. Mobile Device. + + This field is a member of `oneof`_ ``criterion``. + location_group (google.ads.googleads.v24.common.types.LocationGroupInfo): + Immutable. Location Group + + This field is a member of `oneof`_ ``criterion``. + custom_affinity (google.ads.googleads.v24.common.types.CustomAffinityInfo): + Immutable. Custom Affinity. + + This field is a member of `oneof`_ ``criterion``. + custom_audience (google.ads.googleads.v24.common.types.CustomAudienceInfo): + Immutable. Custom Audience + + This field is a member of `oneof`_ ``criterion``. + combined_audience (google.ads.googleads.v24.common.types.CombinedAudienceInfo): + Immutable. Combined Audience. + + This field is a member of `oneof`_ ``criterion``. + keyword_theme (google.ads.googleads.v24.common.types.KeywordThemeInfo): + Immutable. Smart Campaign Keyword Theme. + + This field is a member of `oneof`_ ``criterion``. + local_service_id (google.ads.googleads.v24.common.types.LocalServiceIdInfo): + Immutable. GLS service campaign criterion. + + This field is a member of `oneof`_ ``criterion``. + brand_list (google.ads.googleads.v24.common.types.BrandListInfo): + Immutable. Brand list campaign criterion. + + This field is a member of `oneof`_ ``criterion``. + life_event (google.ads.googleads.v24.common.types.LifeEventInfo): + Immutable. Life event campaign criterion. + + This field is a member of `oneof`_ ``criterion``. + webpage_list (google.ads.googleads.v24.common.types.WebpageListInfo): + Immutable. Webpage list. + This criterion is not publicly available. + + This field is a member of `oneof`_ ``criterion``. + video_lineup (google.ads.googleads.v24.common.types.VideoLineupInfo): + Immutable. Video lineup criterion. + + This field is a member of `oneof`_ ``criterion``. + extended_demographic (google.ads.googleads.v24.common.types.ExtendedDemographicInfo): + Immutable. Extended demographic criterion. + + This field is a member of `oneof`_ ``criterion``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=37, + optional=True, + ) + criterion_id: int = proto.Field( + proto.INT64, + number=38, + optional=True, + ) + display_name: str = proto.Field( + proto.STRING, + number=43, + ) + bid_modifier: float = proto.Field( + proto.FLOAT, + number=39, + optional=True, + ) + negative: bool = proto.Field( + proto.BOOL, + number=40, + optional=True, + ) + type_: criterion_type.CriterionTypeEnum.CriterionType = proto.Field( + proto.ENUM, + number=6, + enum=criterion_type.CriterionTypeEnum.CriterionType, + ) + status: ( + campaign_criterion_status.CampaignCriterionStatusEnum.CampaignCriterionStatus + ) = proto.Field( + proto.ENUM, + number=35, + enum=campaign_criterion_status.CampaignCriterionStatusEnum.CampaignCriterionStatus, + ) + keyword: criteria.KeywordInfo = proto.Field( + proto.MESSAGE, + number=8, + oneof="criterion", + message=criteria.KeywordInfo, + ) + placement: criteria.PlacementInfo = proto.Field( + proto.MESSAGE, + number=9, + oneof="criterion", + message=criteria.PlacementInfo, + ) + mobile_app_category: criteria.MobileAppCategoryInfo = proto.Field( + proto.MESSAGE, + number=10, + oneof="criterion", + message=criteria.MobileAppCategoryInfo, + ) + mobile_application: criteria.MobileApplicationInfo = proto.Field( + proto.MESSAGE, + number=11, + oneof="criterion", + message=criteria.MobileApplicationInfo, + ) + location: criteria.LocationInfo = proto.Field( + proto.MESSAGE, + number=12, + oneof="criterion", + message=criteria.LocationInfo, + ) + device: criteria.DeviceInfo = proto.Field( + proto.MESSAGE, + number=13, + oneof="criterion", + message=criteria.DeviceInfo, + ) + ad_schedule: criteria.AdScheduleInfo = proto.Field( + proto.MESSAGE, + number=15, + oneof="criterion", + message=criteria.AdScheduleInfo, + ) + age_range: criteria.AgeRangeInfo = proto.Field( + proto.MESSAGE, + number=16, + oneof="criterion", + message=criteria.AgeRangeInfo, + ) + gender: criteria.GenderInfo = proto.Field( + proto.MESSAGE, + number=17, + oneof="criterion", + message=criteria.GenderInfo, + ) + income_range: criteria.IncomeRangeInfo = proto.Field( + proto.MESSAGE, + number=18, + oneof="criterion", + message=criteria.IncomeRangeInfo, + ) + parental_status: criteria.ParentalStatusInfo = proto.Field( + proto.MESSAGE, + number=19, + oneof="criterion", + message=criteria.ParentalStatusInfo, + ) + user_list: criteria.UserListInfo = proto.Field( + proto.MESSAGE, + number=22, + oneof="criterion", + message=criteria.UserListInfo, + ) + youtube_video: criteria.YouTubeVideoInfo = proto.Field( + proto.MESSAGE, + number=20, + oneof="criterion", + message=criteria.YouTubeVideoInfo, + ) + youtube_channel: criteria.YouTubeChannelInfo = proto.Field( + proto.MESSAGE, + number=21, + oneof="criterion", + message=criteria.YouTubeChannelInfo, + ) + proximity: criteria.ProximityInfo = proto.Field( + proto.MESSAGE, + number=23, + oneof="criterion", + message=criteria.ProximityInfo, + ) + topic: criteria.TopicInfo = proto.Field( + proto.MESSAGE, + number=24, + oneof="criterion", + message=criteria.TopicInfo, + ) + listing_scope: criteria.ListingScopeInfo = proto.Field( + proto.MESSAGE, + number=25, + oneof="criterion", + message=criteria.ListingScopeInfo, + ) + language: criteria.LanguageInfo = proto.Field( + proto.MESSAGE, + number=26, + oneof="criterion", + message=criteria.LanguageInfo, + ) + ip_block: criteria.IpBlockInfo = proto.Field( + proto.MESSAGE, + number=27, + oneof="criterion", + message=criteria.IpBlockInfo, + ) + content_label: criteria.ContentLabelInfo = proto.Field( + proto.MESSAGE, + number=28, + oneof="criterion", + message=criteria.ContentLabelInfo, + ) + carrier: criteria.CarrierInfo = proto.Field( + proto.MESSAGE, + number=29, + oneof="criterion", + message=criteria.CarrierInfo, + ) + user_interest: criteria.UserInterestInfo = proto.Field( + proto.MESSAGE, + number=30, + oneof="criterion", + message=criteria.UserInterestInfo, + ) + webpage: criteria.WebpageInfo = proto.Field( + proto.MESSAGE, + number=31, + oneof="criterion", + message=criteria.WebpageInfo, + ) + operating_system_version: criteria.OperatingSystemVersionInfo = proto.Field( + proto.MESSAGE, + number=32, + oneof="criterion", + message=criteria.OperatingSystemVersionInfo, + ) + mobile_device: criteria.MobileDeviceInfo = proto.Field( + proto.MESSAGE, + number=33, + oneof="criterion", + message=criteria.MobileDeviceInfo, + ) + location_group: criteria.LocationGroupInfo = proto.Field( + proto.MESSAGE, + number=34, + oneof="criterion", + message=criteria.LocationGroupInfo, + ) + custom_affinity: criteria.CustomAffinityInfo = proto.Field( + proto.MESSAGE, + number=36, + oneof="criterion", + message=criteria.CustomAffinityInfo, + ) + custom_audience: criteria.CustomAudienceInfo = proto.Field( + proto.MESSAGE, + number=41, + oneof="criterion", + message=criteria.CustomAudienceInfo, + ) + combined_audience: criteria.CombinedAudienceInfo = proto.Field( + proto.MESSAGE, + number=42, + oneof="criterion", + message=criteria.CombinedAudienceInfo, + ) + keyword_theme: criteria.KeywordThemeInfo = proto.Field( + proto.MESSAGE, + number=45, + oneof="criterion", + message=criteria.KeywordThemeInfo, + ) + local_service_id: criteria.LocalServiceIdInfo = proto.Field( + proto.MESSAGE, + number=46, + oneof="criterion", + message=criteria.LocalServiceIdInfo, + ) + brand_list: criteria.BrandListInfo = proto.Field( + proto.MESSAGE, + number=47, + oneof="criterion", + message=criteria.BrandListInfo, + ) + life_event: criteria.LifeEventInfo = proto.Field( + proto.MESSAGE, + number=48, + oneof="criterion", + message=criteria.LifeEventInfo, + ) + webpage_list: criteria.WebpageListInfo = proto.Field( + proto.MESSAGE, + number=49, + oneof="criterion", + message=criteria.WebpageListInfo, + ) + video_lineup: criteria.VideoLineupInfo = proto.Field( + proto.MESSAGE, + number=50, + oneof="criterion", + message=criteria.VideoLineupInfo, + ) + extended_demographic: criteria.ExtendedDemographicInfo = proto.Field( + proto.MESSAGE, + number=52, + oneof="criterion", + message=criteria.ExtendedDemographicInfo, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_customizer.py b/google/ads/googleads/v24/resources/types/campaign_customizer.py new file mode 100644 index 000000000..b43ecae21 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_customizer.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import customizer_value +from google.ads.googleads.v24.enums.types import customizer_value_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignCustomizer", + }, +) + + +class CampaignCustomizer(proto.Message): + r"""A customizer value for the associated CustomizerAttribute at + the Campaign level. + + Attributes: + resource_name (str): + Immutable. The resource name of the campaign customizer. + Campaign customizer resource names have the form: + + ``customers/{customer_id}/campaignCustomizers/{campaign_id}~{customizer_attribute_id}`` + campaign (str): + Immutable. The campaign to which the + customizer attribute is linked. + customizer_attribute (str): + Required. Immutable. The customizer attribute + which is linked to the campaign. + status (google.ads.googleads.v24.enums.types.CustomizerValueStatusEnum.CustomizerValueStatus): + Output only. The status of the campaign + customizer. + value (google.ads.googleads.v24.common.types.CustomizerValue): + Required. The value to associate with the + customizer attribute at this level. The value + must be of the type specified for the + CustomizerAttribute. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=2, + ) + customizer_attribute: str = proto.Field( + proto.STRING, + number=3, + ) + status: ( + customizer_value_status.CustomizerValueStatusEnum.CustomizerValueStatus + ) = proto.Field( + proto.ENUM, + number=4, + enum=customizer_value_status.CustomizerValueStatusEnum.CustomizerValueStatus, + ) + value: customizer_value.CustomizerValue = proto.Field( + proto.MESSAGE, + number=5, + message=customizer_value.CustomizerValue, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_draft.py b/google/ads/googleads/v24/resources/types/campaign_draft.py new file mode 100644 index 000000000..fe3c46811 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_draft.py @@ -0,0 +1,137 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import campaign_draft_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignDraft", + }, +) + + +class CampaignDraft(proto.Message): + r"""A campaign draft. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the campaign draft. Campaign + draft resource names have the form: + + ``customers/{customer_id}/campaignDrafts/{base_campaign_id}~{draft_id}`` + draft_id (int): + Output only. The ID of the draft. + + This field is read-only. + + This field is a member of `oneof`_ ``_draft_id``. + base_campaign (str): + Immutable. The base campaign to which the + draft belongs. + + This field is a member of `oneof`_ ``_base_campaign``. + name (str): + The name of the campaign draft. + + This field is required and should not be empty + when creating new campaign drafts. + + It must not contain any null (code point 0x0), + NL line feed (code point 0xA) or carriage return + (code point 0xD) characters. + + This field is a member of `oneof`_ ``_name``. + draft_campaign (str): + Output only. Resource name of the Campaign + that results from overlaying the draft changes + onto the base campaign. + + This field is read-only. + + This field is a member of `oneof`_ ``_draft_campaign``. + status (google.ads.googleads.v24.enums.types.CampaignDraftStatusEnum.CampaignDraftStatus): + Output only. The status of the campaign + draft. This field is read-only. + When a new campaign draft is added, the status + defaults to PROPOSED. + has_experiment_running (bool): + Output only. Whether there is an experiment + based on this draft currently serving. + + This field is a member of `oneof`_ ``_has_experiment_running``. + long_running_operation (str): + Output only. The resource name of the + long-running operation that can be used to poll + for completion of draft promotion. This is only + set if the draft promotion is in progress or + finished. + + This field is a member of `oneof`_ ``_long_running_operation``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + draft_id: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + base_campaign: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + draft_campaign: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + status: ( + campaign_draft_status.CampaignDraftStatusEnum.CampaignDraftStatus + ) = proto.Field( + proto.ENUM, + number=6, + enum=campaign_draft_status.CampaignDraftStatusEnum.CampaignDraftStatus, + ) + has_experiment_running: bool = proto.Field( + proto.BOOL, + number=13, + optional=True, + ) + long_running_operation: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_goal_config.py b/google/ads/googleads/v24/resources/types/campaign_goal_config.py new file mode 100644 index 000000000..2a3f852ab --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_goal_config.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import campaign_goal_settings +from google.ads.googleads.v24.enums.types import goal_type as gage_goal_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignGoalConfig", + }, +) + + +class CampaignGoalConfig(proto.Message): + r"""A link between a campaign and a goal enabling + campaign-specific optimization. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the campaign goal config. + campaign goal config resource names have the form: + ``customers/{customer_id}/campaignGoalConfigs/{campaign_id}~{goal_id}`` + campaign (str): + Immutable. The resource name of the campaign + for this link. + goal (str): + Immutable. The resource name of the goal this + link is attached to. + goal_type (google.ads.googleads.v24.enums.types.GoalTypeEnum.GoalType): + Output only. The goal type this link is + attached to. + campaign_retention_settings (google.ads.googleads.v24.common.types.CampaignGoalSettings.CampaignRetentionGoalSettings): + Retention goal campaign settings. + + This field is a member of `oneof`_ ``campaign_goal_config_settings``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=2, + ) + goal: str = proto.Field( + proto.STRING, + number=3, + ) + goal_type: gage_goal_type.GoalTypeEnum.GoalType = proto.Field( + proto.ENUM, + number=4, + enum=gage_goal_type.GoalTypeEnum.GoalType, + ) + campaign_retention_settings: ( + campaign_goal_settings.CampaignGoalSettings.CampaignRetentionGoalSettings + ) = proto.Field( + proto.MESSAGE, + number=5, + oneof="campaign_goal_config_settings", + message=campaign_goal_settings.CampaignGoalSettings.CampaignRetentionGoalSettings, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_group.py b/google/ads/googleads/v24/resources/types/campaign_group.py new file mode 100644 index 000000000..c12fde1e0 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_group.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import campaign_group_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignGroup", + }, +) + + +class CampaignGroup(proto.Message): + r"""A campaign group. + + Attributes: + resource_name (str): + Immutable. The resource name of the campaign group. Campaign + group resource names have the form: + + ``customers/{customer_id}/campaignGroups/{campaign_group_id}`` + id (int): + Output only. The ID of the campaign group. + name (str): + The name of the campaign group. + + This field is required and should not be empty + when creating new campaign groups. + + It must not contain any null (code point 0x0), + NL line feed (code point 0xA) or carriage return + (code point 0xD) characters. + status (google.ads.googleads.v24.enums.types.CampaignGroupStatusEnum.CampaignGroupStatus): + The status of the campaign group. + + When a new campaign group is added, the status + defaults to ENABLED. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=3, + ) + name: str = proto.Field( + proto.STRING, + number=4, + ) + status: ( + campaign_group_status.CampaignGroupStatusEnum.CampaignGroupStatus + ) = proto.Field( + proto.ENUM, + number=5, + enum=campaign_group_status.CampaignGroupStatusEnum.CampaignGroupStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_label.py b/google/ads/googleads/v24/resources/types/campaign_label.py new file mode 100644 index 000000000..d0dac67d0 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_label.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignLabel", + }, +) + + +class CampaignLabel(proto.Message): + r"""Represents a relationship between a campaign and a label. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. Name of the resource. Campaign label resource + names have the form: + ``customers/{customer_id}/campaignLabels/{campaign_id}~{label_id}`` + campaign (str): + Immutable. The campaign to which the label is + attached. + + This field is a member of `oneof`_ ``_campaign``. + label (str): + Immutable. The label assigned to the + campaign. + + This field is a member of `oneof`_ ``_label``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + label: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_lifecycle_goal.py b/google/ads/googleads/v24/resources/types/campaign_lifecycle_goal.py new file mode 100644 index 000000000..b06f1a9a1 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_lifecycle_goal.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import lifecycle_goals +from google.ads.googleads.v24.enums.types import ( + customer_acquisition_optimization_mode, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignLifecycleGoal", + "CustomerAcquisitionGoalSettings", + }, +) + + +class CampaignLifecycleGoal(proto.Message): + r"""Campaign level customer lifecycle goal settings. + + Attributes: + resource_name (str): + Immutable. The resource name of the customer lifecycle goal + of a campaign. + + ``customers/{customer_id}/campaignLifecycleGoal/{campaign_id}`` + campaign (str): + Output only. The campaign where the goal is + attached. + customer_acquisition_goal_settings (google.ads.googleads.v24.resources.types.CustomerAcquisitionGoalSettings): + Output only. The customer acquisition goal + settings for the campaign. The customer + acquisition goal is described in this article: + + https://support.google.com/google-ads/answer/12080169 + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=2, + ) + customer_acquisition_goal_settings: "CustomerAcquisitionGoalSettings" = ( + proto.Field( + proto.MESSAGE, + number=3, + message="CustomerAcquisitionGoalSettings", + ) + ) + + +class CustomerAcquisitionGoalSettings(proto.Message): + r"""The customer acquisition goal settings for the campaign. + + Attributes: + optimization_mode (google.ads.googleads.v24.enums.types.CustomerAcquisitionOptimizationModeEnum.CustomerAcquisitionOptimizationMode): + Output only. Customer acquisition + optimization mode of this campaign. + value_settings (google.ads.googleads.v24.common.types.LifecycleGoalValueSettings): + Output only. Campaign specific values for the + customer acquisition goal. + """ + + optimization_mode: ( + customer_acquisition_optimization_mode.CustomerAcquisitionOptimizationModeEnum.CustomerAcquisitionOptimizationMode + ) = proto.Field( + proto.ENUM, + number=1, + enum=customer_acquisition_optimization_mode.CustomerAcquisitionOptimizationModeEnum.CustomerAcquisitionOptimizationMode, + ) + value_settings: lifecycle_goals.LifecycleGoalValueSettings = proto.Field( + proto.MESSAGE, + number=2, + message=lifecycle_goals.LifecycleGoalValueSettings, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_search_term_insight.py b/google/ads/googleads/v24/resources/types/campaign_search_term_insight.py new file mode 100644 index 000000000..94b65edbc --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_search_term_insight.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignSearchTermInsight", + }, +) + + +class CampaignSearchTermInsight(proto.Message): + r"""This report provides a high-level view of search demand at + the campaign level by grouping similar search terms into + categories and showing their search volume. + Historical data is available starting March 2023. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the campaign level search + term insight. Campaign level search term insight resource + names have the form: + + ``customers/{customer_id}/campaignSearchTermInsights/{campaign_id}~{category_id}`` + category_label (str): + Output only. The label for the search + category. An empty string denotes the catch-all + category for search terms that didn't fit into + another category. + + This field is a member of `oneof`_ ``_category_label``. + id (int): + Output only. The ID of the insight. + + This field is a member of `oneof`_ ``_id``. + campaign_id (int): + Output only. The ID of the campaign. + + This field is a member of `oneof`_ ``_campaign_id``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + category_label: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + id: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + campaign_id: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_search_term_view.py b/google/ads/googleads/v24/resources/types/campaign_search_term_view.py new file mode 100644 index 000000000..4f018c6f3 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_search_term_view.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignSearchTermView", + }, +) + + +class CampaignSearchTermView(proto.Message): + r"""This report provides granular performance data, including + cost metrics, for each individual search term that triggered + your ads. If keyword-related segments are used, Performance Max + data will be excluded from the results. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the campaign search term + view. Campaign search term view resource names have the + form: + + ``customers/{customer_id}/campaignSearchTermViews/{campaign_id}~{URL-base64_search_term}`` + search_term (str): + Output only. The search term. + + This field is a member of `oneof`_ ``_search_term``. + campaign (str): + Output only. The campaign the search term + served in. + + This field is a member of `oneof`_ ``_campaign``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + search_term: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + campaign: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_shared_set.py b/google/ads/googleads/v24/resources/types/campaign_shared_set.py new file mode 100644 index 000000000..84570da33 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_shared_set.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import campaign_shared_set_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignSharedSet", + }, +) + + +class CampaignSharedSet(proto.Message): + r"""CampaignSharedSets are used for managing the shared sets + associated with a campaign. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the campaign shared set. + Campaign shared set resource names have the form: + + ``customers/{customer_id}/campaignSharedSets/{campaign_id}~{shared_set_id}`` + campaign (str): + Immutable. The campaign to which the campaign + shared set belongs. + + This field is a member of `oneof`_ ``_campaign``. + shared_set (str): + Immutable. The shared set associated with the + campaign. This may be a negative keyword shared + set of another customer. This customer should be + a manager of the other customer, otherwise the + campaign shared set will exist but have no + serving effect. Only negative keyword shared + sets can be associated with Shopping campaigns. + Only negative placement shared sets can be + associated with Display mobile app campaigns. + + This field is a member of `oneof`_ ``_shared_set``. + status (google.ads.googleads.v24.enums.types.CampaignSharedSetStatusEnum.CampaignSharedSetStatus): + Output only. The status of this campaign + shared set. Read only. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + shared_set: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + status: ( + campaign_shared_set_status.CampaignSharedSetStatusEnum.CampaignSharedSetStatus + ) = proto.Field( + proto.ENUM, + number=2, + enum=campaign_shared_set_status.CampaignSharedSetStatusEnum.CampaignSharedSetStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/campaign_simulation.py b/google/ads/googleads/v24/resources/types/campaign_simulation.py new file mode 100644 index 000000000..13f94f28c --- /dev/null +++ b/google/ads/googleads/v24/resources/types/campaign_simulation.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import simulation +from google.ads.googleads.v24.enums.types import simulation_modification_method +from google.ads.googleads.v24.enums.types import simulation_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CampaignSimulation", + }, +) + + +class CampaignSimulation(proto.Message): + r"""A campaign simulation. Supported combinations of advertising channel + type, simulation type and simulation modification method is detailed + below respectively. + + - SEARCH - CPC_BID - UNIFORM + - SEARCH - CPC_BID - SCALING + - SEARCH - TARGET_CPA - UNIFORM + - SEARCH - TARGET_CPA - SCALING + - SEARCH - TARGET_ROAS - UNIFORM + - SEARCH - TARGET_IMPRESSION_SHARE - UNIFORM + - SEARCH - BUDGET - UNIFORM + - SHOPPING - BUDGET - UNIFORM + - SHOPPING - TARGET_ROAS - UNIFORM + - MULTI_CHANNEL - TARGET_CPA - UNIFORM + - MULTI_CHANNEL - TARGET_ROAS - UNIFORM + - DEMAND_GEN - TARGET_CPA - DEFAULT + - DISPLAY - TARGET_CPA - UNIFORM + - PERFORMANCE_MAX - TARGET_CPA - UNIFORM + - PERFORMANCE_MAX - TARGET_ROAS - UNIFORM + - PERFORMANCE_MAX - BUDGET - UNIFORM + + 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: + resource_name (str): + Output only. The resource name of the campaign simulation. + Campaign simulation resource names have the form: + + ``customers/{customer_id}/campaignSimulations/{campaign_id}~{type}~{modification_method}~{start_date}~{end_date}`` + campaign_id (int): + Output only. Campaign id of the simulation. + type_ (google.ads.googleads.v24.enums.types.SimulationTypeEnum.SimulationType): + Output only. The field that the simulation + modifies. + modification_method (google.ads.googleads.v24.enums.types.SimulationModificationMethodEnum.SimulationModificationMethod): + Output only. How the simulation modifies the + field. + start_date (str): + Output only. First day on which the + simulation is based, in YYYY-MM-DD format. + end_date (str): + Output only. Last day on which the simulation + is based, in YYYY-MM-DD format + cpc_bid_point_list (google.ads.googleads.v24.common.types.CpcBidSimulationPointList): + Output only. Simulation points if the simulation type is + CPC_BID. + + This field is a member of `oneof`_ ``point_list``. + target_cpa_point_list (google.ads.googleads.v24.common.types.TargetCpaSimulationPointList): + Output only. Simulation points if the simulation type is + TARGET_CPA. + + This field is a member of `oneof`_ ``point_list``. + target_roas_point_list (google.ads.googleads.v24.common.types.TargetRoasSimulationPointList): + Output only. Simulation points if the simulation type is + TARGET_ROAS. + + This field is a member of `oneof`_ ``point_list``. + target_impression_share_point_list (google.ads.googleads.v24.common.types.TargetImpressionShareSimulationPointList): + Output only. Simulation points if the simulation type is + TARGET_IMPRESSION_SHARE. + + This field is a member of `oneof`_ ``point_list``. + budget_point_list (google.ads.googleads.v24.common.types.BudgetSimulationPointList): + Output only. Simulation points if the + simulation type is BUDGET. + + This field is a member of `oneof`_ ``point_list``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_id: int = proto.Field( + proto.INT64, + number=2, + ) + type_: simulation_type.SimulationTypeEnum.SimulationType = proto.Field( + proto.ENUM, + number=3, + enum=simulation_type.SimulationTypeEnum.SimulationType, + ) + modification_method: ( + simulation_modification_method.SimulationModificationMethodEnum.SimulationModificationMethod + ) = proto.Field( + proto.ENUM, + number=4, + enum=simulation_modification_method.SimulationModificationMethodEnum.SimulationModificationMethod, + ) + start_date: str = proto.Field( + proto.STRING, + number=5, + ) + end_date: str = proto.Field( + proto.STRING, + number=6, + ) + cpc_bid_point_list: simulation.CpcBidSimulationPointList = proto.Field( + proto.MESSAGE, + number=7, + oneof="point_list", + message=simulation.CpcBidSimulationPointList, + ) + target_cpa_point_list: simulation.TargetCpaSimulationPointList = ( + proto.Field( + proto.MESSAGE, + number=8, + oneof="point_list", + message=simulation.TargetCpaSimulationPointList, + ) + ) + target_roas_point_list: simulation.TargetRoasSimulationPointList = ( + proto.Field( + proto.MESSAGE, + number=9, + oneof="point_list", + message=simulation.TargetRoasSimulationPointList, + ) + ) + target_impression_share_point_list: ( + simulation.TargetImpressionShareSimulationPointList + ) = proto.Field( + proto.MESSAGE, + number=10, + oneof="point_list", + message=simulation.TargetImpressionShareSimulationPointList, + ) + budget_point_list: simulation.BudgetSimulationPointList = proto.Field( + proto.MESSAGE, + number=11, + oneof="point_list", + message=simulation.BudgetSimulationPointList, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/carrier_constant.py b/google/ads/googleads/v24/resources/types/carrier_constant.py new file mode 100644 index 000000000..3641b399b --- /dev/null +++ b/google/ads/googleads/v24/resources/types/carrier_constant.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CarrierConstant", + }, +) + + +class CarrierConstant(proto.Message): + r"""A carrier criterion that can be used in campaign targeting. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the carrier criterion. + Carrier criterion resource names have the form: + + ``carrierConstants/{criterion_id}`` + id (int): + Output only. The ID of the carrier criterion. + + This field is a member of `oneof`_ ``_id``. + name (str): + Output only. The full name of the carrier in + English. + + This field is a member of `oneof`_ ``_name``. + country_code (str): + Output only. The country code of the country + where the carrier is located, for example, "AR", + "FR", etc. + + This field is a member of `oneof`_ ``_country_code``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + country_code: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/cart_data_sales_view.py b/google/ads/googleads/v24/resources/types/cart_data_sales_view.py new file mode 100644 index 000000000..d7a4bcfe1 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/cart_data_sales_view.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CartDataSalesView", + }, +) + + +class CartDataSalesView(proto.Message): + r"""Cart data sales view. + + Provides information about the products which were purchased if + conversions with cart data is implemented. Performance metrics + like revenue, gross profit, lead/cross-sell metrics etc. and + Merchant Center attributes such as brand, category etc. are + available for products defined in an inventory feed and sold as + a result of Google ads. For purchases attributed to clicks on + Shopping ads, dimensions of both clicked and sold products can + be viewed together. + + Attributes: + resource_name (str): + Output only. The resource name of the Cart data sales view. + Cart data sales view resource names have the form: + ``customers/{customer_id}/cartDataSalesView`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/change_event.py b/google/ads/googleads/v24/resources/types/change_event.py new file mode 100644 index 000000000..fb1be4d51 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/change_event.py @@ -0,0 +1,315 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import change_client_type +from google.ads.googleads.v24.enums.types import change_event_resource_type +from google.ads.googleads.v24.enums.types import ( + resource_change_operation as gage_resource_change_operation, +) +from google.ads.googleads.v24.resources.types import ad as gagr_ad +from google.ads.googleads.v24.resources.types import ad_group as gagr_ad_group +from google.ads.googleads.v24.resources.types import ( + ad_group_ad as gagr_ad_group_ad, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_asset as gagr_ad_group_asset, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_bid_modifier as gagr_ad_group_bid_modifier, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_criterion as gagr_ad_group_criterion, +) +from google.ads.googleads.v24.resources.types import asset as gagr_asset +from google.ads.googleads.v24.resources.types import asset_set as gagr_asset_set +from google.ads.googleads.v24.resources.types import ( + asset_set_asset as gagr_asset_set_asset, +) +from google.ads.googleads.v24.resources.types import campaign as gagr_campaign +from google.ads.googleads.v24.resources.types import ( + campaign_asset as gagr_campaign_asset, +) +from google.ads.googleads.v24.resources.types import ( + campaign_asset_set as gagr_campaign_asset_set, +) +from google.ads.googleads.v24.resources.types import ( + campaign_budget as gagr_campaign_budget, +) +from google.ads.googleads.v24.resources.types import ( + campaign_criterion as gagr_campaign_criterion, +) +from google.ads.googleads.v24.resources.types import ( + customer_asset as gagr_customer_asset, +) +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ChangeEvent", + }, +) + + +class ChangeEvent(proto.Message): + r"""Describes the granular change of returned resources of + certain resource types. Changes made through the UI or API in + the past 30 days are included. Previous and new values of the + changed fields are shown. ChangeEvent could have up to 3 minutes + delay to reflect a new change. + + Attributes: + resource_name (str): + Output only. The resource name of the change event. Change + event resource names have the form: + + ``customers/{customer_id}/changeEvents/{timestamp_micros}~{command_index}~{mutate_index}`` + change_date_time (str): + Output only. Time at which the change was + committed on this resource. + change_resource_type (google.ads.googleads.v24.enums.types.ChangeEventResourceTypeEnum.ChangeEventResourceType): + Output only. The type of the changed resource. This dictates + what resource will be set in old_resource and new_resource. + change_resource_name (str): + Output only. The Simply resource this change + occurred on. + client_type (google.ads.googleads.v24.enums.types.ChangeClientTypeEnum.ChangeClientType): + Output only. Where the change was made + through. + user_email (str): + Output only. The email of the user who made + this change. + old_resource (google.ads.googleads.v24.resources.types.ChangeEvent.ChangedResource): + Output only. The old resource before the + change. Only changed fields will be populated. + new_resource (google.ads.googleads.v24.resources.types.ChangeEvent.ChangedResource): + Output only. The new resource after the + change. Only changed fields will be populated. + resource_change_operation (google.ads.googleads.v24.enums.types.ResourceChangeOperationEnum.ResourceChangeOperation): + Output only. The operation on the changed + resource. + changed_fields (google.protobuf.field_mask_pb2.FieldMask): + Output only. A list of fields that are + changed in the returned resource. + campaign (str): + Output only. The Campaign affected by this + change. + ad_group (str): + Output only. The AdGroup affected by this + change. + asset (str): + Output only. The Asset affected by this + change. + """ + + class ChangedResource(proto.Message): + r"""A wrapper proto presenting all supported resources. Only the + resource of the change_resource_type will be set. + + Attributes: + ad (google.ads.googleads.v24.resources.types.Ad): + Output only. Set if change_resource_type == AD. + ad_group (google.ads.googleads.v24.resources.types.AdGroup): + Output only. Set if change_resource_type == AD_GROUP. + ad_group_criterion (google.ads.googleads.v24.resources.types.AdGroupCriterion): + Output only. Set if change_resource_type == + AD_GROUP_CRITERION. + campaign (google.ads.googleads.v24.resources.types.Campaign): + Output only. Set if change_resource_type == CAMPAIGN. + campaign_budget (google.ads.googleads.v24.resources.types.CampaignBudget): + Output only. Set if change_resource_type == CAMPAIGN_BUDGET. + ad_group_bid_modifier (google.ads.googleads.v24.resources.types.AdGroupBidModifier): + Output only. Set if change_resource_type == + AD_GROUP_BID_MODIFIER. + campaign_criterion (google.ads.googleads.v24.resources.types.CampaignCriterion): + Output only. Set if change_resource_type == + CAMPAIGN_CRITERION. + ad_group_ad (google.ads.googleads.v24.resources.types.AdGroupAd): + Output only. Set if change_resource_type == AD_GROUP_AD. + asset (google.ads.googleads.v24.resources.types.Asset): + Output only. Set if change_resource_type == ASSET. + customer_asset (google.ads.googleads.v24.resources.types.CustomerAsset): + Output only. Set if change_resource_type == CUSTOMER_ASSET. + campaign_asset (google.ads.googleads.v24.resources.types.CampaignAsset): + Output only. Set if change_resource_type == CAMPAIGN_ASSET. + ad_group_asset (google.ads.googleads.v24.resources.types.AdGroupAsset): + Output only. Set if change_resource_type == AD_GROUP_ASSET. + asset_set (google.ads.googleads.v24.resources.types.AssetSet): + Output only. Set if change_resource_type == ASSET_SET. + asset_set_asset (google.ads.googleads.v24.resources.types.AssetSetAsset): + Output only. Set if change_resource_type == ASSET_SET_ASSET. + campaign_asset_set (google.ads.googleads.v24.resources.types.CampaignAssetSet): + Output only. Set if change_resource_type == + CAMPAIGN_ASSET_SET. + """ + + ad: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=1, + message=gagr_ad.Ad, + ) + ad_group: gagr_ad_group.AdGroup = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad_group.AdGroup, + ) + ad_group_criterion: gagr_ad_group_criterion.AdGroupCriterion = ( + proto.Field( + proto.MESSAGE, + number=3, + message=gagr_ad_group_criterion.AdGroupCriterion, + ) + ) + campaign: gagr_campaign.Campaign = proto.Field( + proto.MESSAGE, + number=4, + message=gagr_campaign.Campaign, + ) + campaign_budget: gagr_campaign_budget.CampaignBudget = proto.Field( + proto.MESSAGE, + number=5, + message=gagr_campaign_budget.CampaignBudget, + ) + ad_group_bid_modifier: gagr_ad_group_bid_modifier.AdGroupBidModifier = ( + proto.Field( + proto.MESSAGE, + number=6, + message=gagr_ad_group_bid_modifier.AdGroupBidModifier, + ) + ) + campaign_criterion: gagr_campaign_criterion.CampaignCriterion = ( + proto.Field( + proto.MESSAGE, + number=7, + message=gagr_campaign_criterion.CampaignCriterion, + ) + ) + ad_group_ad: gagr_ad_group_ad.AdGroupAd = proto.Field( + proto.MESSAGE, + number=12, + message=gagr_ad_group_ad.AdGroupAd, + ) + asset: gagr_asset.Asset = proto.Field( + proto.MESSAGE, + number=13, + message=gagr_asset.Asset, + ) + customer_asset: gagr_customer_asset.CustomerAsset = proto.Field( + proto.MESSAGE, + number=14, + message=gagr_customer_asset.CustomerAsset, + ) + campaign_asset: gagr_campaign_asset.CampaignAsset = proto.Field( + proto.MESSAGE, + number=15, + message=gagr_campaign_asset.CampaignAsset, + ) + ad_group_asset: gagr_ad_group_asset.AdGroupAsset = proto.Field( + proto.MESSAGE, + number=16, + message=gagr_ad_group_asset.AdGroupAsset, + ) + asset_set: gagr_asset_set.AssetSet = proto.Field( + proto.MESSAGE, + number=17, + message=gagr_asset_set.AssetSet, + ) + asset_set_asset: gagr_asset_set_asset.AssetSetAsset = proto.Field( + proto.MESSAGE, + number=18, + message=gagr_asset_set_asset.AssetSetAsset, + ) + campaign_asset_set: gagr_campaign_asset_set.CampaignAssetSet = ( + proto.Field( + proto.MESSAGE, + number=19, + message=gagr_campaign_asset_set.CampaignAssetSet, + ) + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + change_date_time: str = proto.Field( + proto.STRING, + number=2, + ) + change_resource_type: ( + change_event_resource_type.ChangeEventResourceTypeEnum.ChangeEventResourceType + ) = proto.Field( + proto.ENUM, + number=3, + enum=change_event_resource_type.ChangeEventResourceTypeEnum.ChangeEventResourceType, + ) + change_resource_name: str = proto.Field( + proto.STRING, + number=4, + ) + client_type: change_client_type.ChangeClientTypeEnum.ChangeClientType = ( + proto.Field( + proto.ENUM, + number=5, + enum=change_client_type.ChangeClientTypeEnum.ChangeClientType, + ) + ) + user_email: str = proto.Field( + proto.STRING, + number=6, + ) + old_resource: ChangedResource = proto.Field( + proto.MESSAGE, + number=7, + message=ChangedResource, + ) + new_resource: ChangedResource = proto.Field( + proto.MESSAGE, + number=8, + message=ChangedResource, + ) + resource_change_operation: ( + gage_resource_change_operation.ResourceChangeOperationEnum.ResourceChangeOperation + ) = proto.Field( + proto.ENUM, + number=9, + enum=gage_resource_change_operation.ResourceChangeOperationEnum.ResourceChangeOperation, + ) + changed_fields: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=10, + message=field_mask_pb2.FieldMask, + ) + campaign: str = proto.Field( + proto.STRING, + number=11, + ) + ad_group: str = proto.Field( + proto.STRING, + number=12, + ) + asset: str = proto.Field( + proto.STRING, + number=20, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/change_status.py b/google/ads/googleads/v24/resources/types/change_status.py new file mode 100644 index 000000000..de218f856 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/change_status.py @@ -0,0 +1,223 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import change_status_operation +from google.ads.googleads.v24.enums.types import change_status_resource_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ChangeStatus", + }, +) + + +class ChangeStatus(proto.Message): + r"""Describes the status of returned resource. ChangeStatus could + have up to 3 minutes delay to reflect a new change. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the change status. Change + status resource names have the form: + + ``customers/{customer_id}/changeStatus/{change_status_id}`` + last_change_date_time (str): + Output only. Time at which the most recent + change has occurred on this resource. + + This field is a member of `oneof`_ ``_last_change_date_time``. + resource_type (google.ads.googleads.v24.enums.types.ChangeStatusResourceTypeEnum.ChangeStatusResourceType): + Output only. Represents the type of the changed resource. + This dictates what fields will be set. For example, for + AD_GROUP, campaign and ad_group fields will be set. + campaign (str): + Output only. The Campaign affected by this + change. + + This field is a member of `oneof`_ ``_campaign``. + ad_group (str): + Output only. The AdGroup affected by this + change. + + This field is a member of `oneof`_ ``_ad_group``. + resource_status (google.ads.googleads.v24.enums.types.ChangeStatusOperationEnum.ChangeStatusOperation): + Output only. Represents the status of the + changed resource. + ad_group_ad (str): + Output only. The AdGroupAd affected by this + change. + + This field is a member of `oneof`_ ``_ad_group_ad``. + ad_group_criterion (str): + Output only. The AdGroupCriterion affected by + this change. + + This field is a member of `oneof`_ ``_ad_group_criterion``. + campaign_criterion (str): + Output only. The CampaignCriterion affected + by this change. + + This field is a member of `oneof`_ ``_campaign_criterion``. + ad_group_bid_modifier (str): + Output only. The AdGroupBidModifier affected + by this change. + + This field is a member of `oneof`_ ``_ad_group_bid_modifier``. + shared_set (str): + Output only. The SharedSet affected by this + change. + campaign_shared_set (str): + Output only. The CampaignSharedSet affected + by this change. + asset (str): + Output only. The Asset affected by this + change. + customer_asset (str): + Output only. The CustomerAsset affected by + this change. + campaign_asset (str): + Output only. The CampaignAsset affected by + this change. + ad_group_asset (str): + Output only. The AdGroupAsset affected by + this change. + combined_audience (str): + Output only. The CombinedAudience affected by + this change. + asset_group (str): + Output only. The AssetGroup affected by this + change. + asset_set (str): + Output only. The AssetSet affected by this + change. + campaign_budget (str): + Output only. The CampaignBudget affected by + this change. + campaign_asset_set (str): + Output only. The CampaignAssetSet affected by + this change. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + last_change_date_time: str = proto.Field( + proto.STRING, + number=24, + optional=True, + ) + resource_type: ( + change_status_resource_type.ChangeStatusResourceTypeEnum.ChangeStatusResourceType + ) = proto.Field( + proto.ENUM, + number=4, + enum=change_status_resource_type.ChangeStatusResourceTypeEnum.ChangeStatusResourceType, + ) + campaign: str = proto.Field( + proto.STRING, + number=17, + optional=True, + ) + ad_group: str = proto.Field( + proto.STRING, + number=18, + optional=True, + ) + resource_status: ( + change_status_operation.ChangeStatusOperationEnum.ChangeStatusOperation + ) = proto.Field( + proto.ENUM, + number=8, + enum=change_status_operation.ChangeStatusOperationEnum.ChangeStatusOperation, + ) + ad_group_ad: str = proto.Field( + proto.STRING, + number=25, + optional=True, + ) + ad_group_criterion: str = proto.Field( + proto.STRING, + number=26, + optional=True, + ) + campaign_criterion: str = proto.Field( + proto.STRING, + number=27, + optional=True, + ) + ad_group_bid_modifier: str = proto.Field( + proto.STRING, + number=32, + optional=True, + ) + shared_set: str = proto.Field( + proto.STRING, + number=33, + ) + campaign_shared_set: str = proto.Field( + proto.STRING, + number=34, + ) + asset: str = proto.Field( + proto.STRING, + number=35, + ) + customer_asset: str = proto.Field( + proto.STRING, + number=36, + ) + campaign_asset: str = proto.Field( + proto.STRING, + number=37, + ) + ad_group_asset: str = proto.Field( + proto.STRING, + number=38, + ) + combined_audience: str = proto.Field( + proto.STRING, + number=40, + ) + asset_group: str = proto.Field( + proto.STRING, + number=41, + ) + asset_set: str = proto.Field( + proto.STRING, + number=43, + ) + campaign_budget: str = proto.Field( + proto.STRING, + number=42, + ) + campaign_asset_set: str = proto.Field( + proto.STRING, + number=44, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/channel_aggregate_asset_view.py b/google/ads/googleads/v24/resources/types/channel_aggregate_asset_view.py new file mode 100644 index 000000000..fbf776edf --- /dev/null +++ b/google/ads/googleads/v24/resources/types/channel_aggregate_asset_view.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + advertising_channel_type as gage_advertising_channel_type, +) +from google.ads.googleads.v24.enums.types import asset_field_type +from google.ads.googleads.v24.enums.types import ( + asset_source as gage_asset_source, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ChannelAggregateAssetView", + }, +) + + +class ChannelAggregateAssetView(proto.Message): + r"""A channel-level aggregate asset view that shows where the + asset is linked, performamce of the asset and stats. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the channel aggregate + asset view. Channel aggregate asset view resource names have + the form: + + ``customers/{customer_id}/channelAggregateAssetViews/{ChannelAssetV2.advertising_channel_type}~{ChannelAssetV2.asset_id}~{ChannelAssetV2.asset_source}~{ChannelAssetV2.field_type}"`` + advertising_channel_type (google.ads.googleads.v24.enums.types.AdvertisingChannelTypeEnum.AdvertisingChannelType): + Output only. Channel in which the asset + served. + + This field is a member of `oneof`_ ``_advertising_channel_type``. + asset (str): + Output only. The ID of the asset. + + This field is a member of `oneof`_ ``_asset``. + asset_source (google.ads.googleads.v24.enums.types.AssetSourceEnum.AssetSource): + Output only. Source of the asset link. + + This field is a member of `oneof`_ ``_asset_source``. + field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + Output only. FieldType of the asset. + + This field is a member of `oneof`_ ``_field_type``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + advertising_channel_type: ( + gage_advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType + ) = proto.Field( + proto.ENUM, + number=2, + optional=True, + enum=gage_advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType, + ) + asset: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + asset_source: gage_asset_source.AssetSourceEnum.AssetSource = proto.Field( + proto.ENUM, + number=4, + optional=True, + enum=gage_asset_source.AssetSourceEnum.AssetSource, + ) + field_type: asset_field_type.AssetFieldTypeEnum.AssetFieldType = ( + proto.Field( + proto.ENUM, + number=5, + optional=True, + enum=asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/click_view.py b/google/ads/googleads/v24/resources/types/click_view.py new file mode 100644 index 000000000..0b6c3bc66 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/click_view.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import click_location +from google.ads.googleads.v24.common.types import criteria + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ClickView", + }, +) + + +class ClickView(proto.Message): + r"""A click view with metrics aggregated at each click level, + including both valid and invalid clicks. For non-Search + campaigns, metrics.clicks represents the number of valid and + invalid interactions. Queries including ClickView must have a + filter limiting the results to one day and can be requested for + dates back to 90 days before the time of the request. + + GCLIDs are not available in this report for App Campaigns for + Installs (ACi) and App Campaigns for Pre-registration (ACpre). + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the click view. Click view + resource names have the form: + + ``customers/{customer_id}/clickViews/{date (yyyy-MM-dd)}~{gclid}`` + gclid (str): + Output only. The Google Click ID. + + This field is a member of `oneof`_ ``_gclid``. + area_of_interest (google.ads.googleads.v24.common.types.ClickLocation): + Output only. The location criteria matching + the area of interest associated with the + impression. + location_of_presence (google.ads.googleads.v24.common.types.ClickLocation): + Output only. The location criteria matching + the location of presence associated with the + impression. + page_number (int): + Output only. Page number in search results + where the ad was shown. + + This field is a member of `oneof`_ ``_page_number``. + ad_group_ad (str): + Output only. The associated ad. + + This field is a member of `oneof`_ ``_ad_group_ad``. + campaign_location_target (str): + Output only. The associated campaign location + target, if one exists. + + This field is a member of `oneof`_ ``_campaign_location_target``. + user_list (str): + Output only. The associated user list, if one + exists. + + This field is a member of `oneof`_ ``_user_list``. + keyword (str): + Output only. The associated keyword, if one + exists and the click corresponds to the SEARCH + channel. + keyword_info (google.ads.googleads.v24.common.types.KeywordInfo): + Output only. Basic information about the + associated keyword, if it exists. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + gclid: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + area_of_interest: click_location.ClickLocation = proto.Field( + proto.MESSAGE, + number=3, + message=click_location.ClickLocation, + ) + location_of_presence: click_location.ClickLocation = proto.Field( + proto.MESSAGE, + number=4, + message=click_location.ClickLocation, + ) + page_number: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + ad_group_ad: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + campaign_location_target: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + user_list: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + keyword: str = proto.Field( + proto.STRING, + number=13, + ) + keyword_info: criteria.KeywordInfo = proto.Field( + proto.MESSAGE, + number=14, + message=criteria.KeywordInfo, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/combined_audience.py b/google/ads/googleads/v24/resources/types/combined_audience.py new file mode 100644 index 000000000..63b7399cd --- /dev/null +++ b/google/ads/googleads/v24/resources/types/combined_audience.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import combined_audience_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CombinedAudience", + }, +) + + +class CombinedAudience(proto.Message): + r"""Describe a resource for combined audiences which includes + different audiences. + + Attributes: + resource_name (str): + Immutable. The resource name of the combined audience. + Combined audience names have the form: + + ``customers/{customer_id}/combinedAudience/{combined_audience_id}`` + id (int): + Output only. ID of the combined audience. + status (google.ads.googleads.v24.enums.types.CombinedAudienceStatusEnum.CombinedAudienceStatus): + Output only. Status of this combined + audience. Indicates whether the combined + audience is enabled or removed. + name (str): + Output only. Name of the combined audience. + It should be unique across all combined + audiences. + description (str): + Output only. Description of this combined + audience. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + ) + status: ( + combined_audience_status.CombinedAudienceStatusEnum.CombinedAudienceStatus + ) = proto.Field( + proto.ENUM, + number=3, + enum=combined_audience_status.CombinedAudienceStatusEnum.CombinedAudienceStatus, + ) + name: str = proto.Field( + proto.STRING, + number=4, + ) + description: str = proto.Field( + proto.STRING, + number=5, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/content_criterion_view.py b/google/ads/googleads/v24/resources/types/content_criterion_view.py new file mode 100644 index 000000000..a9b1da413 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/content_criterion_view.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ContentCriterionView", + }, +) + + +class ContentCriterionView(proto.Message): + r"""A content criterion view. + + Attributes: + resource_name (str): + Output only. The resource name of the content criterion + view. Content criterion view resource names have the form: + + ``customers/{customer_id}/contentCriterionViews/{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/conversion_action.py b/google/ads/googleads/v24/resources/types/conversion_action.py new file mode 100644 index 000000000..5a096aff5 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/conversion_action.py @@ -0,0 +1,456 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import tag_snippet +from google.ads.googleads.v24.enums.types import ( + attribution_model as gage_attribution_model, +) +from google.ads.googleads.v24.enums.types import conversion_action_category +from google.ads.googleads.v24.enums.types import conversion_action_counting_type +from google.ads.googleads.v24.enums.types import conversion_action_status +from google.ads.googleads.v24.enums.types import conversion_action_type +from google.ads.googleads.v24.enums.types import conversion_origin +from google.ads.googleads.v24.enums.types import ( + data_driven_model_status as gage_data_driven_model_status, +) +from google.ads.googleads.v24.enums.types import ( + mobile_app_vendor as gage_mobile_app_vendor, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionAction", + }, +) + + +class ConversionAction(proto.Message): + r"""A conversion action. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the conversion action. + Conversion action resource names have the form: + + ``customers/{customer_id}/conversionActions/{conversion_action_id}`` + id (int): + Output only. The ID of the conversion action. + + This field is a member of `oneof`_ ``_id``. + name (str): + The name of the conversion action. + + This field is required and should not be empty + when creating new conversion actions. + + This field is a member of `oneof`_ ``_name``. + status (google.ads.googleads.v24.enums.types.ConversionActionStatusEnum.ConversionActionStatus): + The status of this conversion action for + conversion event accrual. + type_ (google.ads.googleads.v24.enums.types.ConversionActionTypeEnum.ConversionActionType): + Immutable. The type of this conversion + action. + origin (google.ads.googleads.v24.enums.types.ConversionOriginEnum.ConversionOrigin): + Output only. The conversion origin of this + conversion action. + primary_for_goal (bool): + If a conversion action's primary_for_goal bit is false, the + conversion action is non-biddable for all campaigns + regardless of their customer conversion goal or campaign + conversion goal. However, custom conversion goals do not + respect primary_for_goal, so if a campaign has a custom + conversion goal configured with a primary_for_goal = false + conversion action, that conversion action is still biddable. + By default, primary_for_goal will be true if not set. In V9, + primary_for_goal can only be set to false after creation + through an 'update' operation because it's not declared as + optional. + + This field is a member of `oneof`_ ``_primary_for_goal``. + category (google.ads.googleads.v24.enums.types.ConversionActionCategoryEnum.ConversionActionCategory): + The category of conversions reported for this + conversion action. + owner_customer (str): + Output only. The resource name of the + conversion action owner customer, or null if + this is a system-defined conversion action. + + This field is a member of `oneof`_ ``_owner_customer``. + include_in_conversions_metric (bool): + Whether this conversion action should be + included in the "conversions" metric. + + This field is a member of `oneof`_ ``_include_in_conversions_metric``. + click_through_lookback_window_days (int): + The maximum number of days that may elapse + between an interaction (for example, a click) + and a conversion event. + + This field is a member of `oneof`_ ``_click_through_lookback_window_days``. + view_through_lookback_window_days (int): + The maximum number of days which may elapse + between an impression and a conversion without + an interaction. + + This field is a member of `oneof`_ ``_view_through_lookback_window_days``. + value_settings (google.ads.googleads.v24.resources.types.ConversionAction.ValueSettings): + Settings related to the value for conversion + events associated with this conversion action. + counting_type (google.ads.googleads.v24.enums.types.ConversionActionCountingTypeEnum.ConversionActionCountingType): + How to count conversion events for the + conversion action. + attribution_model_settings (google.ads.googleads.v24.resources.types.ConversionAction.AttributionModelSettings): + Settings related to this conversion action's + attribution model. + tag_snippets (MutableSequence[google.ads.googleads.v24.common.types.TagSnippet]): + Output only. The snippets used for tracking + conversions. + phone_call_duration_seconds (int): + The phone call duration in seconds after + which a conversion should be reported for this + conversion action. + + The value must be between 0 and 10000, + inclusive. + + This field is a member of `oneof`_ ``_phone_call_duration_seconds``. + app_id (str): + App ID for an app conversion action. + + This field is a member of `oneof`_ ``_app_id``. + mobile_app_vendor (google.ads.googleads.v24.enums.types.MobileAppVendorEnum.MobileAppVendor): + Output only. Mobile app vendor for an app + conversion action. + firebase_settings (google.ads.googleads.v24.resources.types.ConversionAction.FirebaseSettings): + Output only. Firebase settings for Firebase + conversion types. + third_party_app_analytics_settings (google.ads.googleads.v24.resources.types.ConversionAction.ThirdPartyAppAnalyticsSettings): + Output only. Third Party App Analytics + settings for third party conversion types. + google_analytics_4_settings (google.ads.googleads.v24.resources.types.ConversionAction.GoogleAnalytics4Settings): + Output only. Google Analytics 4 settings for + Google Analytics 4 conversion types. + """ + + class AttributionModelSettings(proto.Message): + r"""Settings related to this conversion action's attribution + model. + + Attributes: + attribution_model (google.ads.googleads.v24.enums.types.AttributionModelEnum.AttributionModel): + The attribution model type of this conversion + action. + data_driven_model_status (google.ads.googleads.v24.enums.types.DataDrivenModelStatusEnum.DataDrivenModelStatus): + Output only. The status of the data-driven + attribution model for the conversion action. + """ + + attribution_model: ( + gage_attribution_model.AttributionModelEnum.AttributionModel + ) = proto.Field( + proto.ENUM, + number=1, + enum=gage_attribution_model.AttributionModelEnum.AttributionModel, + ) + data_driven_model_status: ( + gage_data_driven_model_status.DataDrivenModelStatusEnum.DataDrivenModelStatus + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_data_driven_model_status.DataDrivenModelStatusEnum.DataDrivenModelStatus, + ) + + class ValueSettings(proto.Message): + r"""Settings related to the value for conversion events + associated with this conversion action. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + default_value (float): + The value to use when conversion events for + this conversion action are sent with an invalid, + disallowed or missing value, or when this + conversion action is configured to always use + the default value. + + This field is a member of `oneof`_ ``_default_value``. + default_currency_code (str): + The currency code to use when conversion + events for this conversion action are sent with + an invalid or missing currency code, or when + this conversion action is configured to always + use the default value. + + This field is a member of `oneof`_ ``_default_currency_code``. + always_use_default_value (bool): + Controls whether the default value and + default currency code are used in place of the + value and currency code specified in conversion + events for this conversion action. + + This field is a member of `oneof`_ ``_always_use_default_value``. + """ + + default_value: float = proto.Field( + proto.DOUBLE, + number=4, + optional=True, + ) + default_currency_code: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + always_use_default_value: bool = proto.Field( + proto.BOOL, + number=6, + optional=True, + ) + + class ThirdPartyAppAnalyticsSettings(proto.Message): + r"""Settings related to a third party app analytics conversion + action. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + event_name (str): + Output only. The event name of a third-party + app analytics conversion. + + This field is a member of `oneof`_ ``_event_name``. + provider_name (str): + Output only. Name of the third-party app + analytics provider. + """ + + event_name: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + provider_name: str = proto.Field( + proto.STRING, + number=3, + ) + + class FirebaseSettings(proto.Message): + r"""Settings related to a Firebase conversion action. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + event_name (str): + Output only. The event name of a Firebase + conversion. + + This field is a member of `oneof`_ ``_event_name``. + project_id (str): + Output only. The Firebase project ID of the + conversion. + + This field is a member of `oneof`_ ``_project_id``. + property_id (int): + Output only. The GA property ID of the + conversion. + property_name (str): + Output only. The GA property name of the + conversion. + """ + + event_name: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + project_id: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + property_id: int = proto.Field( + proto.INT64, + number=5, + ) + property_name: str = proto.Field( + proto.STRING, + number=6, + ) + + class GoogleAnalytics4Settings(proto.Message): + r"""Settings related to a Google Analytics 4 conversion action. + + Attributes: + event_name (str): + Output only. The name of the GA 4 event. + property_name (str): + Output only. The name of the GA 4 property. + property_id (int): + Output only. The ID of the GA 4 property. + """ + + event_name: str = proto.Field( + proto.STRING, + number=1, + ) + property_name: str = proto.Field( + proto.STRING, + number=2, + ) + property_id: int = proto.Field( + proto.INT64, + number=3, + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=21, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=22, + optional=True, + ) + status: ( + conversion_action_status.ConversionActionStatusEnum.ConversionActionStatus + ) = proto.Field( + proto.ENUM, + number=4, + enum=conversion_action_status.ConversionActionStatusEnum.ConversionActionStatus, + ) + type_: ( + conversion_action_type.ConversionActionTypeEnum.ConversionActionType + ) = proto.Field( + proto.ENUM, + number=5, + enum=conversion_action_type.ConversionActionTypeEnum.ConversionActionType, + ) + origin: conversion_origin.ConversionOriginEnum.ConversionOrigin = ( + proto.Field( + proto.ENUM, + number=30, + enum=conversion_origin.ConversionOriginEnum.ConversionOrigin, + ) + ) + primary_for_goal: bool = proto.Field( + proto.BOOL, + number=31, + optional=True, + ) + category: ( + conversion_action_category.ConversionActionCategoryEnum.ConversionActionCategory + ) = proto.Field( + proto.ENUM, + number=6, + enum=conversion_action_category.ConversionActionCategoryEnum.ConversionActionCategory, + ) + owner_customer: str = proto.Field( + proto.STRING, + number=23, + optional=True, + ) + include_in_conversions_metric: bool = proto.Field( + proto.BOOL, + number=24, + optional=True, + ) + click_through_lookback_window_days: int = proto.Field( + proto.INT64, + number=25, + optional=True, + ) + view_through_lookback_window_days: int = proto.Field( + proto.INT64, + number=26, + optional=True, + ) + value_settings: ValueSettings = proto.Field( + proto.MESSAGE, + number=11, + message=ValueSettings, + ) + counting_type: ( + conversion_action_counting_type.ConversionActionCountingTypeEnum.ConversionActionCountingType + ) = proto.Field( + proto.ENUM, + number=12, + enum=conversion_action_counting_type.ConversionActionCountingTypeEnum.ConversionActionCountingType, + ) + attribution_model_settings: AttributionModelSettings = proto.Field( + proto.MESSAGE, + number=13, + message=AttributionModelSettings, + ) + tag_snippets: MutableSequence[tag_snippet.TagSnippet] = proto.RepeatedField( + proto.MESSAGE, + number=14, + message=tag_snippet.TagSnippet, + ) + phone_call_duration_seconds: int = proto.Field( + proto.INT64, + number=27, + optional=True, + ) + app_id: str = proto.Field( + proto.STRING, + number=28, + optional=True, + ) + mobile_app_vendor: ( + gage_mobile_app_vendor.MobileAppVendorEnum.MobileAppVendor + ) = proto.Field( + proto.ENUM, + number=17, + enum=gage_mobile_app_vendor.MobileAppVendorEnum.MobileAppVendor, + ) + firebase_settings: FirebaseSettings = proto.Field( + proto.MESSAGE, + number=18, + message=FirebaseSettings, + ) + third_party_app_analytics_settings: ThirdPartyAppAnalyticsSettings = ( + proto.Field( + proto.MESSAGE, + number=19, + message=ThirdPartyAppAnalyticsSettings, + ) + ) + google_analytics_4_settings: GoogleAnalytics4Settings = proto.Field( + proto.MESSAGE, + number=34, + message=GoogleAnalytics4Settings, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/conversion_custom_variable.py b/google/ads/googleads/v24/resources/types/conversion_custom_variable.py new file mode 100644 index 000000000..7af646e86 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/conversion_custom_variable.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + conversion_custom_variable_status, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionCustomVariable", + }, +) + + +class ConversionCustomVariable(proto.Message): + r"""A conversion custom variable + See "About custom variables for conversions" at + https://support.google.com/google-ads/answer/9964350 + + Attributes: + resource_name (str): + Immutable. The resource name of the conversion custom + variable. Conversion custom variable resource names have the + form: + + ``customers/{customer_id}/conversionCustomVariables/{conversion_custom_variable_id}`` + id (int): + Output only. The ID of the conversion custom + variable. + name (str): + Required. The name of the conversion custom + variable. Name should be unique. The maximum + length of name is 100 characters. There should + not be any extra spaces before and after. + tag (str): + Required. Immutable. The tag of the + conversion custom variable. It is used in the + event snippet and sent to Google Ads along with + conversion pings. For conversion uploads in + Google Ads API, the resource name of the + conversion custom variable is used. Tag should + be unique. The maximum size of tag is 100 bytes. + There should not be any extra spaces before and + after. Currently only lowercase letters, numbers + and underscores are allowed in the tag. + status (google.ads.googleads.v24.enums.types.ConversionCustomVariableStatusEnum.ConversionCustomVariableStatus): + The status of the conversion custom variable + for conversion event accrual. + owner_customer (str): + Output only. The resource name of the + customer that owns the conversion custom + variable. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + ) + name: str = proto.Field( + proto.STRING, + number=3, + ) + tag: str = proto.Field( + proto.STRING, + number=4, + ) + status: ( + conversion_custom_variable_status.ConversionCustomVariableStatusEnum.ConversionCustomVariableStatus + ) = proto.Field( + proto.ENUM, + number=5, + enum=conversion_custom_variable_status.ConversionCustomVariableStatusEnum.ConversionCustomVariableStatus, + ) + owner_customer: str = proto.Field( + proto.STRING, + number=6, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/conversion_goal_campaign_config.py b/google/ads/googleads/v24/resources/types/conversion_goal_campaign_config.py new file mode 100644 index 000000000..cf28c5746 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/conversion_goal_campaign_config.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + goal_config_level as gage_goal_config_level, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionGoalCampaignConfig", + }, +) + + +class ConversionGoalCampaignConfig(proto.Message): + r"""Conversion goal settings for a Campaign. + + Attributes: + resource_name (str): + Immutable. The resource name of the conversion goal campaign + config. Conversion goal campaign config resource names have + the form: + + ``customers/{customer_id}/conversionGoalCampaignConfigs/{campaign_id}`` + campaign (str): + Immutable. The campaign with which this + conversion goal campaign config is associated. + goal_config_level (google.ads.googleads.v24.enums.types.GoalConfigLevelEnum.GoalConfigLevel): + The level of goal config the campaign is + using. + custom_conversion_goal (str): + The custom conversion goal the campaign is + using for optimization. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=2, + ) + goal_config_level: ( + gage_goal_config_level.GoalConfigLevelEnum.GoalConfigLevel + ) = proto.Field( + proto.ENUM, + number=3, + enum=gage_goal_config_level.GoalConfigLevelEnum.GoalConfigLevel, + ) + custom_conversion_goal: str = proto.Field( + proto.STRING, + number=4, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/conversion_value_rule.py b/google/ads/googleads/v24/resources/types/conversion_value_rule.py new file mode 100644 index 000000000..db27e658c --- /dev/null +++ b/google/ads/googleads/v24/resources/types/conversion_value_rule.py @@ -0,0 +1,359 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import conversion_value_rule_status +from google.ads.googleads.v24.enums.types import value_rule_device_type +from google.ads.googleads.v24.enums.types import ( + value_rule_geo_location_match_type, +) +from google.ads.googleads.v24.enums.types import value_rule_operation + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionValueRule", + }, +) + + +class ConversionValueRule(proto.Message): + r"""A conversion value rule + + Attributes: + resource_name (str): + Immutable. The resource name of the conversion value rule. + Conversion value rule resource names have the form: + + ``customers/{customer_id}/conversionValueRules/{conversion_value_rule_id}`` + id (int): + Output only. The ID of the conversion value + rule. + action (google.ads.googleads.v24.resources.types.ConversionValueRule.ValueRuleAction): + Action applied when the rule is triggered. + geo_location_condition (google.ads.googleads.v24.resources.types.ConversionValueRule.ValueRuleGeoLocationCondition): + Condition for Geo location that must be + satisfied for the value rule to apply. + device_condition (google.ads.googleads.v24.resources.types.ConversionValueRule.ValueRuleDeviceCondition): + Condition for device type that must be + satisfied for the value rule to apply. + audience_condition (google.ads.googleads.v24.resources.types.ConversionValueRule.ValueRuleAudienceCondition): + Condition for audience that must be satisfied + for the value rule to apply. + itinerary_condition (google.ads.googleads.v24.resources.types.ConversionValueRule.ValueRuleItineraryCondition): + Condition for itinerary that must be + satisfied for the value rule to apply. + owner_customer (str): + Output only. The resource name of the conversion value + rule's owner customer. When the value rule is inherited from + a manager customer, owner_customer will be the resource name + of the manager whereas the customer in the resource_name + will be of the requesting serving customer. \*\* Read-only + \*\* + status (google.ads.googleads.v24.enums.types.ConversionValueRuleStatusEnum.ConversionValueRuleStatus): + The status of the conversion value rule. + """ + + class ValueRuleAction(proto.Message): + r"""Action applied when rule is applied. + + Attributes: + operation (google.ads.googleads.v24.enums.types.ValueRuleOperationEnum.ValueRuleOperation): + Specifies applied operation. + value (float): + Specifies applied value. + """ + + operation: ( + value_rule_operation.ValueRuleOperationEnum.ValueRuleOperation + ) = proto.Field( + proto.ENUM, + number=1, + enum=value_rule_operation.ValueRuleOperationEnum.ValueRuleOperation, + ) + value: float = proto.Field( + proto.DOUBLE, + number=2, + ) + + class ValueRuleGeoLocationCondition(proto.Message): + r"""Condition on Geo dimension. + + Attributes: + excluded_geo_target_constants (MutableSequence[str]): + Geo locations that advertisers want to + exclude. + excluded_geo_match_type (google.ads.googleads.v24.enums.types.ValueRuleGeoLocationMatchTypeEnum.ValueRuleGeoLocationMatchType): + Excluded Geo location match type. + geo_target_constants (MutableSequence[str]): + Geo locations that advertisers want to + include. + geo_match_type (google.ads.googleads.v24.enums.types.ValueRuleGeoLocationMatchTypeEnum.ValueRuleGeoLocationMatchType): + Included Geo location match type. + """ + + excluded_geo_target_constants: MutableSequence[str] = ( + proto.RepeatedField( + proto.STRING, + number=1, + ) + ) + excluded_geo_match_type: ( + value_rule_geo_location_match_type.ValueRuleGeoLocationMatchTypeEnum.ValueRuleGeoLocationMatchType + ) = proto.Field( + proto.ENUM, + number=2, + enum=value_rule_geo_location_match_type.ValueRuleGeoLocationMatchTypeEnum.ValueRuleGeoLocationMatchType, + ) + geo_target_constants: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + geo_match_type: ( + value_rule_geo_location_match_type.ValueRuleGeoLocationMatchTypeEnum.ValueRuleGeoLocationMatchType + ) = proto.Field( + proto.ENUM, + number=4, + enum=value_rule_geo_location_match_type.ValueRuleGeoLocationMatchTypeEnum.ValueRuleGeoLocationMatchType, + ) + + class ValueRuleDeviceCondition(proto.Message): + r"""Condition on Device dimension. + + Attributes: + device_types (MutableSequence[google.ads.googleads.v24.enums.types.ValueRuleDeviceTypeEnum.ValueRuleDeviceType]): + Value for device type condition. + """ + + device_types: MutableSequence[ + value_rule_device_type.ValueRuleDeviceTypeEnum.ValueRuleDeviceType + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum=value_rule_device_type.ValueRuleDeviceTypeEnum.ValueRuleDeviceType, + ) + + class ValueRuleAudienceCondition(proto.Message): + r"""Condition on Audience dimension. + + Attributes: + user_lists (MutableSequence[str]): + User Lists. + user_interests (MutableSequence[str]): + User Interests. + """ + + user_lists: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + user_interests: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + + class ValueRuleItineraryCondition(proto.Message): + r"""Condition on Itinerary dimension. + + Attributes: + advance_booking_window (google.ads.googleads.v24.resources.types.ConversionValueRule.ValueRuleItineraryAdvanceBookingWindow): + Range for the number of days between the date + of the booking and the start of the itinerary. + travel_length (google.ads.googleads.v24.resources.types.ConversionValueRule.ValueRuleItineraryTravelLength): + Range for the itinerary length in number of + nights. + travel_start_day (google.ads.googleads.v24.resources.types.ConversionValueRule.ValueRuleItineraryTravelStartDay): + The days of the week on which this + itinerary's travel can start. + """ + + advance_booking_window: ( + "ConversionValueRule.ValueRuleItineraryAdvanceBookingWindow" + ) = proto.Field( + proto.MESSAGE, + number=1, + message="ConversionValueRule.ValueRuleItineraryAdvanceBookingWindow", + ) + travel_length: "ConversionValueRule.ValueRuleItineraryTravelLength" = ( + proto.Field( + proto.MESSAGE, + number=2, + message="ConversionValueRule.ValueRuleItineraryTravelLength", + ) + ) + travel_start_day: ( + "ConversionValueRule.ValueRuleItineraryTravelStartDay" + ) = proto.Field( + proto.MESSAGE, + number=3, + message="ConversionValueRule.ValueRuleItineraryTravelStartDay", + ) + + class ValueRuleItineraryAdvanceBookingWindow(proto.Message): + r"""Range for the number of days between the date of the booking + and the start of the itinerary. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + min_days (int): + Minimum number of days between the date of + the booking the start date. + + This field is a member of `oneof`_ ``_min_days``. + max_days (int): + Maximum number of days between the date of + the booking the start date. + + This field is a member of `oneof`_ ``_max_days``. + """ + + min_days: int = proto.Field( + proto.INT32, + number=3, + optional=True, + ) + max_days: int = proto.Field( + proto.INT32, + number=4, + optional=True, + ) + + class ValueRuleItineraryTravelLength(proto.Message): + r"""Range for the itinerary length in number of nights. + + Attributes: + min_nights (int): + Minimum number of nights between the start + date and the end date. + max_nights (int): + Maximum number of days between the start date + and the end date. + """ + + min_nights: int = proto.Field( + proto.INT32, + number=1, + ) + max_nights: int = proto.Field( + proto.INT32, + number=2, + ) + + class ValueRuleItineraryTravelStartDay(proto.Message): + r"""The days of the week on which an itinerary's travel can + start. + + Attributes: + monday (bool): + The travel can start on Monday. + tuesday (bool): + The travel can start on Tuesday. + wednesday (bool): + The travel can start on Wednesday. + thursday (bool): + The travel can start on Thursday. + friday (bool): + The travel can start on Friday. + saturday (bool): + The travel can start on Saturday. + sunday (bool): + The travel can start on Sunday. + """ + + monday: bool = proto.Field( + proto.BOOL, + number=1, + ) + tuesday: bool = proto.Field( + proto.BOOL, + number=2, + ) + wednesday: bool = proto.Field( + proto.BOOL, + number=3, + ) + thursday: bool = proto.Field( + proto.BOOL, + number=4, + ) + friday: bool = proto.Field( + proto.BOOL, + number=5, + ) + saturday: bool = proto.Field( + proto.BOOL, + number=6, + ) + sunday: bool = proto.Field( + proto.BOOL, + number=7, + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + ) + action: ValueRuleAction = proto.Field( + proto.MESSAGE, + number=3, + message=ValueRuleAction, + ) + geo_location_condition: ValueRuleGeoLocationCondition = proto.Field( + proto.MESSAGE, + number=4, + message=ValueRuleGeoLocationCondition, + ) + device_condition: ValueRuleDeviceCondition = proto.Field( + proto.MESSAGE, + number=5, + message=ValueRuleDeviceCondition, + ) + audience_condition: ValueRuleAudienceCondition = proto.Field( + proto.MESSAGE, + number=6, + message=ValueRuleAudienceCondition, + ) + itinerary_condition: ValueRuleItineraryCondition = proto.Field( + proto.MESSAGE, + number=9, + message=ValueRuleItineraryCondition, + ) + owner_customer: str = proto.Field( + proto.STRING, + number=7, + ) + status: ( + conversion_value_rule_status.ConversionValueRuleStatusEnum.ConversionValueRuleStatus + ) = proto.Field( + proto.ENUM, + number=8, + enum=conversion_value_rule_status.ConversionValueRuleStatusEnum.ConversionValueRuleStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/conversion_value_rule_set.py b/google/ads/googleads/v24/resources/types/conversion_value_rule_set.py new file mode 100644 index 000000000..9a034d19f --- /dev/null +++ b/google/ads/googleads/v24/resources/types/conversion_value_rule_set.py @@ -0,0 +1,137 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import conversion_action_category +from google.ads.googleads.v24.enums.types import ( + conversion_value_rule_set_status, +) +from google.ads.googleads.v24.enums.types import value_rule_set_attachment_type +from google.ads.googleads.v24.enums.types import value_rule_set_dimension + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ConversionValueRuleSet", + }, +) + + +class ConversionValueRuleSet(proto.Message): + r"""A conversion value rule set is a collection of conversion value + rules that lets you adjust conversion values based on the dimensions + specified in the ``dimensions`` field. + + Attributes: + resource_name (str): + Immutable. The resource name of the conversion value rule + set. Conversion value rule set resource names have the form: + + ``customers/{customer_id}/conversionValueRuleSets/{conversion_value_rule_set_id}`` + id (int): + Output only. The ID of the conversion value + rule set. + conversion_value_rules (MutableSequence[str]): + Resource names of rules within the rule set. + dimensions (MutableSequence[google.ads.googleads.v24.enums.types.ValueRuleSetDimensionEnum.ValueRuleSetDimension]): + Defines dimensions for Value Rule conditions. + The condition types of value rules within this + value rule set must be of these dimensions. The + first entry in this list is the primary + dimension of the included value rules. When + using value rule primary dimension segmentation, + conversion values will be segmented into the + values adjusted by value rules and the original + values, if some value rules apply. + owner_customer (str): + Output only. The resource name of the conversion value rule + set's owner customer. When the value rule set is inherited + from a manager customer, owner_customer will be the resource + name of the manager whereas the customer in the + resource_name will be of the requesting serving customer. + \*\* Read-only \*\* + attachment_type (google.ads.googleads.v24.enums.types.ValueRuleSetAttachmentTypeEnum.ValueRuleSetAttachmentType): + Immutable. Defines the scope where the + conversion value rule set is attached. + campaign (str): + The resource name of the campaign when the + conversion value rule set is attached to a + campaign. + status (google.ads.googleads.v24.enums.types.ConversionValueRuleSetStatusEnum.ConversionValueRuleSetStatus): + Output only. The status of the conversion value rule set. + \*\* Read-only \*\* + conversion_action_categories (MutableSequence[google.ads.googleads.v24.enums.types.ConversionActionCategoryEnum.ConversionActionCategory]): + Immutable. The conversion action categories + of the conversion value rule set. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + ) + conversion_value_rules: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + dimensions: MutableSequence[ + value_rule_set_dimension.ValueRuleSetDimensionEnum.ValueRuleSetDimension + ] = proto.RepeatedField( + proto.ENUM, + number=4, + enum=value_rule_set_dimension.ValueRuleSetDimensionEnum.ValueRuleSetDimension, + ) + owner_customer: str = proto.Field( + proto.STRING, + number=5, + ) + attachment_type: ( + value_rule_set_attachment_type.ValueRuleSetAttachmentTypeEnum.ValueRuleSetAttachmentType + ) = proto.Field( + proto.ENUM, + number=6, + enum=value_rule_set_attachment_type.ValueRuleSetAttachmentTypeEnum.ValueRuleSetAttachmentType, + ) + campaign: str = proto.Field( + proto.STRING, + number=7, + ) + status: ( + conversion_value_rule_set_status.ConversionValueRuleSetStatusEnum.ConversionValueRuleSetStatus + ) = proto.Field( + proto.ENUM, + number=8, + enum=conversion_value_rule_set_status.ConversionValueRuleSetStatusEnum.ConversionValueRuleSetStatus, + ) + conversion_action_categories: MutableSequence[ + conversion_action_category.ConversionActionCategoryEnum.ConversionActionCategory + ] = proto.RepeatedField( + proto.ENUM, + number=9, + enum=conversion_action_category.ConversionActionCategoryEnum.ConversionActionCategory, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/currency_constant.py b/google/ads/googleads/v24/resources/types/currency_constant.py new file mode 100644 index 000000000..bac834ea6 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/currency_constant.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CurrencyConstant", + }, +) + + +class CurrencyConstant(proto.Message): + r"""A currency constant. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the currency constant. + Currency constant resource names have the form: + + ``currencyConstants/{code}`` + code (str): + Output only. ISO 4217 three-letter currency + code, for example, "USD". + + This field is a member of `oneof`_ ``_code``. + name (str): + Output only. Full English name of the + currency. + + This field is a member of `oneof`_ ``_name``. + symbol (str): + Output only. Standard symbol for describing + this currency, for example, '$' for US Dollars. + + This field is a member of `oneof`_ ``_symbol``. + billable_unit_micros (int): + Output only. The billable unit for this + currency. Billed amounts should be multiples of + this value. + + This field is a member of `oneof`_ ``_billable_unit_micros``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + code: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + symbol: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + billable_unit_micros: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/custom_audience.py b/google/ads/googleads/v24/resources/types/custom_audience.py new file mode 100644 index 000000000..9472b9d98 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/custom_audience.py @@ -0,0 +1,182 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import custom_audience_member_type +from google.ads.googleads.v24.enums.types import custom_audience_status +from google.ads.googleads.v24.enums.types import custom_audience_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomAudience", + "CustomAudienceMember", + }, +) + + +class CustomAudience(proto.Message): + r"""A custom audience. This is a list of users by interest. The unique + key of a custom audience consists of the following fields: name. + Violating the unique key constraint produces error: + CustomAudienceError.NAME_ALREADY_USED + + Attributes: + resource_name (str): + Immutable. The resource name of the custom audience. Custom + audience resource names have the form: + + ``customers/{customer_id}/customAudiences/{custom_audience_id}`` + id (int): + Output only. ID of the custom audience. + status (google.ads.googleads.v24.enums.types.CustomAudienceStatusEnum.CustomAudienceStatus): + Output only. Status of this custom audience. + Indicates whether the custom audience is enabled + or removed. + name (str): + Name of the custom audience. It should be + unique for all custom audiences created by a + customer. This field is required for creating + operations. + type_ (google.ads.googleads.v24.enums.types.CustomAudienceTypeEnum.CustomAudienceType): + Type of the custom audience. ("INTEREST" OR + "PURCHASE_INTENT" is not allowed for newly created custom + audience but kept for existing audiences) + description (str): + Description of this custom audience. + members (MutableSequence[google.ads.googleads.v24.resources.types.CustomAudienceMember]): + List of custom audience members that this + custom audience is composed of. Members can be + added during CustomAudience creation. If members + are presented in UPDATE operation, existing + members will be overridden. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + ) + status: ( + custom_audience_status.CustomAudienceStatusEnum.CustomAudienceStatus + ) = proto.Field( + proto.ENUM, + number=3, + enum=custom_audience_status.CustomAudienceStatusEnum.CustomAudienceStatus, + ) + name: str = proto.Field( + proto.STRING, + number=4, + ) + type_: custom_audience_type.CustomAudienceTypeEnum.CustomAudienceType = ( + proto.Field( + proto.ENUM, + number=5, + enum=custom_audience_type.CustomAudienceTypeEnum.CustomAudienceType, + ) + ) + description: str = proto.Field( + proto.STRING, + number=6, + ) + members: MutableSequence["CustomAudienceMember"] = proto.RepeatedField( + proto.MESSAGE, + number=7, + message="CustomAudienceMember", + ) + + +class CustomAudienceMember(proto.Message): + r"""A member of custom audience. A member can be a KEYWORD, URL, + PLACE_CATEGORY or APP. It can only be created or removed but not + changed. + + 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: + member_type (google.ads.googleads.v24.enums.types.CustomAudienceMemberTypeEnum.CustomAudienceMemberType): + The type of custom audience member, KEYWORD, URL, + PLACE_CATEGORY or APP. + keyword (str): + A keyword or keyword phrase — at most 10 + words and 80 characters. Languages with + double-width characters such as Chinese, + Japanese, or Korean, are allowed 40 characters, + which describes the user's interests or actions. + + This field is a member of `oneof`_ ``value``. + url (str): + An HTTP URL, protocol-included — at most 2048 + characters, which includes contents users have + interests in. + + This field is a member of `oneof`_ ``value``. + place_category (int): + A place type described by a place category + users visit. + + This field is a member of `oneof`_ ``value``. + app (str): + A package name of Android apps which users + installed such as com.google.example. + + This field is a member of `oneof`_ ``value``. + """ + + member_type: ( + custom_audience_member_type.CustomAudienceMemberTypeEnum.CustomAudienceMemberType + ) = proto.Field( + proto.ENUM, + number=1, + enum=custom_audience_member_type.CustomAudienceMemberTypeEnum.CustomAudienceMemberType, + ) + keyword: str = proto.Field( + proto.STRING, + number=2, + oneof="value", + ) + url: str = proto.Field( + proto.STRING, + number=3, + oneof="value", + ) + place_category: int = proto.Field( + proto.INT64, + number=4, + oneof="value", + ) + app: str = proto.Field( + proto.STRING, + number=5, + oneof="value", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/custom_conversion_goal.py b/google/ads/googleads/v24/resources/types/custom_conversion_goal.py new file mode 100644 index 000000000..7b18eb80d --- /dev/null +++ b/google/ads/googleads/v24/resources/types/custom_conversion_goal.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import custom_conversion_goal_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomConversionGoal", + }, +) + + +class CustomConversionGoal(proto.Message): + r"""Custom conversion goal that can make arbitrary conversion + actions biddable. + + Attributes: + resource_name (str): + Immutable. The resource name of the custom conversion goal. + Custom conversion goal resource names have the form: + + ``customers/{customer_id}/customConversionGoals/{goal_id}`` + id (int): + Immutable. The ID for this custom conversion + goal. + name (str): + The name for this custom conversion goal. + conversion_actions (MutableSequence[str]): + Conversion actions that the custom conversion + goal makes biddable. + status (google.ads.googleads.v24.enums.types.CustomConversionGoalStatusEnum.CustomConversionGoalStatus): + The status of the custom conversion goal. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + ) + name: str = proto.Field( + proto.STRING, + number=3, + ) + conversion_actions: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=4, + ) + status: ( + custom_conversion_goal_status.CustomConversionGoalStatusEnum.CustomConversionGoalStatus + ) = proto.Field( + proto.ENUM, + number=5, + enum=custom_conversion_goal_status.CustomConversionGoalStatusEnum.CustomConversionGoalStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/custom_interest.py b/google/ads/googleads/v24/resources/types/custom_interest.py new file mode 100644 index 000000000..f764694db --- /dev/null +++ b/google/ads/googleads/v24/resources/types/custom_interest.py @@ -0,0 +1,151 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import custom_interest_member_type +from google.ads.googleads.v24.enums.types import custom_interest_status +from google.ads.googleads.v24.enums.types import custom_interest_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomInterest", + "CustomInterestMember", + }, +) + + +class CustomInterest(proto.Message): + r"""A custom interest. This is a list of users by interest. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the custom interest. Custom + interest resource names have the form: + + ``customers/{customer_id}/customInterests/{custom_interest_id}`` + id (int): + Output only. Id of the custom interest. + + This field is a member of `oneof`_ ``_id``. + status (google.ads.googleads.v24.enums.types.CustomInterestStatusEnum.CustomInterestStatus): + Status of this custom interest. Indicates + whether the custom interest is enabled or + removed. + name (str): + Name of the custom interest. It should be + unique across the same custom affinity audience. + This field is required for create operations. + + This field is a member of `oneof`_ ``_name``. + type_ (google.ads.googleads.v24.enums.types.CustomInterestTypeEnum.CustomInterestType): + Type of the custom interest, CUSTOM_AFFINITY or + CUSTOM_INTENT. By default the type is set to + CUSTOM_AFFINITY. + description (str): + Description of this custom interest audience. + + This field is a member of `oneof`_ ``_description``. + members (MutableSequence[google.ads.googleads.v24.resources.types.CustomInterestMember]): + List of custom interest members that this + custom interest is composed of. Members can be + added during CustomInterest creation. If members + are presented in UPDATE operation, existing + members will be overridden. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + status: ( + custom_interest_status.CustomInterestStatusEnum.CustomInterestStatus + ) = proto.Field( + proto.ENUM, + number=3, + enum=custom_interest_status.CustomInterestStatusEnum.CustomInterestStatus, + ) + name: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + type_: custom_interest_type.CustomInterestTypeEnum.CustomInterestType = ( + proto.Field( + proto.ENUM, + number=5, + enum=custom_interest_type.CustomInterestTypeEnum.CustomInterestType, + ) + ) + description: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + members: MutableSequence["CustomInterestMember"] = proto.RepeatedField( + proto.MESSAGE, + number=7, + message="CustomInterestMember", + ) + + +class CustomInterestMember(proto.Message): + r"""A member of custom interest audience. A member can be a + keyword or url. It is immutable, that is, it can only be created + or removed but not changed. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + member_type (google.ads.googleads.v24.enums.types.CustomInterestMemberTypeEnum.CustomInterestMemberType): + The type of custom interest member, KEYWORD + or URL. + parameter (str): + Keyword text when member_type is KEYWORD or URL string when + member_type is URL. + + This field is a member of `oneof`_ ``_parameter``. + """ + + member_type: ( + custom_interest_member_type.CustomInterestMemberTypeEnum.CustomInterestMemberType + ) = proto.Field( + proto.ENUM, + number=1, + enum=custom_interest_member_type.CustomInterestMemberTypeEnum.CustomInterestMemberType, + ) + parameter: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer.py b/google/ads/googleads/v24/resources/types/customer.py new file mode 100644 index 000000000..be0d4b729 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer.py @@ -0,0 +1,648 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import ( + third_party_integration_partners as gagc_third_party_integration_partners, +) +from google.ads.googleads.v24.enums.types import brand_safety_suitability +from google.ads.googleads.v24.enums.types import conversion_tracking_status_enum +from google.ads.googleads.v24.enums.types import ( + customer_pay_per_conversion_eligibility_failure_reason, +) +from google.ads.googleads.v24.enums.types import customer_status +from google.ads.googleads.v24.enums.types import eu_political_advertising_status +from google.ads.googleads.v24.enums.types import ( + local_services_verification_status, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "Customer", + "CallReportingSetting", + "ConversionTrackingSetting", + "RemarketingSetting", + "CustomerAgreementSetting", + "LocalServicesSettings", + "GranularLicenseStatus", + "GranularInsuranceStatus", + "VideoCustomer", + }, +) + + +class Customer(proto.Message): + r"""A customer. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the customer. Customer + resource names have the form: + + ``customers/{customer_id}`` + id (int): + Output only. The ID of the customer. + + This field is a member of `oneof`_ ``_id``. + descriptive_name (str): + Optional, non-unique descriptive name of the + customer. + + This field is a member of `oneof`_ ``_descriptive_name``. + currency_code (str): + Immutable. The currency in which the account + operates. A subset of the currency codes from + the ISO 4217 standard is supported. + + This field is a member of `oneof`_ ``_currency_code``. + time_zone (str): + Immutable. The local timezone ID of the + customer. + + This field is a member of `oneof`_ ``_time_zone``. + tracking_url_template (str): + The URL template for constructing a tracking URL out of + parameters. Only mutable in an ``update`` operation. + + This field is a member of `oneof`_ ``_tracking_url_template``. + final_url_suffix (str): + The URL template for appending params to the final URL. Only + mutable in an ``update`` operation. + + This field is a member of `oneof`_ ``_final_url_suffix``. + auto_tagging_enabled (bool): + Whether auto-tagging is enabled for the customer. Only + mutable in an ``update`` operation. + + This field is a member of `oneof`_ ``_auto_tagging_enabled``. + has_partners_badge (bool): + Output only. Whether the Customer has a + Partners program badge. If the Customer is not + associated with the Partners program, this will + be false. For more information, see + https://support.google.com/partners/answer/3125774. + + This field is a member of `oneof`_ ``_has_partners_badge``. + manager (bool): + Output only. Whether the customer is a + manager. + + This field is a member of `oneof`_ ``_manager``. + test_account (bool): + Output only. Whether the customer is a test + account. + + This field is a member of `oneof`_ ``_test_account``. + call_reporting_setting (google.ads.googleads.v24.resources.types.CallReportingSetting): + Call reporting setting for a customer. Only mutable in an + ``update`` operation. + conversion_tracking_setting (google.ads.googleads.v24.resources.types.ConversionTrackingSetting): + Conversion tracking setting for a customer. + remarketing_setting (google.ads.googleads.v24.resources.types.RemarketingSetting): + Output only. Remarketing setting for a + customer. + pay_per_conversion_eligibility_failure_reasons (MutableSequence[google.ads.googleads.v24.enums.types.CustomerPayPerConversionEligibilityFailureReasonEnum.CustomerPayPerConversionEligibilityFailureReason]): + Output only. Reasons why the customer is not + eligible to use PaymentMode.CONVERSIONS. If the + list is empty, the customer is eligible. This + field is read-only. + optimization_score (float): + Output only. Optimization score of the + customer. + Optimization score is an estimate of how well a + customer's campaigns are set to perform. It + ranges from 0% (0.0) to 100% (1.0). This field + is null for all manager customers, and for + unscored non-manager customers. + + See "About optimization score" at + https://support.google.com/google-ads/answer/9061546. + + This field is read-only. + + This field is a member of `oneof`_ ``_optimization_score``. + optimization_score_weight (float): + Output only. Optimization score weight of the customer. + + Optimization score weight can be used to compare/aggregate + optimization scores across multiple non-manager customers. + The aggregate optimization score of a manager is computed as + the sum over all of their customers of + ``Customer.optimization_score * Customer.optimization_score_weight``. + This field is 0 for all manager customers, and for unscored + non-manager customers. + + This field is read-only. + status (google.ads.googleads.v24.enums.types.CustomerStatusEnum.CustomerStatus): + Output only. The status of the customer. + location_asset_auto_migration_done (bool): + Output only. True if feed based location has + been migrated to asset based location. + + This field is a member of `oneof`_ ``_location_asset_auto_migration_done``. + image_asset_auto_migration_done (bool): + Output only. True if feed based image has + been migrated to asset based image. + + This field is a member of `oneof`_ ``_image_asset_auto_migration_done``. + location_asset_auto_migration_done_date_time (str): + Output only. Timestamp of migration from feed + based location to asset base location in + yyyy-MM-dd HH:mm:ss format. + + This field is a member of `oneof`_ ``_location_asset_auto_migration_done_date_time``. + image_asset_auto_migration_done_date_time (str): + Output only. Timestamp of migration from feed + based image to asset base image in yyyy-MM-dd + HH:mm:ss format. + + This field is a member of `oneof`_ ``_image_asset_auto_migration_done_date_time``. + customer_agreement_setting (google.ads.googleads.v24.resources.types.CustomerAgreementSetting): + Output only. Customer Agreement Setting for a + customer. + local_services_settings (google.ads.googleads.v24.resources.types.LocalServicesSettings): + Output only. Settings for Local Services + customer. + video_brand_safety_suitability (google.ads.googleads.v24.enums.types.BrandSafetySuitabilityEnum.BrandSafetySuitability): + Brand Safety setting at the account level. + Allows for selecting an inventory type to show + your ads on content that is the right fit for + your brand. See + https://support.google.com/google-ads/answer/7515513. + video_customer (google.ads.googleads.v24.resources.types.VideoCustomer): + Video specific information about a Customer. + contains_eu_political_advertising (google.ads.googleads.v24.enums.types.EuPoliticalAdvertisingStatusEnum.EuPoliticalAdvertisingStatus): + Output only. Returns the advertiser + self-declaration status of whether this customer + contains political advertising content targeted + towards the European Union. You can use the + Google Ads UI to update this account-level + declaration, or use the API to update the + self-declaration status of individual campaigns. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=19, + optional=True, + ) + descriptive_name: str = proto.Field( + proto.STRING, + number=20, + optional=True, + ) + currency_code: str = proto.Field( + proto.STRING, + number=21, + optional=True, + ) + time_zone: str = proto.Field( + proto.STRING, + number=22, + optional=True, + ) + tracking_url_template: str = proto.Field( + proto.STRING, + number=23, + optional=True, + ) + final_url_suffix: str = proto.Field( + proto.STRING, + number=24, + optional=True, + ) + auto_tagging_enabled: bool = proto.Field( + proto.BOOL, + number=25, + optional=True, + ) + has_partners_badge: bool = proto.Field( + proto.BOOL, + number=26, + optional=True, + ) + manager: bool = proto.Field( + proto.BOOL, + number=27, + optional=True, + ) + test_account: bool = proto.Field( + proto.BOOL, + number=28, + optional=True, + ) + call_reporting_setting: "CallReportingSetting" = proto.Field( + proto.MESSAGE, + number=10, + message="CallReportingSetting", + ) + conversion_tracking_setting: "ConversionTrackingSetting" = proto.Field( + proto.MESSAGE, + number=14, + message="ConversionTrackingSetting", + ) + remarketing_setting: "RemarketingSetting" = proto.Field( + proto.MESSAGE, + number=15, + message="RemarketingSetting", + ) + pay_per_conversion_eligibility_failure_reasons: MutableSequence[ + customer_pay_per_conversion_eligibility_failure_reason.CustomerPayPerConversionEligibilityFailureReasonEnum.CustomerPayPerConversionEligibilityFailureReason + ] = proto.RepeatedField( + proto.ENUM, + number=16, + enum=customer_pay_per_conversion_eligibility_failure_reason.CustomerPayPerConversionEligibilityFailureReasonEnum.CustomerPayPerConversionEligibilityFailureReason, + ) + optimization_score: float = proto.Field( + proto.DOUBLE, + number=29, + optional=True, + ) + optimization_score_weight: float = proto.Field( + proto.DOUBLE, + number=30, + ) + status: customer_status.CustomerStatusEnum.CustomerStatus = proto.Field( + proto.ENUM, + number=36, + enum=customer_status.CustomerStatusEnum.CustomerStatus, + ) + location_asset_auto_migration_done: bool = proto.Field( + proto.BOOL, + number=38, + optional=True, + ) + image_asset_auto_migration_done: bool = proto.Field( + proto.BOOL, + number=39, + optional=True, + ) + location_asset_auto_migration_done_date_time: str = proto.Field( + proto.STRING, + number=40, + optional=True, + ) + image_asset_auto_migration_done_date_time: str = proto.Field( + proto.STRING, + number=41, + optional=True, + ) + customer_agreement_setting: "CustomerAgreementSetting" = proto.Field( + proto.MESSAGE, + number=44, + message="CustomerAgreementSetting", + ) + local_services_settings: "LocalServicesSettings" = proto.Field( + proto.MESSAGE, + number=45, + message="LocalServicesSettings", + ) + video_brand_safety_suitability: ( + brand_safety_suitability.BrandSafetySuitabilityEnum.BrandSafetySuitability + ) = proto.Field( + proto.ENUM, + number=46, + enum=brand_safety_suitability.BrandSafetySuitabilityEnum.BrandSafetySuitability, + ) + video_customer: "VideoCustomer" = proto.Field( + proto.MESSAGE, + number=54, + message="VideoCustomer", + ) + contains_eu_political_advertising: ( + eu_political_advertising_status.EuPoliticalAdvertisingStatusEnum.EuPoliticalAdvertisingStatus + ) = proto.Field( + proto.ENUM, + number=55, + enum=eu_political_advertising_status.EuPoliticalAdvertisingStatusEnum.EuPoliticalAdvertisingStatus, + ) + + +class CallReportingSetting(proto.Message): + r"""Call reporting setting for a customer. Only mutable in an ``update`` + operation. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + call_reporting_enabled (bool): + Enable reporting of phone call events by + redirecting them through Google System. + + This field is a member of `oneof`_ ``_call_reporting_enabled``. + call_conversion_reporting_enabled (bool): + Whether to enable call conversion reporting. + + This field is a member of `oneof`_ ``_call_conversion_reporting_enabled``. + call_conversion_action (str): + Customer-level call conversion action to attribute a call + conversion to. If not set a default conversion action is + used. Only in effect when call_conversion_reporting_enabled + is set to true. + + This field is a member of `oneof`_ ``_call_conversion_action``. + """ + + call_reporting_enabled: bool = proto.Field( + proto.BOOL, + number=10, + optional=True, + ) + call_conversion_reporting_enabled: bool = proto.Field( + proto.BOOL, + number=11, + optional=True, + ) + call_conversion_action: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + + +class ConversionTrackingSetting(proto.Message): + r"""A collection of customer-wide settings related to Google Ads + Conversion Tracking. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + conversion_tracking_id (int): + Output only. The conversion tracking id used for this + account. This id doesn't indicate whether the customer uses + conversion tracking (conversion_tracking_status does). This + field is read-only. + + This field is a member of `oneof`_ ``_conversion_tracking_id``. + cross_account_conversion_tracking_id (int): + Output only. The conversion tracking id of the customer's + manager. This is set when the customer is opted into cross + account conversion tracking, and it overrides + conversion_tracking_id. This field can only be managed + through the Google Ads UI. This field is read-only. + + This field is a member of `oneof`_ ``_cross_account_conversion_tracking_id``. + accepted_customer_data_terms (bool): + Output only. Whether the customer has + accepted customer data terms. If using + cross-account conversion tracking, this value is + inherited from the manager. This field is + read-only. For more + information, see + https://support.google.com/adspolicy/answer/7475709. + conversion_tracking_status (google.ads.googleads.v24.enums.types.ConversionTrackingStatusEnum.ConversionTrackingStatus): + Output only. Conversion tracking status. It indicates + whether the customer is using conversion tracking, and who + is the conversion tracking owner of this customer. If this + customer is using cross-account conversion tracking, the + value returned will differ based on the + ``login-customer-id`` of the request. + enhanced_conversions_for_leads_enabled (bool): + Output only. Whether the customer is opted-in + for enhanced conversions for leads. If using + cross-account conversion tracking, this value is + inherited from the manager. This field is + read-only. + google_ads_conversion_customer (str): + The resource name of the customer where + conversions are created and managed. This field + is read-only. + """ + + conversion_tracking_id: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + cross_account_conversion_tracking_id: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + accepted_customer_data_terms: bool = proto.Field( + proto.BOOL, + number=5, + ) + conversion_tracking_status: ( + conversion_tracking_status_enum.ConversionTrackingStatusEnum.ConversionTrackingStatus + ) = proto.Field( + proto.ENUM, + number=6, + enum=conversion_tracking_status_enum.ConversionTrackingStatusEnum.ConversionTrackingStatus, + ) + enhanced_conversions_for_leads_enabled: bool = proto.Field( + proto.BOOL, + number=7, + ) + google_ads_conversion_customer: str = proto.Field( + proto.STRING, + number=8, + ) + + +class RemarketingSetting(proto.Message): + r"""Remarketing setting for a customer. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + google_global_site_tag (str): + Output only. The Google tag. + + This field is a member of `oneof`_ ``_google_global_site_tag``. + """ + + google_global_site_tag: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class CustomerAgreementSetting(proto.Message): + r"""Customer Agreement Setting for a customer. + + Attributes: + accepted_lead_form_terms (bool): + Output only. Whether the customer has + accepted lead form term of service. + """ + + accepted_lead_form_terms: bool = proto.Field( + proto.BOOL, + number=1, + ) + + +class LocalServicesSettings(proto.Message): + r"""Settings for Local Services customer. + + Attributes: + granular_license_statuses (MutableSequence[google.ads.googleads.v24.resources.types.GranularLicenseStatus]): + Output only. A read-only list of geo vertical + level license statuses. + granular_insurance_statuses (MutableSequence[google.ads.googleads.v24.resources.types.GranularInsuranceStatus]): + Output only. A read-only list of geo vertical + level insurance statuses. + """ + + granular_license_statuses: MutableSequence["GranularLicenseStatus"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="GranularLicenseStatus", + ) + ) + granular_insurance_statuses: MutableSequence["GranularInsuranceStatus"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="GranularInsuranceStatus", + ) + ) + + +class GranularLicenseStatus(proto.Message): + r"""License status at geo + vertical level. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + geo_criterion_id (int): + Output only. Geotarget criterion ID + associated with the status. Can be on country or + state/province geo level, depending on + requirements and location. See + https://developers.google.com/google-ads/api/data/geotargets + for more information. + + This field is a member of `oneof`_ ``_geo_criterion_id``. + category_id (str): + Output only. Service category associated with the status. + For example, xcat:service_area_business_plumber. For more + details see: + https://developers.google.com/google-ads/api/data/codes-formats#local_services_ids + + This field is a member of `oneof`_ ``_category_id``. + verification_status (google.ads.googleads.v24.enums.types.LocalServicesVerificationStatusEnum.LocalServicesVerificationStatus): + Output only. Granular license status, per geo + + vertical. + + This field is a member of `oneof`_ ``_verification_status``. + """ + + geo_criterion_id: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + category_id: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + verification_status: ( + local_services_verification_status.LocalServicesVerificationStatusEnum.LocalServicesVerificationStatus + ) = proto.Field( + proto.ENUM, + number=3, + optional=True, + enum=local_services_verification_status.LocalServicesVerificationStatusEnum.LocalServicesVerificationStatus, + ) + + +class GranularInsuranceStatus(proto.Message): + r"""Insurance status at geo + vertical level. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + geo_criterion_id (int): + Output only. Geotarget criterion ID + associated with the status. Can be on country or + state/province geo level, depending on + requirements and location. See + https://developers.google.com/google-ads/api/data/geotargets + for more information. + + This field is a member of `oneof`_ ``_geo_criterion_id``. + category_id (str): + Output only. Service category associated with the status. + For example, xcat:service_area_business_plumber. For more + details see: + https://developers.google.com/google-ads/api/data/codes-formats#local_services_ids + + This field is a member of `oneof`_ ``_category_id``. + verification_status (google.ads.googleads.v24.enums.types.LocalServicesVerificationStatusEnum.LocalServicesVerificationStatus): + Output only. Granular insurance status, per + geo + vertical. + + This field is a member of `oneof`_ ``_verification_status``. + """ + + geo_criterion_id: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + category_id: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + verification_status: ( + local_services_verification_status.LocalServicesVerificationStatusEnum.LocalServicesVerificationStatus + ) = proto.Field( + proto.ENUM, + number=3, + optional=True, + enum=local_services_verification_status.LocalServicesVerificationStatusEnum.LocalServicesVerificationStatus, + ) + + +class VideoCustomer(proto.Message): + r"""Video specific information about a Customer. + + Attributes: + third_party_integration_partners (google.ads.googleads.v24.common.types.CustomerThirdPartyIntegrationPartners): + Third Party integration partners. + """ + + third_party_integration_partners: ( + gagc_third_party_integration_partners.CustomerThirdPartyIntegrationPartners + ) = proto.Field( + proto.MESSAGE, + number=1, + message=gagc_third_party_integration_partners.CustomerThirdPartyIntegrationPartners, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer_asset.py b/google/ads/googleads/v24/resources/types/customer_asset.py new file mode 100644 index 000000000..9fb3a4ee6 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer_asset.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import asset_policy +from google.ads.googleads.v24.enums.types import asset_field_type +from google.ads.googleads.v24.enums.types import asset_link_primary_status +from google.ads.googleads.v24.enums.types import ( + asset_link_primary_status_reason, +) +from google.ads.googleads.v24.enums.types import asset_link_status +from google.ads.googleads.v24.enums.types import asset_source + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerAsset", + }, +) + + +class CustomerAsset(proto.Message): + r"""A link between a customer and an asset. + + Attributes: + resource_name (str): + Immutable. The resource name of the customer asset. + CustomerAsset resource names have the form: + + ``customers/{customer_id}/customerAssets/{asset_id}~{field_type}`` + asset (str): + Required. Immutable. The asset which is + linked to the customer. + field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + Required. Immutable. Role that the asset + takes for the customer link. + source (google.ads.googleads.v24.enums.types.AssetSourceEnum.AssetSource): + Output only. Source of the customer asset + link. + status (google.ads.googleads.v24.enums.types.AssetLinkStatusEnum.AssetLinkStatus): + Status of the customer asset. + primary_status (google.ads.googleads.v24.enums.types.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus): + Output only. Provides the PrimaryStatus of + this asset link. Primary status is meant + essentially to differentiate between the plain + "status" field, which has advertiser set values + of enabled, paused, or removed. The primary + status takes into account other signals (for + assets its mainly policy and quality approvals) + to come up with a more comprehensive status to + indicate its serving state. + primary_status_details (MutableSequence[google.ads.googleads.v24.common.types.AssetLinkPrimaryStatusDetails]): + Output only. Provides the details of the + primary status and its associated reasons. + primary_status_reasons (MutableSequence[google.ads.googleads.v24.enums.types.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason]): + Output only. Provides a list of reasons for + why an asset is not serving or not serving at + full capacity. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + asset: str = proto.Field( + proto.STRING, + number=2, + ) + field_type: asset_field_type.AssetFieldTypeEnum.AssetFieldType = ( + proto.Field( + proto.ENUM, + number=3, + enum=asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + ) + source: asset_source.AssetSourceEnum.AssetSource = proto.Field( + proto.ENUM, + number=5, + enum=asset_source.AssetSourceEnum.AssetSource, + ) + status: asset_link_status.AssetLinkStatusEnum.AssetLinkStatus = proto.Field( + proto.ENUM, + number=4, + enum=asset_link_status.AssetLinkStatusEnum.AssetLinkStatus, + ) + primary_status: ( + asset_link_primary_status.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus + ) = proto.Field( + proto.ENUM, + number=6, + enum=asset_link_primary_status.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus, + ) + primary_status_details: MutableSequence[ + asset_policy.AssetLinkPrimaryStatusDetails + ] = proto.RepeatedField( + proto.MESSAGE, + number=7, + message=asset_policy.AssetLinkPrimaryStatusDetails, + ) + primary_status_reasons: MutableSequence[ + asset_link_primary_status_reason.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason + ] = proto.RepeatedField( + proto.ENUM, + number=8, + enum=asset_link_primary_status_reason.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer_asset_set.py b/google/ads/googleads/v24/resources/types/customer_asset_set.py new file mode 100644 index 000000000..ee9f626e7 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer_asset_set.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import asset_set_link_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerAssetSet", + }, +) + + +class CustomerAssetSet(proto.Message): + r"""CustomerAssetSet is the linkage between a customer and an + asset set. Adding a CustomerAssetSet links an asset set with a + customer. + + Attributes: + resource_name (str): + Immutable. The resource name of the customer asset set. + Asset set asset resource names have the form: + + ``customers/{customer_id}/customerAssetSets/{asset_set_id}`` + asset_set (str): + Immutable. The asset set which is linked to + the customer. + customer (str): + Immutable. The customer to which this asset + set is linked. + status (google.ads.googleads.v24.enums.types.AssetSetLinkStatusEnum.AssetSetLinkStatus): + Output only. The status of the customer asset + set asset. Read-only. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + asset_set: str = proto.Field( + proto.STRING, + number=2, + ) + customer: str = proto.Field( + proto.STRING, + number=3, + ) + status: asset_set_link_status.AssetSetLinkStatusEnum.AssetSetLinkStatus = ( + proto.Field( + proto.ENUM, + number=4, + enum=asset_set_link_status.AssetSetLinkStatusEnum.AssetSetLinkStatus, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer_client.py b/google/ads/googleads/v24/resources/types/customer_client.py new file mode 100644 index 000000000..e9702e38a --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer_client.py @@ -0,0 +1,168 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import customer_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerClient", + }, +) + + +class CustomerClient(proto.Message): + r"""A link between the given customer and a client customer. + CustomerClients only exist for manager customers. All direct and + indirect client customers are included, as well as the manager + itself. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the customer client. + CustomerClient resource names have the form: + ``customers/{customer_id}/customerClients/{client_customer_id}`` + client_customer (str): + Output only. The resource name of the + client-customer which is linked to the given + customer. Read only. + + This field is a member of `oneof`_ ``_client_customer``. + hidden (bool): + Output only. Specifies whether this is a `hidden + account `__. + Read only. + + This field is a member of `oneof`_ ``_hidden``. + level (int): + Output only. Distance between given customer + and client. For self link, the level value will + be 0. Read only. + + This field is a member of `oneof`_ ``_level``. + time_zone (str): + Output only. Common Locale Data Repository (CLDR) string + representation of the time zone of the client, for example, + America/Los_Angeles. Read only. + + This field is a member of `oneof`_ ``_time_zone``. + test_account (bool): + Output only. Identifies if the client is a + test account. Read only. + + This field is a member of `oneof`_ ``_test_account``. + manager (bool): + Output only. Identifies if the client is a + manager. Read only. + + This field is a member of `oneof`_ ``_manager``. + descriptive_name (str): + Output only. Descriptive name for the client. + Read only. + + This field is a member of `oneof`_ ``_descriptive_name``. + currency_code (str): + Output only. Currency code (for example, + 'USD', 'EUR') for the client. Read only. + + This field is a member of `oneof`_ ``_currency_code``. + id (int): + Output only. The ID of the client customer. + Read only. + + This field is a member of `oneof`_ ``_id``. + applied_labels (MutableSequence[str]): + Output only. The resource names of the labels owned by the + requesting customer that are applied to the client customer. + Label resource names have the form: + + ``customers/{customer_id}/labels/{label_id}`` + status (google.ads.googleads.v24.enums.types.CustomerStatusEnum.CustomerStatus): + Output only. The status of the client + customer. Read only. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + client_customer: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + hidden: bool = proto.Field( + proto.BOOL, + number=13, + optional=True, + ) + level: int = proto.Field( + proto.INT64, + number=14, + optional=True, + ) + time_zone: str = proto.Field( + proto.STRING, + number=15, + optional=True, + ) + test_account: bool = proto.Field( + proto.BOOL, + number=16, + optional=True, + ) + manager: bool = proto.Field( + proto.BOOL, + number=17, + optional=True, + ) + descriptive_name: str = proto.Field( + proto.STRING, + number=18, + optional=True, + ) + currency_code: str = proto.Field( + proto.STRING, + number=19, + optional=True, + ) + id: int = proto.Field( + proto.INT64, + number=20, + optional=True, + ) + applied_labels: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=21, + ) + status: customer_status.CustomerStatusEnum.CustomerStatus = proto.Field( + proto.ENUM, + number=22, + enum=customer_status.CustomerStatusEnum.CustomerStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer_client_link.py b/google/ads/googleads/v24/resources/types/customer_client_link.py new file mode 100644 index 000000000..d80ac8caa --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer_client_link.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import manager_link_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerClientLink", + }, +) + + +class CustomerClientLink(proto.Message): + r"""Represents customer client link relationship. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. Name of the resource. CustomerClientLink resource + names have the form: + ``customers/{customer_id}/customerClientLinks/{client_customer_id}~{manager_link_id}`` + client_customer (str): + Immutable. The client customer linked to this + customer. + + This field is a member of `oneof`_ ``_client_customer``. + manager_link_id (int): + Output only. This is uniquely identifies a + customer client link. Read only. + + This field is a member of `oneof`_ ``_manager_link_id``. + status (google.ads.googleads.v24.enums.types.ManagerLinkStatusEnum.ManagerLinkStatus): + This is the status of the link between client + and manager. + hidden (bool): + The visibility of the link. Users can choose + whether or not to see hidden links in the Google + Ads UI. Default value is false + + This field is a member of `oneof`_ ``_hidden``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + client_customer: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + manager_link_id: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + status: manager_link_status.ManagerLinkStatusEnum.ManagerLinkStatus = ( + proto.Field( + proto.ENUM, + number=5, + enum=manager_link_status.ManagerLinkStatusEnum.ManagerLinkStatus, + ) + ) + hidden: bool = proto.Field( + proto.BOOL, + number=9, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer_conversion_goal.py b/google/ads/googleads/v24/resources/types/customer_conversion_goal.py new file mode 100644 index 000000000..77561c02b --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer_conversion_goal.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import conversion_action_category +from google.ads.googleads.v24.enums.types import conversion_origin + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerConversionGoal", + }, +) + + +class CustomerConversionGoal(proto.Message): + r"""Biddability control for conversion actions with a matching + category and origin. + + Attributes: + resource_name (str): + Immutable. The resource name of the customer conversion + goal. Customer conversion goal resource names have the form: + + ``customers/{customer_id}/customerConversionGoals/{category}~{origin}`` + category (google.ads.googleads.v24.enums.types.ConversionActionCategoryEnum.ConversionActionCategory): + The conversion category of this customer + conversion goal. Only conversion actions that + have this category will be included in this + goal. + origin (google.ads.googleads.v24.enums.types.ConversionOriginEnum.ConversionOrigin): + The conversion origin of this customer + conversion goal. Only conversion actions that + have this conversion origin will be included in + this goal. + biddable (bool): + The biddability of the customer conversion + goal. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + category: ( + conversion_action_category.ConversionActionCategoryEnum.ConversionActionCategory + ) = proto.Field( + proto.ENUM, + number=2, + enum=conversion_action_category.ConversionActionCategoryEnum.ConversionActionCategory, + ) + origin: conversion_origin.ConversionOriginEnum.ConversionOrigin = ( + proto.Field( + proto.ENUM, + number=3, + enum=conversion_origin.ConversionOriginEnum.ConversionOrigin, + ) + ) + biddable: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer_customizer.py b/google/ads/googleads/v24/resources/types/customer_customizer.py new file mode 100644 index 000000000..d1d8368fb --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer_customizer.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import customizer_value +from google.ads.googleads.v24.enums.types import customizer_value_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerCustomizer", + }, +) + + +class CustomerCustomizer(proto.Message): + r"""A customizer value for the associated CustomizerAttribute at + the Customer level. + + Attributes: + resource_name (str): + Immutable. The resource name of the customer customizer. + Customer customizer resource names have the form: + + ``customers/{customer_id}/customerCustomizers/{customizer_attribute_id}`` + customizer_attribute (str): + Required. Immutable. The customizer attribute + which is linked to the customer. + status (google.ads.googleads.v24.enums.types.CustomizerValueStatusEnum.CustomizerValueStatus): + Output only. The status of the customer + customizer attribute. + value (google.ads.googleads.v24.common.types.CustomizerValue): + Required. The value to associate with the + customizer attribute at this level. The value + must be of the type specified for the + CustomizerAttribute. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + customizer_attribute: str = proto.Field( + proto.STRING, + number=2, + ) + status: ( + customizer_value_status.CustomizerValueStatusEnum.CustomizerValueStatus + ) = proto.Field( + proto.ENUM, + number=3, + enum=customizer_value_status.CustomizerValueStatusEnum.CustomizerValueStatus, + ) + value: customizer_value.CustomizerValue = proto.Field( + proto.MESSAGE, + number=4, + message=customizer_value.CustomizerValue, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer_label.py b/google/ads/googleads/v24/resources/types/customer_label.py new file mode 100644 index 000000000..d93abf7f6 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer_label.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerLabel", + }, +) + + +class CustomerLabel(proto.Message): + r"""Represents a relationship between a customer and a label. + This customer may not have access to all the labels attached to + it. Additional CustomerLabels may be returned by increasing + permissions with login-customer-id. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. Name of the resource. Customer label resource + names have the form: + ``customers/{customer_id}/customerLabels/{label_id}`` + customer (str): + Output only. The resource name of the customer to which the + label is attached. This field should not be set when + creating a new ``CustomerLabel``. + + This field is a member of `oneof`_ ``_customer``. + label (str): + Output only. The resource name of the label assigned to the + customer. This field should not be set when creating a new + ``CustomerLabel``. + + Note: the Customer ID portion of the label resource name is + not validated when creating a new ``CustomerLabel``. + + This field is a member of `oneof`_ ``_label``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + customer: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + label: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer_lifecycle_goal.py b/google/ads/googleads/v24/resources/types/customer_lifecycle_goal.py new file mode 100644 index 000000000..2359ab710 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer_lifecycle_goal.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import lifecycle_goals + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerLifecycleGoal", + }, +) + + +class CustomerLifecycleGoal(proto.Message): + r"""Account level customer lifecycle goal settings. + + Attributes: + resource_name (str): + Immutable. The resource name of the customer lifecycle goal. + Customer lifecycle resource names have the form: + + ``customers/{customer_id}/customerLifecycleGoal`` + customer_acquisition_goal_value_settings (google.ads.googleads.v24.common.types.LifecycleGoalValueSettings): + Output only. Customer acquisition goal + customer level value settings. + owner_customer (str): + Output only. The resource name of the + customer which owns the lifecycle goal. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + customer_acquisition_goal_value_settings: ( + lifecycle_goals.LifecycleGoalValueSettings + ) = proto.Field( + proto.MESSAGE, + number=3, + message=lifecycle_goals.LifecycleGoalValueSettings, + ) + owner_customer: str = proto.Field( + proto.STRING, + number=4, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer_manager_link.py b/google/ads/googleads/v24/resources/types/customer_manager_link.py new file mode 100644 index 000000000..ae8da5426 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer_manager_link.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import manager_link_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerManagerLink", + }, +) + + +class CustomerManagerLink(proto.Message): + r"""Represents customer-manager link relationship. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. Name of the resource. CustomerManagerLink + resource names have the form: + ``customers/{customer_id}/customerManagerLinks/{manager_customer_id}~{manager_link_id}`` + manager_customer (str): + Output only. The manager customer linked to + the customer. + + This field is a member of `oneof`_ ``_manager_customer``. + manager_link_id (int): + Output only. ID of the customer-manager link. + This field is read only. + + This field is a member of `oneof`_ ``_manager_link_id``. + status (google.ads.googleads.v24.enums.types.ManagerLinkStatusEnum.ManagerLinkStatus): + Status of the link between the customer and + the manager. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + manager_customer: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + manager_link_id: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + status: manager_link_status.ManagerLinkStatusEnum.ManagerLinkStatus = ( + proto.Field( + proto.ENUM, + number=5, + enum=manager_link_status.ManagerLinkStatusEnum.ManagerLinkStatus, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer_negative_criterion.py b/google/ads/googleads/v24/resources/types/customer_negative_criterion.py new file mode 100644 index 000000000..1928feb04 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer_negative_criterion.py @@ -0,0 +1,168 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.enums.types import criterion_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerNegativeCriterion", + }, +) + + +class CustomerNegativeCriterion(proto.Message): + r"""A negative criterion for exclusions at the customer level. + + 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: + resource_name (str): + Immutable. The resource name of the customer negative + criterion. Customer negative criterion resource names have + the form: + + ``customers/{customer_id}/customerNegativeCriteria/{criterion_id}`` + id (int): + Output only. The ID of the criterion. + + This field is a member of `oneof`_ ``_id``. + type_ (google.ads.googleads.v24.enums.types.CriterionTypeEnum.CriterionType): + Output only. The type of the criterion. + content_label (google.ads.googleads.v24.common.types.ContentLabelInfo): + Immutable. ContentLabel. + + This field is a member of `oneof`_ ``criterion``. + mobile_application (google.ads.googleads.v24.common.types.MobileApplicationInfo): + Immutable. MobileApplication. + + This field is a member of `oneof`_ ``criterion``. + mobile_app_category (google.ads.googleads.v24.common.types.MobileAppCategoryInfo): + Immutable. MobileAppCategory. + + This field is a member of `oneof`_ ``criterion``. + placement (google.ads.googleads.v24.common.types.PlacementInfo): + Immutable. Placement. + + This field is a member of `oneof`_ ``criterion``. + youtube_video (google.ads.googleads.v24.common.types.YouTubeVideoInfo): + Immutable. YouTube Video. + + This field is a member of `oneof`_ ``criterion``. + youtube_channel (google.ads.googleads.v24.common.types.YouTubeChannelInfo): + Immutable. YouTube Channel. + + This field is a member of `oneof`_ ``criterion``. + negative_keyword_list (google.ads.googleads.v24.common.types.NegativeKeywordListInfo): + Immutable. NegativeKeywordList. + + This field is a member of `oneof`_ ``criterion``. + ip_block (google.ads.googleads.v24.common.types.IpBlockInfo): + Immutable. IpBlock. + + You can exclude up to 500 IP addresses per + account. + + This field is a member of `oneof`_ ``criterion``. + placement_list (google.ads.googleads.v24.common.types.PlacementListInfo): + Immutable. PlacementList. + + This field is a member of `oneof`_ ``criterion``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=10, + optional=True, + ) + type_: criterion_type.CriterionTypeEnum.CriterionType = proto.Field( + proto.ENUM, + number=3, + enum=criterion_type.CriterionTypeEnum.CriterionType, + ) + content_label: criteria.ContentLabelInfo = proto.Field( + proto.MESSAGE, + number=4, + oneof="criterion", + message=criteria.ContentLabelInfo, + ) + mobile_application: criteria.MobileApplicationInfo = proto.Field( + proto.MESSAGE, + number=5, + oneof="criterion", + message=criteria.MobileApplicationInfo, + ) + mobile_app_category: criteria.MobileAppCategoryInfo = proto.Field( + proto.MESSAGE, + number=6, + oneof="criterion", + message=criteria.MobileAppCategoryInfo, + ) + placement: criteria.PlacementInfo = proto.Field( + proto.MESSAGE, + number=7, + oneof="criterion", + message=criteria.PlacementInfo, + ) + youtube_video: criteria.YouTubeVideoInfo = proto.Field( + proto.MESSAGE, + number=8, + oneof="criterion", + message=criteria.YouTubeVideoInfo, + ) + youtube_channel: criteria.YouTubeChannelInfo = proto.Field( + proto.MESSAGE, + number=9, + oneof="criterion", + message=criteria.YouTubeChannelInfo, + ) + negative_keyword_list: criteria.NegativeKeywordListInfo = proto.Field( + proto.MESSAGE, + number=11, + oneof="criterion", + message=criteria.NegativeKeywordListInfo, + ) + ip_block: criteria.IpBlockInfo = proto.Field( + proto.MESSAGE, + number=12, + oneof="criterion", + message=criteria.IpBlockInfo, + ) + placement_list: criteria.PlacementListInfo = proto.Field( + proto.MESSAGE, + number=13, + oneof="criterion", + message=criteria.PlacementListInfo, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer_search_term_insight.py b/google/ads/googleads/v24/resources/types/customer_search_term_insight.py new file mode 100644 index 000000000..cb2e63210 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer_search_term_insight.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerSearchTermInsight", + }, +) + + +class CustomerSearchTermInsight(proto.Message): + r"""This report provides a high-level view of search demand at + the customer level by grouping similar search terms into + categories and showing their search volume. + Historical data is available starting March 2023. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the customer level search + term insight. Customer level search term insight resource + names have the form: + + ``customers/{customer_id}/customerSearchTermInsights/{category_id}`` + category_label (str): + Output only. The label for the search + category. An empty string denotes the catch-all + category for search terms that didn't fit into + another category. + + This field is a member of `oneof`_ ``_category_label``. + id (int): + Output only. The ID of the insight. + + This field is a member of `oneof`_ ``_id``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + category_label: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + id: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer_sk_ad_network_conversion_value_schema.py b/google/ads/googleads/v24/resources/types/customer_sk_ad_network_conversion_value_schema.py new file mode 100644 index 000000000..3a4410835 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer_sk_ad_network_conversion_value_schema.py @@ -0,0 +1,374 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + sk_ad_network_coarse_conversion_value, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerSkAdNetworkConversionValueSchema", + }, +) + + +class CustomerSkAdNetworkConversionValueSchema(proto.Message): + r"""A CustomerSkAdNetworkConversionValueSchema. + + Attributes: + resource_name (str): + Output only. The resource name of the schema. + CustomerSkAdNetworkConversionValueSchema resource names have + the form: + customers/{customer_id}/customerSkAdNetworkConversionValueSchemas/{account_link_id} + schema (google.ads.googleads.v24.resources.types.CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema): + Output only. The schema for the specified + resource. + """ + + class SkAdNetworkConversionValueSchema(proto.Message): + r"""The CustomerLink specific SkAdNetworkConversionValueSchema. + + Attributes: + app_id (str): + Required. Output only. Apple App Store app + ID. + measurement_window_hours (int): + Output only. A time window (measured in hours) post-install, + after which the App Attribution Partner or advertiser stops + calling [updateConversionValue] + (https://developer.apple.com/documentation/storekit/skadnetwork/3566697-updateconversionvalue). + fine_grained_conversion_value_mappings (MutableSequence[google.ads.googleads.v24.resources.types.CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.FineGrainedConversionValueMappings]): + Output only. Fine grained conversion value + mappings. For SkAdNetwork versions >= 4.0 that + support multiple conversion windows, fine + grained conversion value mappings are only + applicable to the first postback. + postback_mappings (MutableSequence[google.ads.googleads.v24.resources.types.CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.PostbackMapping]): + Output only. Per-postback conversion value + mappings for postbacks in multiple conversion + windows. Only applicable for SkAdNetwork + versions >= 4.0. + """ + + class FineGrainedConversionValueMappings(proto.Message): + r"""Mappings for fine grained conversion value. + + Attributes: + fine_grained_conversion_value (int): + Output only. Fine grained conversion value. Valid values are + in the inclusive range [0,63]. + conversion_value_mapping (google.ads.googleads.v24.resources.types.CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.ConversionValueMapping): + Output only. Conversion events the fine + grained conversion value maps to. + """ + + fine_grained_conversion_value: int = proto.Field( + proto.INT32, + number=1, + ) + conversion_value_mapping: "CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.ConversionValueMapping" = proto.Field( + proto.MESSAGE, + number=2, + message="CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.ConversionValueMapping", + ) + + class PostbackMapping(proto.Message): + r"""Mappings for each postback in multiple conversion windows. + + 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: + postback_sequence_index (int): + Output only. 0-based index that indicates the order of + postback. Valid values are in the inclusive range [0,2]. + coarse_grained_conversion_value_mappings (google.ads.googleads.v24.resources.types.CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.CoarseGrainedConversionValueMappings): + Output only. Conversion value mappings for + all coarse grained conversion values. + lock_window_coarse_conversion_value (google.ads.googleads.v24.enums.types.SkAdNetworkCoarseConversionValueEnum.SkAdNetworkCoarseConversionValue): + Output only. Coarse grained conversion value + that triggers conversion window lock. + + This field is a member of `oneof`_ ``lock_window_trigger``. + lock_window_fine_conversion_value (int): + Output only. Fine grained conversion value + that triggers conversion window lock. + + This field is a member of `oneof`_ ``lock_window_trigger``. + lock_window_event (str): + Output only. Event name that triggers + conversion window lock. + + This field is a member of `oneof`_ ``lock_window_trigger``. + """ + + postback_sequence_index: int = proto.Field( + proto.INT32, + number=1, + ) + coarse_grained_conversion_value_mappings: "CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.CoarseGrainedConversionValueMappings" = proto.Field( + proto.MESSAGE, + number=2, + message="CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.CoarseGrainedConversionValueMappings", + ) + lock_window_coarse_conversion_value: ( + sk_ad_network_coarse_conversion_value.SkAdNetworkCoarseConversionValueEnum.SkAdNetworkCoarseConversionValue + ) = proto.Field( + proto.ENUM, + number=3, + oneof="lock_window_trigger", + enum=sk_ad_network_coarse_conversion_value.SkAdNetworkCoarseConversionValueEnum.SkAdNetworkCoarseConversionValue, + ) + lock_window_fine_conversion_value: int = proto.Field( + proto.INT32, + number=4, + oneof="lock_window_trigger", + ) + lock_window_event: str = proto.Field( + proto.STRING, + number=5, + oneof="lock_window_trigger", + ) + + class CoarseGrainedConversionValueMappings(proto.Message): + r"""Mappings for coarse grained conversion values. + + Attributes: + low_conversion_value_mapping (google.ads.googleads.v24.resources.types.CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.ConversionValueMapping): + Output only. Mapping for "low" coarse + conversion value. + medium_conversion_value_mapping (google.ads.googleads.v24.resources.types.CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.ConversionValueMapping): + Output only. Mapping for "medium" coarse + conversion value. + high_conversion_value_mapping (google.ads.googleads.v24.resources.types.CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.ConversionValueMapping): + Output only. Mapping for "high" coarse + conversion value. + """ + + low_conversion_value_mapping: "CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.ConversionValueMapping" = proto.Field( + proto.MESSAGE, + number=1, + message="CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.ConversionValueMapping", + ) + medium_conversion_value_mapping: "CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.ConversionValueMapping" = proto.Field( + proto.MESSAGE, + number=2, + message="CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.ConversionValueMapping", + ) + high_conversion_value_mapping: "CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.ConversionValueMapping" = proto.Field( + proto.MESSAGE, + number=3, + message="CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.ConversionValueMapping", + ) + + class ConversionValueMapping(proto.Message): + r"""Represents mapping from one conversion value to one or more + conversion events. + + Attributes: + min_time_post_install_hours (int): + Output only. The minimum of the time range in + which a user was last active during the + measurement window. + max_time_post_install_hours (int): + Output only. The maximum of the time range in + which a user was last active during the + measurement window. + mapped_events (MutableSequence[google.ads.googleads.v24.resources.types.CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.Event]): + Output only. The conversion value may be + mapped to multiple events with various + attributes. + """ + + min_time_post_install_hours: int = proto.Field( + proto.INT64, + number=1, + ) + max_time_post_install_hours: int = proto.Field( + proto.INT64, + number=2, + ) + mapped_events: MutableSequence[ + "CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.Event" + ] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.Event", + ) + + class Event(proto.Message): + r"""Defines a Google conversion event that the conversion value + is mapped to. + + 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: + mapped_event_name (str): + Output only. Google event name represented by + this conversion value. + currency_code (str): + Output only. The reported currency for the event_revenue. + ISO 4217 three-letter currency code, for example, "USD". + event_revenue_range (google.ads.googleads.v24.resources.types.CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.Event.RevenueRange): + Output only. The event revenue range. + + This field is a member of `oneof`_ ``revenue_rate``. + event_revenue_value (float): + Output only. The specific event revenue + value. + + This field is a member of `oneof`_ ``revenue_rate``. + event_occurrence_range (google.ads.googleads.v24.resources.types.CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.Event.EventOccurrenceRange): + Output only. The event counter range. + + This field is a member of `oneof`_ ``event_rate``. + event_counter (int): + Output only. For specific event counter + values. + + This field is a member of `oneof`_ ``event_rate``. + """ + + class RevenueRange(proto.Message): + r"""Defines a range for revenue values. + + Attributes: + min_event_revenue (float): + Output only. For revenue ranges, the minimum value in + ``currency_code`` for which this conversion value would be + updated. A value of 0 will be treated as unset. + max_event_revenue (float): + Output only. For revenue ranges, the maximum value in + ``currency_code`` for which this conversion value would be + updated. A value of 0 will be treated as unset. + """ + + min_event_revenue: float = proto.Field( + proto.DOUBLE, + number=3, + ) + max_event_revenue: float = proto.Field( + proto.DOUBLE, + number=4, + ) + + class EventOccurrenceRange(proto.Message): + r"""Defines a range for event counter values. + + Attributes: + min_event_count (int): + Output only. For event counter ranges, the + minimum of the defined range. A value of 0 will + be treated as unset. + max_event_count (int): + Output only. For event counter ranges, the + maximum of the defined range. A value of 0 will + be treated as unset. + """ + + min_event_count: int = proto.Field( + proto.INT64, + number=1, + ) + max_event_count: int = proto.Field( + proto.INT64, + number=2, + ) + + mapped_event_name: str = proto.Field( + proto.STRING, + number=1, + ) + currency_code: str = proto.Field( + proto.STRING, + number=2, + ) + event_revenue_range: "CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.Event.RevenueRange" = proto.Field( + proto.MESSAGE, + number=3, + oneof="revenue_rate", + message="CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.Event.RevenueRange", + ) + event_revenue_value: float = proto.Field( + proto.DOUBLE, + number=4, + oneof="revenue_rate", + ) + event_occurrence_range: "CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.Event.EventOccurrenceRange" = proto.Field( + proto.MESSAGE, + number=5, + oneof="event_rate", + message="CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.Event.EventOccurrenceRange", + ) + event_counter: int = proto.Field( + proto.INT64, + number=6, + oneof="event_rate", + ) + + app_id: str = proto.Field( + proto.STRING, + number=1, + ) + measurement_window_hours: int = proto.Field( + proto.INT32, + number=2, + ) + fine_grained_conversion_value_mappings: MutableSequence[ + "CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.FineGrainedConversionValueMappings" + ] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.FineGrainedConversionValueMappings", + ) + postback_mappings: MutableSequence[ + "CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.PostbackMapping" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.PostbackMapping", + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + schema: SkAdNetworkConversionValueSchema = proto.Field( + proto.MESSAGE, + number=2, + message=SkAdNetworkConversionValueSchema, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer_user_access.py b/google/ads/googleads/v24/resources/types/customer_user_access.py new file mode 100644 index 000000000..07549abd4 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer_user_access.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import access_role as gage_access_role + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerUserAccess", + }, +) + + +class CustomerUserAccess(proto.Message): + r"""Represents the permission of a single user onto a single + customer. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. Name of the resource. Resource names have the + form: + ``customers/{customer_id}/customerUserAccesses/{user_id}`` + user_id (int): + Output only. User id of the user with the + customer access. Read only field + email_address (str): + Output only. Email address of the user. + Read only field + + This field is a member of `oneof`_ ``_email_address``. + access_role (google.ads.googleads.v24.enums.types.AccessRoleEnum.AccessRole): + Access role of the user. + access_creation_date_time (str): + Output only. The customer user access + creation time. Read only field + The format is "YYYY-MM-DD HH:MM:SS". + Examples: "2018-03-05 09:15:00" or "2018-02-01 + 14:34:30". + + This field is a member of `oneof`_ ``_access_creation_date_time``. + inviter_user_email_address (str): + Output only. The email address of the inviter + user. Read only field + + This field is a member of `oneof`_ ``_inviter_user_email_address``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + user_id: int = proto.Field( + proto.INT64, + number=2, + ) + email_address: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + access_role: gage_access_role.AccessRoleEnum.AccessRole = proto.Field( + proto.ENUM, + number=4, + enum=gage_access_role.AccessRoleEnum.AccessRole, + ) + access_creation_date_time: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + inviter_user_email_address: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customer_user_access_invitation.py b/google/ads/googleads/v24/resources/types/customer_user_access_invitation.py new file mode 100644 index 000000000..1eae534da --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customer_user_access_invitation.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import access_invitation_status +from google.ads.googleads.v24.enums.types import access_role as gage_access_role + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerUserAccessInvitation", + }, +) + + +class CustomerUserAccessInvitation(proto.Message): + r"""Represent an invitation to a new user on this customer + account. + + Attributes: + resource_name (str): + Immutable. Name of the resource. Resource names have the + form: + ``customers/{customer_id}/customerUserAccessInvitations/{invitation_id}`` + invitation_id (int): + Output only. The ID of the invitation. + This field is read-only. + access_role (google.ads.googleads.v24.enums.types.AccessRoleEnum.AccessRole): + Immutable. Access role of the user. + email_address (str): + Immutable. Email address the invitation was + sent to. This can differ from the email address + of the account that accepts the invite. + creation_date_time (str): + Output only. Time invitation was created. + This field is read-only. + The format is "YYYY-MM-DD HH:MM:SS". + Examples: "2018-03-05 09:15:00" or "2018-02-01 + 14:34:30". + invitation_status (google.ads.googleads.v24.enums.types.AccessInvitationStatusEnum.AccessInvitationStatus): + Output only. Invitation status of the user. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + invitation_id: int = proto.Field( + proto.INT64, + number=2, + ) + access_role: gage_access_role.AccessRoleEnum.AccessRole = proto.Field( + proto.ENUM, + number=3, + enum=gage_access_role.AccessRoleEnum.AccessRole, + ) + email_address: str = proto.Field( + proto.STRING, + number=4, + ) + creation_date_time: str = proto.Field( + proto.STRING, + number=5, + ) + invitation_status: ( + access_invitation_status.AccessInvitationStatusEnum.AccessInvitationStatus + ) = proto.Field( + proto.ENUM, + number=6, + enum=access_invitation_status.AccessInvitationStatusEnum.AccessInvitationStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/customizer_attribute.py b/google/ads/googleads/v24/resources/types/customizer_attribute.py new file mode 100644 index 000000000..52204b2a6 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/customizer_attribute.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import customizer_attribute_status +from google.ads.googleads.v24.enums.types import customizer_attribute_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "CustomizerAttribute", + }, +) + + +class CustomizerAttribute(proto.Message): + r"""A customizer attribute. + Use CustomerCustomizer, CampaignCustomizer, AdGroupCustomizer, + or AdGroupCriterionCustomizer to associate a customizer + attribute and set its value at the customer, campaign, ad group, + or ad group criterion level, respectively. + + Attributes: + resource_name (str): + Immutable. The resource name of the customizer attribute. + Customizer Attribute resource names have the form: + + ``customers/{customer_id}/customizerAttributes/{customizer_attribute_id}`` + id (int): + Output only. The ID of the customizer + attribute. + name (str): + Required. Immutable. Name of the customizer + attribute. Required. It must have a minimum + length of 1 and maximum length of 40. Name of an + enabled customizer attribute must be unique + (case insensitive). + type_ (google.ads.googleads.v24.enums.types.CustomizerAttributeTypeEnum.CustomizerAttributeType): + Immutable. The type of the customizer + attribute. + status (google.ads.googleads.v24.enums.types.CustomizerAttributeStatusEnum.CustomizerAttributeStatus): + Output only. The status of the customizer + attribute. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + ) + name: str = proto.Field( + proto.STRING, + number=3, + ) + type_: ( + customizer_attribute_type.CustomizerAttributeTypeEnum.CustomizerAttributeType + ) = proto.Field( + proto.ENUM, + number=4, + enum=customizer_attribute_type.CustomizerAttributeTypeEnum.CustomizerAttributeType, + ) + status: ( + customizer_attribute_status.CustomizerAttributeStatusEnum.CustomizerAttributeStatus + ) = proto.Field( + proto.ENUM, + number=5, + enum=customizer_attribute_status.CustomizerAttributeStatusEnum.CustomizerAttributeStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/data_link.py b/google/ads/googleads/v24/resources/types/data_link.py new file mode 100644 index 000000000..5dbe7d5a3 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/data_link.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import data_link_status +from google.ads.googleads.v24.enums.types import data_link_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "DataLink", + "YoutubeVideoIdentifier", + }, +) + + +class DataLink(proto.Message): + r"""Represents the data sharing connection between a Google + Ads customer and another product's data. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. Resource name of the product data link. DataLink + resource names have the form: + + \`customers/{customer_id}/datalinks/{product_link_id}~{data_link_id}} + product_link_id (int): + Output only. The ID of the link. + This field is read only. + + This field is a member of `oneof`_ ``_product_link_id``. + data_link_id (int): + Output only. The ID of the data link. + This field is read only. + + This field is a member of `oneof`_ ``_data_link_id``. + type_ (google.ads.googleads.v24.enums.types.DataLinkTypeEnum.DataLinkType): + Output only. The type of the data. + status (google.ads.googleads.v24.enums.types.DataLinkStatusEnum.DataLinkStatus): + Output only. The status of the data link. + youtube_video (google.ads.googleads.v24.resources.types.YoutubeVideoIdentifier): + Immutable. A data link to YouTube video. + + This field is a member of `oneof`_ ``data_link_entity``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + product_link_id: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + data_link_id: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + type_: data_link_type.DataLinkTypeEnum.DataLinkType = proto.Field( + proto.ENUM, + number=4, + enum=data_link_type.DataLinkTypeEnum.DataLinkType, + ) + status: data_link_status.DataLinkStatusEnum.DataLinkStatus = proto.Field( + proto.ENUM, + number=5, + enum=data_link_status.DataLinkStatusEnum.DataLinkStatus, + ) + youtube_video: "YoutubeVideoIdentifier" = proto.Field( + proto.MESSAGE, + number=6, + oneof="data_link_entity", + message="YoutubeVideoIdentifier", + ) + + +class YoutubeVideoIdentifier(proto.Message): + r"""The identifier for YouTube video + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + channel_id (str): + Immutable. The ID of the hosting channel of + the video. This is a string value with “UC” + prefix. For example, "UCK8sQmJBp8GCxrOtXWBpyEA". + + This field is a member of `oneof`_ ``_channel_id``. + video_id (str): + Immutable. The ID of the video associated + with the video link. This is the 11 character + string value used in the YouTube video URL. For + example, video ID is jV1vkHv4zq8 from the + YouTube video URL + "https://www.youtube.com/watch?v=jV1vkHv4zq8&t=2s". + + This field is a member of `oneof`_ ``_video_id``. + """ + + channel_id: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + video_id: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/detail_content_suitability_placement_view.py b/google/ads/googleads/v24/resources/types/detail_content_suitability_placement_view.py new file mode 100644 index 000000000..e90f67163 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/detail_content_suitability_placement_view.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + placement_type as gage_placement_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "DetailContentSuitabilityPlacementView", + }, +) + + +class DetailContentSuitabilityPlacementView(proto.Message): + r"""A detail content suitability placement view. + + Attributes: + resource_name (str): + Output only. The resource name of the detail content + suitability placement view. Detail content suitability + placement view resource names have the form: + + ``customers/{customer_id}/detailContentSuitabilityPlacementViews/{placement_fingerprint}`` + display_name (str): + Output only. The display name is URL for + websites, YouTube video name for YouTube videos, + and translated mobile app name for mobile apps. + placement (str): + Output only. The automatic placement string + at detail level, for example. website url, + mobile application id, or a YouTube video id. + placement_type (google.ads.googleads.v24.enums.types.PlacementTypeEnum.PlacementType): + Output only. Represents the type of the + placement, for example, Website, YouTubeVideo + and MobileApplication. + target_url (str): + Output only. URL of the placement, for + example, website, link to the mobile application + in app store, or a YouTube video URL. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + display_name: str = proto.Field( + proto.STRING, + number=2, + ) + placement: str = proto.Field( + proto.STRING, + number=3, + ) + placement_type: gage_placement_type.PlacementTypeEnum.PlacementType = ( + proto.Field( + proto.ENUM, + number=4, + enum=gage_placement_type.PlacementTypeEnum.PlacementType, + ) + ) + target_url: str = proto.Field( + proto.STRING, + number=5, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/detail_placement_view.py b/google/ads/googleads/v24/resources/types/detail_placement_view.py new file mode 100644 index 000000000..c4512fd21 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/detail_placement_view.py @@ -0,0 +1,117 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + placement_type as gage_placement_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "DetailPlacementView", + }, +) + + +class DetailPlacementView(proto.Message): + r"""A view with metrics aggregated by ad group and URL or YouTube video. + + This view primarily surfaces placement data from the Google Display + Network. While you can select segments like + ``segments.ad_network_type``, this view generally does not include + placement data from other networks, such as the Search Partners + network. To understand performance on Search Partners, consider + other reports and segmentations. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the detail placement view. + Detail placement view resource names have the form: + + ``customers/{customer_id}/detailPlacementViews/{ad_group_id}~{base64_placement}`` + placement (str): + Output only. The automatic placement string + at detail level, e. g. website URL, mobile + application ID, or a YouTube video ID. + + This field is a member of `oneof`_ ``_placement``. + display_name (str): + Output only. The display name is URL name for + websites, YouTube video name for YouTube videos, + and translated mobile app name for mobile apps. + + This field is a member of `oneof`_ ``_display_name``. + group_placement_target_url (str): + Output only. URL of the group placement, for + example, domain, link to the mobile application + in app store, or a YouTube channel URL. + + This field is a member of `oneof`_ ``_group_placement_target_url``. + target_url (str): + Output only. URL of the placement, for + example, website, link to the mobile application + in app store, or a YouTube video URL. + + This field is a member of `oneof`_ ``_target_url``. + placement_type (google.ads.googleads.v24.enums.types.PlacementTypeEnum.PlacementType): + Output only. Type of the placement, for + example, Website, YouTube Video, and Mobile + Application. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + placement: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + display_name: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + group_placement_target_url: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + target_url: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + placement_type: gage_placement_type.PlacementTypeEnum.PlacementType = ( + proto.Field( + proto.ENUM, + number=6, + enum=gage_placement_type.PlacementTypeEnum.PlacementType, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/detailed_demographic.py b/google/ads/googleads/v24/resources/types/detailed_demographic.py new file mode 100644 index 000000000..e581ce3d4 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/detailed_demographic.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import ( + criterion_category_availability, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "DetailedDemographic", + }, +) + + +class DetailedDemographic(proto.Message): + r"""A detailed demographic: a particular interest-based vertical + to be targeted to reach users based on long-term life facts. + + Attributes: + resource_name (str): + Output only. The resource name of the detailed demographic. + Detailed demographic resource names have the form: + + ``customers/{customer_id}/detailedDemographics/{detailed_demographic_id}`` + id (int): + Output only. The ID of the detailed + demographic. + name (str): + Output only. The name of the detailed + demographic. For example,"Highest Level of + Educational Attainment". + parent (str): + Output only. The parent of the detailed_demographic. + launched_to_all (bool): + Output only. True if the detailed demographic + is launched to all channels and locales. + availabilities (MutableSequence[google.ads.googleads.v24.common.types.CriterionCategoryAvailability]): + Output only. Availability information of the + detailed demographic. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + ) + name: str = proto.Field( + proto.STRING, + number=3, + ) + parent: str = proto.Field( + proto.STRING, + number=4, + ) + launched_to_all: bool = proto.Field( + proto.BOOL, + number=5, + ) + availabilities: MutableSequence[ + criterion_category_availability.CriterionCategoryAvailability + ] = proto.RepeatedField( + proto.MESSAGE, + number=6, + message=criterion_category_availability.CriterionCategoryAvailability, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/display_keyword_view.py b/google/ads/googleads/v24/resources/types/display_keyword_view.py new file mode 100644 index 000000000..bdf60c107 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/display_keyword_view.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "DisplayKeywordView", + }, +) + + +class DisplayKeywordView(proto.Message): + r"""A display keyword view. + + Provides performance data for keywords used in Display Network + campaigns. This view lets you analyze how your display keywords are + performing across various segments. + + This view is primarily used to track the effectiveness of keyword + targeting within your Display campaigns. To understand which network + the metrics apply to, you can select the + ``segments.ad_network_type`` field in your query. This field will + segment the data by networks such as the Google Display Network, + YouTube, Gmail, and so on. + + You can select fields from this resource along with metrics like + impressions, clicks, and conversions to gauge performance. + Attributed resources like ``ad_group`` and ``campaign`` can also be + selected without segmenting metrics. + + Attributes: + resource_name (str): + Output only. The resource name of the display keyword view. + Display Keyword view resource names have the form: + + ``customers/{customer_id}/displayKeywordViews/{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/distance_view.py b/google/ads/googleads/v24/resources/types/distance_view.py new file mode 100644 index 000000000..d9a31e30c --- /dev/null +++ b/google/ads/googleads/v24/resources/types/distance_view.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + distance_bucket as gage_distance_bucket, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "DistanceView", + }, +) + + +class DistanceView(proto.Message): + r"""A distance view with metrics aggregated by the user's + distance from an advertiser's location extensions. Each + DistanceBucket includes all impressions that fall within its + distance and a single impression will contribute to the metrics + for all DistanceBuckets that include the user's distance. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the distance view. + Distance view resource names have the form: + + ``customers/{customer_id}/distanceViews/1~{distance_bucket}`` + distance_bucket (google.ads.googleads.v24.enums.types.DistanceBucketEnum.DistanceBucket): + Output only. Grouping of user distance from + location extensions. + metric_system (bool): + Output only. True if the DistanceBucket is + using the metric system, false otherwise. + + This field is a member of `oneof`_ ``_metric_system``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + distance_bucket: gage_distance_bucket.DistanceBucketEnum.DistanceBucket = ( + proto.Field( + proto.ENUM, + number=2, + enum=gage_distance_bucket.DistanceBucketEnum.DistanceBucket, + ) + ) + metric_system: bool = proto.Field( + proto.BOOL, + number=4, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/domain_category.py b/google/ads/googleads/v24/resources/types/domain_category.py new file mode 100644 index 000000000..1baf2148d --- /dev/null +++ b/google/ads/googleads/v24/resources/types/domain_category.py @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "DomainCategory", + }, +) + + +class DomainCategory(proto.Message): + r"""A category generated automatically by crawling a domain. If a + campaign uses the DynamicSearchAdsSetting, then domain + categories will be generated for the domain. The categories can + be targeted using WebpageConditionInfo. See: + https://support.google.com/google-ads/answer/2471185 + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the domain category. + Domain category resource names have the form: + + ``customers/{customer_id}/domainCategories/{campaign_id}~{category_base64}~{language_code}`` + campaign (str): + Output only. The campaign this category is + recommended for. + + This field is a member of `oneof`_ ``_campaign``. + category (str): + Output only. Recommended category for the + website domain, for example, if you have a + website about electronics, the categories could + be "cameras", "televisions", etc. + + This field is a member of `oneof`_ ``_category``. + language_code (str): + Output only. The language code specifying the + language of the website, for example, "en" for + English. The language can be specified in the + DynamicSearchAdsSetting required for dynamic + search ads. This is the language of the pages + from your website that you want Google Ads to + find, create ads for, and match searches with. + + This field is a member of `oneof`_ ``_language_code``. + domain (str): + Output only. The domain for the website. The + domain can be specified in the + DynamicSearchAdsSetting required for dynamic + search ads. + + This field is a member of `oneof`_ ``_domain``. + coverage_fraction (float): + Output only. Fraction of pages on your site + that this category matches. + + This field is a member of `oneof`_ ``_coverage_fraction``. + category_rank (int): + Output only. The position of this category in + the set of categories. Lower numbers indicate a + better match for the domain. null indicates not + recommended. + + This field is a member of `oneof`_ ``_category_rank``. + has_children (bool): + Output only. Indicates whether this category + has sub-categories. + + This field is a member of `oneof`_ ``_has_children``. + recommended_cpc_bid_micros (int): + Output only. The recommended cost per click + for the category. + + This field is a member of `oneof`_ ``_recommended_cpc_bid_micros``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + category: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + language_code: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + domain: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + coverage_fraction: float = proto.Field( + proto.DOUBLE, + number=14, + optional=True, + ) + category_rank: int = proto.Field( + proto.INT64, + number=15, + optional=True, + ) + has_children: bool = proto.Field( + proto.BOOL, + number=16, + optional=True, + ) + recommended_cpc_bid_micros: int = proto.Field( + proto.INT64, + number=17, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/dynamic_search_ads_search_term_view.py b/google/ads/googleads/v24/resources/types/dynamic_search_ads_search_term_view.py new file mode 100644 index 000000000..c047ae67a --- /dev/null +++ b/google/ads/googleads/v24/resources/types/dynamic_search_ads_search_term_view.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "DynamicSearchAdsSearchTermView", + }, +) + + +class DynamicSearchAdsSearchTermView(proto.Message): + r"""A dynamic search ads search term view. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the dynamic search ads + search term view. Dynamic search ads search term view + resource names have the form: + + ``customers/{customer_id}/dynamicSearchAdsSearchTermViews/{ad_group_id}~{search_term_fingerprint}~{headline_fingerprint}~{landing_page_fingerprint}~{page_url_fingerprint}`` + search_term (str): + Output only. Search term + + This field is read-only. + + This field is a member of `oneof`_ ``_search_term``. + headline (str): + Output only. The dynamically generated + headline of the Dynamic Search Ad. + This field is read-only. + + This field is a member of `oneof`_ ``_headline``. + landing_page (str): + Output only. The dynamically selected landing + page URL of the impression. + This field is read-only. + + This field is a member of `oneof`_ ``_landing_page``. + page_url (str): + Output only. The URL of page feed item served + for the impression. + This field is read-only. + + This field is a member of `oneof`_ ``_page_url``. + has_negative_keyword (bool): + Output only. True if query matches a negative + keyword. + This field is read-only. + + This field is a member of `oneof`_ ``_has_negative_keyword``. + has_matching_keyword (bool): + Output only. True if query is added to + targeted keywords. + This field is read-only. + + This field is a member of `oneof`_ ``_has_matching_keyword``. + has_negative_url (bool): + Output only. True if query matches a negative + url. + This field is read-only. + + This field is a member of `oneof`_ ``_has_negative_url``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + search_term: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + headline: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + landing_page: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + page_url: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + has_negative_keyword: bool = proto.Field( + proto.BOOL, + number=13, + optional=True, + ) + has_matching_keyword: bool = proto.Field( + proto.BOOL, + number=14, + optional=True, + ) + has_negative_url: bool = proto.Field( + proto.BOOL, + number=15, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/expanded_landing_page_view.py b/google/ads/googleads/v24/resources/types/expanded_landing_page_view.py new file mode 100644 index 000000000..e095a41f3 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/expanded_landing_page_view.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ExpandedLandingPageView", + }, +) + + +class ExpandedLandingPageView(proto.Message): + r"""A landing page view with metrics aggregated at the expanded + final URL level. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the expanded landing page + view. Expanded landing page view resource names have the + form: + + ``customers/{customer_id}/expandedLandingPageViews/{expanded_final_url_fingerprint}`` + expanded_final_url (str): + Output only. The final URL that clicks are + directed to. + + This field is a member of `oneof`_ ``_expanded_final_url``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + expanded_final_url: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/experiment.py b/google/ads/googleads/v24/resources/types/experiment.py new file mode 100644 index 000000000..2a359aad1 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/experiment.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import metric_goal +from google.ads.googleads.v24.enums.types import async_action_status +from google.ads.googleads.v24.enums.types import experiment_status +from google.ads.googleads.v24.enums.types import experiment_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "Experiment", + }, +) + + +class Experiment(proto.Message): + r"""A Google ads experiment for users to experiment changes on + multiple campaigns, compare the performance, and apply the + effective changes. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the experiment. Experiment + resource names have the form: + + ``customers/{customer_id}/experiments/{experiment_id}`` + experiment_id (int): + Output only. The ID of the experiment. Read + only. + + This field is a member of `oneof`_ ``_experiment_id``. + name (str): + Required. The name of the experiment. It must + have a minimum length of 1 and maximum length of + 1024. It must be unique under a customer. + description (str): + The description of the experiment. It must + have a minimum length of 1 and maximum length of + 2048. + suffix (str): + For system managed experiments, the + advertiser must provide a suffix during + construction, in the setup stage before moving + to initiated. The suffix will be appended to the + in-design and experiment campaign names so that + the name is base campaign name + suffix. + type_ (google.ads.googleads.v24.enums.types.ExperimentTypeEnum.ExperimentType): + Required. The product/feature that uses this + experiment. + status (google.ads.googleads.v24.enums.types.ExperimentStatusEnum.ExperimentStatus): + The Advertiser-chosen status of this + experiment. + start_date (str): + Date when the experiment starts. By default, + the experiment starts now or on the campaign's + start date, whichever is later. If this field is + set, then the experiment starts at the beginning + of the specified date in the customer's time + zone. + + Format: YYYY-MM-DD + Example: 2019-03-14 + + This field is a member of `oneof`_ ``_start_date``. + end_date (str): + Date when the experiment ends. By default, + the experiment ends on the campaign's end date. + If this field is set, then the experiment ends + at the end of the specified date in the + customer's time zone. + + Format: YYYY-MM-DD + Example: 2019-04-18 + + This field is a member of `oneof`_ ``_end_date``. + goals (MutableSequence[google.ads.googleads.v24.common.types.MetricGoal]): + The goals of this experiment. + long_running_operation (str): + Output only. The resource name of the + long-running operation that can be used to poll + for completion of experiment schedule or + promote. The most recent long running operation + is returned. + + This field is a member of `oneof`_ ``_long_running_operation``. + promote_status (google.ads.googleads.v24.enums.types.AsyncActionStatusEnum.AsyncActionStatus): + Output only. The status of the experiment + promotion process. + sync_enabled (bool): + Immutable. Set to true if changes to base + campaigns should be synced to the trial + campaigns. Any changes made directly to trial + campaigns will be preserved. This field can only + be set when the experiment is being created. + + This field is a member of `oneof`_ ``_sync_enabled``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + experiment_id: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=10, + ) + description: str = proto.Field( + proto.STRING, + number=11, + ) + suffix: str = proto.Field( + proto.STRING, + number=12, + ) + type_: experiment_type.ExperimentTypeEnum.ExperimentType = proto.Field( + proto.ENUM, + number=13, + enum=experiment_type.ExperimentTypeEnum.ExperimentType, + ) + status: experiment_status.ExperimentStatusEnum.ExperimentStatus = ( + proto.Field( + proto.ENUM, + number=14, + enum=experiment_status.ExperimentStatusEnum.ExperimentStatus, + ) + ) + start_date: str = proto.Field( + proto.STRING, + number=15, + optional=True, + ) + end_date: str = proto.Field( + proto.STRING, + number=16, + optional=True, + ) + goals: MutableSequence[metric_goal.MetricGoal] = proto.RepeatedField( + proto.MESSAGE, + number=17, + message=metric_goal.MetricGoal, + ) + long_running_operation: str = proto.Field( + proto.STRING, + number=18, + optional=True, + ) + promote_status: ( + async_action_status.AsyncActionStatusEnum.AsyncActionStatus + ) = proto.Field( + proto.ENUM, + number=19, + enum=async_action_status.AsyncActionStatusEnum.AsyncActionStatus, + ) + sync_enabled: bool = proto.Field( + proto.BOOL, + number=20, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/experiment_arm.py b/google/ads/googleads/v24/resources/types/experiment_arm.py new file mode 100644 index 000000000..7de2c189c --- /dev/null +++ b/google/ads/googleads/v24/resources/types/experiment_arm.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ExperimentArm", + }, +) + + +class ExperimentArm(proto.Message): + r"""A Google ads experiment for users to experiment changes on + multiple campaigns, compare the performance, and apply the + effective changes. + + Attributes: + resource_name (str): + Immutable. The resource name of the experiment arm. + Experiment arm resource names have the form: + + ``customers/{customer_id}/experimentArms/{TrialArm.trial_id}~{TrialArm.trial_arm_id}`` + experiment (str): + Immutable. The experiment to which the + ExperimentArm belongs. + name (str): + Required. The name of the experiment arm. It + must have a minimum length of 1 and maximum + length of 1024. It must be unique under an + experiment. + control (bool): + Whether this arm is a control arm. A control + arm is the arm against which the other arms are + compared. + traffic_split (int): + Traffic split of the trial arm. The value + should be between 1 and 100 and must total 100 + between the two trial arms. + campaigns (MutableSequence[str]): + List of campaigns in the trial arm. The max + length is one. + in_design_campaigns (MutableSequence[str]): + Output only. The in design campaigns in the + treatment experiment arm. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + experiment: str = proto.Field( + proto.STRING, + number=8, + ) + name: str = proto.Field( + proto.STRING, + number=3, + ) + control: bool = proto.Field( + proto.BOOL, + number=4, + ) + traffic_split: int = proto.Field( + proto.INT64, + number=5, + ) + campaigns: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=6, + ) + in_design_campaigns: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=7, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/final_url_expansion_asset_view.py b/google/ads/googleads/v24/resources/types/final_url_expansion_asset_view.py new file mode 100644 index 000000000..b87d560c5 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/final_url_expansion_asset_view.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import asset_field_type +from google.ads.googleads.v24.enums.types import asset_link_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "FinalUrlExpansionAssetView", + }, +) + + +class FinalUrlExpansionAssetView(proto.Message): + r"""FinalUrlExpansionAssetView Resource. + + 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: + resource_name (str): + Output only. The resource name of the + FinalUrlExpansionAsset. + campaign (str): + Output only. Campaign in which the asset + served. + + This field is a member of `oneof`_ ``_campaign``. + asset (str): + Output only. The ID of the asset. + + This field is a member of `oneof`_ ``_asset``. + field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + Output only. The field type of the asset. + status (google.ads.googleads.v24.enums.types.AssetLinkStatusEnum.AssetLinkStatus): + Output only. Status of the + FinalUrlExpansionAsset. + + This field is a member of `oneof`_ ``_status``. + final_url (str): + Output only. Final URL of the + FinalUrlExpansionAsset. + ad_group (str): + Output only. Ad Group in which + FinalUrlExpansionAsset served. + + This field is a member of `oneof`_ ``level``. + asset_group (str): + Output only. Asset Group in which + FinalUrlExpansionAsset served. + + This field is a member of `oneof`_ ``level``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + asset: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + field_type: asset_field_type.AssetFieldTypeEnum.AssetFieldType = ( + proto.Field( + proto.ENUM, + number=4, + enum=asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + ) + status: asset_link_status.AssetLinkStatusEnum.AssetLinkStatus = proto.Field( + proto.ENUM, + number=5, + optional=True, + enum=asset_link_status.AssetLinkStatusEnum.AssetLinkStatus, + ) + final_url: str = proto.Field( + proto.STRING, + number=6, + ) + ad_group: str = proto.Field( + proto.STRING, + number=7, + oneof="level", + ) + asset_group: str = proto.Field( + proto.STRING, + number=8, + oneof="level", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/gender_view.py b/google/ads/googleads/v24/resources/types/gender_view.py new file mode 100644 index 000000000..abd23badd --- /dev/null +++ b/google/ads/googleads/v24/resources/types/gender_view.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "GenderView", + }, +) + + +class GenderView(proto.Message): + r"""A gender view. The gender_view resource reflects the effective + serving state, rather than what criteria were added. An ad group + without gender criteria by default shows to all genders, so all + genders appear in gender_view with stats. + + Attributes: + resource_name (str): + Output only. The resource name of the gender view. Gender + view resource names have the form: + + ``customers/{customer_id}/genderViews/{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/geo_target_constant.py b/google/ads/googleads/v24/resources/types/geo_target_constant.py new file mode 100644 index 000000000..7234450bc --- /dev/null +++ b/google/ads/googleads/v24/resources/types/geo_target_constant.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import geo_target_constant_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "GeoTargetConstant", + }, +) + + +class GeoTargetConstant(proto.Message): + r"""A geo target constant. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the geo target constant. + Geo target constant resource names have the form: + + ``geoTargetConstants/{geo_target_constant_id}`` + id (int): + Output only. The ID of the geo target + constant. + + This field is a member of `oneof`_ ``_id``. + name (str): + Output only. Geo target constant English + name. + + This field is a member of `oneof`_ ``_name``. + country_code (str): + Output only. The ISO-3166-1 alpha-2 country + code that is associated with the target. + + This field is a member of `oneof`_ ``_country_code``. + target_type (str): + Output only. Geo target constant target type. + + This field is a member of `oneof`_ ``_target_type``. + status (google.ads.googleads.v24.enums.types.GeoTargetConstantStatusEnum.GeoTargetConstantStatus): + Output only. Geo target constant status. + canonical_name (str): + Output only. The fully qualified English + name, consisting of the target's name and that + of its parent and country. + + This field is a member of `oneof`_ ``_canonical_name``. + parent_geo_target (str): + Output only. The resource name of the parent geo target + constant. Geo target constant resource names have the form: + + ``geoTargetConstants/{parent_geo_target_constant_id}`` + + This field is a member of `oneof`_ ``_parent_geo_target``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=10, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + country_code: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + target_type: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + status: ( + geo_target_constant_status.GeoTargetConstantStatusEnum.GeoTargetConstantStatus + ) = proto.Field( + proto.ENUM, + number=7, + enum=geo_target_constant_status.GeoTargetConstantStatusEnum.GeoTargetConstantStatus, + ) + canonical_name: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + parent_geo_target: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/geographic_view.py b/google/ads/googleads/v24/resources/types/geographic_view.py new file mode 100644 index 000000000..5b9fbaf18 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/geographic_view.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import geo_targeting_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "GeographicView", + }, +) + + +class GeographicView(proto.Message): + r"""A geographic view. + + Geographic View includes all metrics aggregated at the country + level, one row per country. It reports metrics at either actual + physical location of the user or an area of interest. If other + segment fields are used, you may get more than one row per + country. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the geographic view. + Geographic view resource names have the form: + + ``customers/{customer_id}/geographicViews/{country_criterion_id}~{location_type}`` + location_type (google.ads.googleads.v24.enums.types.GeoTargetingTypeEnum.GeoTargetingType): + Output only. Type of the geo targeting of the + campaign. + country_criterion_id (int): + Output only. Criterion Id for the country. + + This field is a member of `oneof`_ ``_country_criterion_id``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + location_type: geo_targeting_type.GeoTargetingTypeEnum.GeoTargetingType = ( + proto.Field( + proto.ENUM, + number=3, + enum=geo_targeting_type.GeoTargetingTypeEnum.GeoTargetingType, + ) + ) + country_criterion_id: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/goal.py b/google/ads/googleads/v24/resources/types/goal.py new file mode 100644 index 000000000..c99dcecc3 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/goal.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import goal_setting +from google.ads.googleads.v24.enums.types import goal_optimization_eligibility +from google.ads.googleads.v24.enums.types import goal_type as gage_goal_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "Goal", + }, +) + + +class Goal(proto.Message): + r"""Representation of goals. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the goal. Goal resource + names have the form: + ``customers/{customer_id}/goals/{goal_id}`` + goal_id (int): + Output only. The ID of this goal. + + This field is a member of `oneof`_ ``_goal_id``. + goal_type (google.ads.googleads.v24.enums.types.GoalTypeEnum.GoalType): + Output only. The type of this goal. + owner_customer (str): + Output only. The resource name of the goal + owner customer. + + This field is a member of `oneof`_ ``_owner_customer``. + optimization_eligibility (google.ads.googleads.v24.enums.types.GoalOptimizationEligibilityEnum.GoalOptimizationEligibility): + Output only. Indicates if this goal is + eligible for campaign optimization. + retention_goal_settings (google.ads.googleads.v24.common.types.GoalSetting.RetentionGoal): + Retention goal settings. + + This field is a member of `oneof`_ ``goal_settings``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + goal_id: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + goal_type: gage_goal_type.GoalTypeEnum.GoalType = proto.Field( + proto.ENUM, + number=3, + enum=gage_goal_type.GoalTypeEnum.GoalType, + ) + owner_customer: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + optimization_eligibility: ( + goal_optimization_eligibility.GoalOptimizationEligibilityEnum.GoalOptimizationEligibility + ) = proto.Field( + proto.ENUM, + number=6, + enum=goal_optimization_eligibility.GoalOptimizationEligibilityEnum.GoalOptimizationEligibility, + ) + retention_goal_settings: goal_setting.GoalSetting.RetentionGoal = ( + proto.Field( + proto.MESSAGE, + number=7, + oneof="goal_settings", + message=goal_setting.GoalSetting.RetentionGoal, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/google_ads_field.py b/google/ads/googleads/v24/resources/types/google_ads_field.py new file mode 100644 index 000000000..a263fd01b --- /dev/null +++ b/google/ads/googleads/v24/resources/types/google_ads_field.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import google_ads_field_category +from google.ads.googleads.v24.enums.types import google_ads_field_data_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "GoogleAdsField", + }, +) + + +class GoogleAdsField(proto.Message): + r"""A field or resource (artifact) used by GoogleAdsService. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the artifact. Artifact + resource names have the form: + + ``googleAdsFields/{name}`` + name (str): + Output only. The name of the artifact. + + This field is a member of `oneof`_ ``_name``. + category (google.ads.googleads.v24.enums.types.GoogleAdsFieldCategoryEnum.GoogleAdsFieldCategory): + Output only. The category of the artifact. + selectable (bool): + Output only. Whether the artifact can be used + in a SELECT clause in search queries. + + This field is a member of `oneof`_ ``_selectable``. + filterable (bool): + Output only. Whether the artifact can be used + in a WHERE clause in search queries. + + This field is a member of `oneof`_ ``_filterable``. + sortable (bool): + Output only. Whether the artifact can be used + in a ORDER BY clause in search queries. + + This field is a member of `oneof`_ ``_sortable``. + selectable_with (MutableSequence[str]): + Output only. The names of all resources, + segments, and metrics that are selectable with + the described artifact. + attribute_resources (MutableSequence[str]): + Output only. The names of all resources that + are selectable with the described artifact. + Fields from these resources do not segment + metrics when included in search queries. + + This field is only set for artifacts whose + category is RESOURCE. + metrics (MutableSequence[str]): + Output only. This field lists the names of + all metrics that are selectable with the + described artifact when it is used in the FROM + clause. It is only set for artifacts whose + category is RESOURCE. + segments (MutableSequence[str]): + Output only. This field lists the names of + all artifacts, whether a segment or another + resource, that segment metrics when included in + search queries and when the described artifact + is used in the FROM clause. It is only set for + artifacts whose category is RESOURCE. + enum_values (MutableSequence[str]): + Output only. Values the artifact can assume + if it is a field of type ENUM. + This field is only set for artifacts of category + SEGMENT or ATTRIBUTE. + data_type (google.ads.googleads.v24.enums.types.GoogleAdsFieldDataTypeEnum.GoogleAdsFieldDataType): + Output only. This field determines the + operators that can be used with the artifact in + WHERE clauses. + type_url (str): + Output only. The URL of proto describing the + artifact's data type. + + This field is a member of `oneof`_ ``_type_url``. + is_repeated (bool): + Output only. Whether the field artifact is + repeated. + + This field is a member of `oneof`_ ``_is_repeated``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + name: str = proto.Field( + proto.STRING, + number=21, + optional=True, + ) + category: ( + google_ads_field_category.GoogleAdsFieldCategoryEnum.GoogleAdsFieldCategory + ) = proto.Field( + proto.ENUM, + number=3, + enum=google_ads_field_category.GoogleAdsFieldCategoryEnum.GoogleAdsFieldCategory, + ) + selectable: bool = proto.Field( + proto.BOOL, + number=22, + optional=True, + ) + filterable: bool = proto.Field( + proto.BOOL, + number=23, + optional=True, + ) + sortable: bool = proto.Field( + proto.BOOL, + number=24, + optional=True, + ) + selectable_with: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=25, + ) + attribute_resources: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=26, + ) + metrics: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=27, + ) + segments: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=28, + ) + enum_values: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=29, + ) + data_type: ( + google_ads_field_data_type.GoogleAdsFieldDataTypeEnum.GoogleAdsFieldDataType + ) = proto.Field( + proto.ENUM, + number=12, + enum=google_ads_field_data_type.GoogleAdsFieldDataTypeEnum.GoogleAdsFieldDataType, + ) + type_url: str = proto.Field( + proto.STRING, + number=30, + optional=True, + ) + is_repeated: bool = proto.Field( + proto.BOOL, + number=31, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/group_content_suitability_placement_view.py b/google/ads/googleads/v24/resources/types/group_content_suitability_placement_view.py new file mode 100644 index 000000000..84e341878 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/group_content_suitability_placement_view.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + placement_type as gage_placement_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "GroupContentSuitabilityPlacementView", + }, +) + + +class GroupContentSuitabilityPlacementView(proto.Message): + r"""A group content suitability placement view. + + Attributes: + resource_name (str): + Output only. The resource name of the group content + suitability placement view. Group content suitability + placement view resource names have the form: + + ``customers/{customer_id}/groupContentSuitabilityPlacementViews/{placement_fingerprint}`` + display_name (str): + Output only. The display name is URL for + websites, YouTube video name for YouTube videos, + and translated mobile app name for mobile apps. + placement (str): + Output only. The automatic placement string + at group level, for example. website url, mobile + application id, or a YouTube video id. + placement_type (google.ads.googleads.v24.enums.types.PlacementTypeEnum.PlacementType): + Output only. Represents the type of the + placement, for example, Website, YouTubeVideo + and MobileApplication. + target_url (str): + Output only. URL of the placement, for + example, website, link to the mobile application + in app store, or a YouTube video URL. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + display_name: str = proto.Field( + proto.STRING, + number=2, + ) + placement: str = proto.Field( + proto.STRING, + number=3, + ) + placement_type: gage_placement_type.PlacementTypeEnum.PlacementType = ( + proto.Field( + proto.ENUM, + number=4, + enum=gage_placement_type.PlacementTypeEnum.PlacementType, + ) + ) + target_url: str = proto.Field( + proto.STRING, + number=5, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/group_placement_view.py b/google/ads/googleads/v24/resources/types/group_placement_view.py new file mode 100644 index 000000000..de5d4e0ff --- /dev/null +++ b/google/ads/googleads/v24/resources/types/group_placement_view.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + placement_type as gage_placement_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "GroupPlacementView", + }, +) + + +class GroupPlacementView(proto.Message): + r"""A group placement view. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the group placement view. + Group placement view resource names have the form: + + ``customers/{customer_id}/groupPlacementViews/{ad_group_id}~{base64_placement}`` + placement (str): + Output only. The automatic placement string + at group level, e. g. web domain, mobile app ID, + or a YouTube channel ID. + + This field is a member of `oneof`_ ``_placement``. + display_name (str): + Output only. Domain name for websites and + YouTube channel name for YouTube channels. + + This field is a member of `oneof`_ ``_display_name``. + target_url (str): + Output only. URL of the group placement, for + example, domain, link to the mobile application + in app store, or a YouTube channel URL. + + This field is a member of `oneof`_ ``_target_url``. + placement_type (google.ads.googleads.v24.enums.types.PlacementTypeEnum.PlacementType): + Output only. Type of the placement, for + example, Website, YouTube Channel, Mobile + Application. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + placement: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + display_name: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + target_url: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + placement_type: gage_placement_type.PlacementTypeEnum.PlacementType = ( + proto.Field( + proto.ENUM, + number=5, + enum=gage_placement_type.PlacementTypeEnum.PlacementType, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/hotel_group_view.py b/google/ads/googleads/v24/resources/types/hotel_group_view.py new file mode 100644 index 000000000..0526b5806 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/hotel_group_view.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "HotelGroupView", + }, +) + + +class HotelGroupView(proto.Message): + r"""A hotel group view. + + Attributes: + resource_name (str): + Output only. The resource name of the hotel group view. + Hotel Group view resource names have the form: + + ``customers/{customer_id}/hotelGroupViews/{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/hotel_performance_view.py b/google/ads/googleads/v24/resources/types/hotel_performance_view.py new file mode 100644 index 000000000..5e0fa66c6 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/hotel_performance_view.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "HotelPerformanceView", + }, +) + + +class HotelPerformanceView(proto.Message): + r"""A hotel performance view. + + Attributes: + resource_name (str): + Output only. The resource name of the hotel performance + view. Hotel performance view resource names have the form: + + ``customers/{customer_id}/hotelPerformanceView`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/hotel_reconciliation.py b/google/ads/googleads/v24/resources/types/hotel_reconciliation.py new file mode 100644 index 000000000..6e3cec9cb --- /dev/null +++ b/google/ads/googleads/v24/resources/types/hotel_reconciliation.py @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import hotel_reconciliation_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "HotelReconciliation", + }, +) + + +class HotelReconciliation(proto.Message): + r"""A hotel reconciliation. It contains conversion information + from Hotel bookings to reconcile with advertiser records. These + rows may be updated or canceled before billing through Bulk + Uploads. + + Attributes: + resource_name (str): + Immutable. The resource name of the hotel reconciliation. + Hotel reconciliation resource names have the form: + + ``customers/{customer_id}/hotelReconciliations/{commission_id}`` + commission_id (str): + Required. Output only. The commission ID is + Google's ID for this booking. Every booking + event is assigned a Commission ID to help you + match it to a guest stay. + order_id (str): + Output only. The order ID is the identifier for this booking + as provided in the 'transaction_id' parameter of the + conversion tracking tag. + campaign (str): + Output only. The resource name for the + Campaign associated with the conversion. + hotel_center_id (int): + Output only. Identifier for the Hotel Center + account which provides the rates for the Hotel + campaign. + hotel_id (str): + Output only. Unique identifier for the booked + property, as provided in the Hotel Center feed. + The hotel ID comes from the 'ID' parameter of + the conversion tracking tag. + check_in_date (str): + Output only. Check-in date recorded when the + booking is made. If the check-in date is + modified at reconciliation, the revised date + will then take the place of the original date in + this column. Format is YYYY-MM-DD. + check_out_date (str): + Output only. Check-out date recorded when the + booking is made. If the check-in date is + modified at reconciliation, the revised date + will then take the place of the original date in + this column. Format is YYYY-MM-DD. + reconciled_value_micros (int): + Required. Output only. Reconciled value is + the final value of a booking as paid by the + guest. If original booking value changes for any + reason, such as itinerary changes or room + upsells, the reconciled value should be the full + final amount collected. If a booking is + canceled, the reconciled value should include + the value of any cancellation fees or + non-refundable nights charged. Value is in + millionths of the base unit currency. For + example, $12.35 would be represented as + 12350000. Currency unit is in the default + customer currency. + billed (bool): + Output only. Whether a given booking has been + billed. Once billed, a booking can't be + modified. + status (google.ads.googleads.v24.enums.types.HotelReconciliationStatusEnum.HotelReconciliationStatus): + Required. Output only. Current status of a + booking with regards to reconciliation and + billing. Bookings should be reconciled within 45 + days after the check-out date. Any booking not + reconciled within 45 days will be billed at its + original value. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + commission_id: str = proto.Field( + proto.STRING, + number=2, + ) + order_id: str = proto.Field( + proto.STRING, + number=3, + ) + campaign: str = proto.Field( + proto.STRING, + number=11, + ) + hotel_center_id: int = proto.Field( + proto.INT64, + number=4, + ) + hotel_id: str = proto.Field( + proto.STRING, + number=5, + ) + check_in_date: str = proto.Field( + proto.STRING, + number=6, + ) + check_out_date: str = proto.Field( + proto.STRING, + number=7, + ) + reconciled_value_micros: int = proto.Field( + proto.INT64, + number=8, + ) + billed: bool = proto.Field( + proto.BOOL, + number=9, + ) + status: ( + hotel_reconciliation_status.HotelReconciliationStatusEnum.HotelReconciliationStatus + ) = proto.Field( + proto.ENUM, + number=10, + enum=hotel_reconciliation_status.HotelReconciliationStatusEnum.HotelReconciliationStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/income_range_view.py b/google/ads/googleads/v24/resources/types/income_range_view.py new file mode 100644 index 000000000..81784c240 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/income_range_view.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "IncomeRangeView", + }, +) + + +class IncomeRangeView(proto.Message): + r"""An income range view. + + Attributes: + resource_name (str): + Output only. The resource name of the income range view. + Income range view resource names have the form: + + ``customers/{customer_id}/incomeRangeViews/{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/invoice.py b/google/ads/googleads/v24/resources/types/invoice.py new file mode 100644 index 000000000..f032e4e60 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/invoice.py @@ -0,0 +1,929 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import dates +from google.ads.googleads.v24.enums.types import invoice_type +from google.ads.googleads.v24.enums.types import month_of_year +from google.ads.googleads.v24.enums.types import ( + regulatory_fee_type as gage_regulatory_fee_type, +) +from google.ads.googleads.v24.enums.types import ( + unit_of_measure as gage_unit_of_measure, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "Invoice", + }, +) + + +class Invoice(proto.Message): + r"""An invoice. All invoice information is snapshotted to match + the PDF invoice. For invoices older than the launch of + InvoiceService, the snapshotted information may not match the + PDF invoice. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the invoice. Multiple + customers can share a given invoice, so multiple resource + names may point to the same invoice. Invoice resource names + have the form: + + ``customers/{customer_id}/invoices/{invoice_id}`` + id (str): + Output only. The ID of the invoice. It + appears on the invoice PDF as "Invoice number". + + This field is a member of `oneof`_ ``_id``. + type_ (google.ads.googleads.v24.enums.types.InvoiceTypeEnum.InvoiceType): + Output only. The type of invoice. + billing_setup (str): + Output only. The resource name of this invoice's billing + setup. + + ``customers/{customer_id}/billingSetups/{billing_setup_id}`` + + This field is a member of `oneof`_ ``_billing_setup``. + payments_account_id (str): + Output only. A 16 digit ID used to identify + the payments account associated with the billing + setup, for example, "1234-5678-9012-3456". It + appears on the invoice PDF as "Billing Account + Number". + + This field is a member of `oneof`_ ``_payments_account_id``. + payments_profile_id (str): + Output only. A 12 digit ID used to identify + the payments profile associated with the billing + setup, for example, "1234-5678-9012". It appears + on the invoice PDF as "Billing ID". + + This field is a member of `oneof`_ ``_payments_profile_id``. + issue_date (str): + Output only. The issue date in yyyy-mm-dd + format. It appears on the invoice PDF as either + "Issue date" or "Invoice date". + + This field is a member of `oneof`_ ``_issue_date``. + due_date (str): + Output only. The due date in yyyy-mm-dd + format. + + This field is a member of `oneof`_ ``_due_date``. + service_date_range (google.ads.googleads.v24.common.types.DateRange): + Output only. The service period date range of + this invoice. The end date is inclusive. + currency_code (str): + Output only. The currency code. All costs are + returned in this currency. A subset of the + currency codes derived from the ISO 4217 + standard is supported. + + This field is a member of `oneof`_ ``_currency_code``. + adjustments_subtotal_amount_micros (int): + Output only. The pretax subtotal amount of + invoice level adjustments, in micros. + adjustments_tax_amount_micros (int): + Output only. The sum of taxes on the invoice + level adjustments, in micros. + adjustments_total_amount_micros (int): + Output only. The total amount of invoice + level adjustments, in micros. + regulatory_costs_subtotal_amount_micros (int): + Output only. The pretax subtotal amount of + invoice level regulatory costs, in micros. + regulatory_costs_tax_amount_micros (int): + Output only. The sum of taxes on the invoice + level regulatory costs, in micros. + regulatory_costs_total_amount_micros (int): + Output only. The total amount of invoice + level regulatory costs, in micros. + export_charge_subtotal_amount_micros (int): + Output only. The pretax subtotal amount of + invoice level export charges, in micros. + + This field is a member of `oneof`_ ``_export_charge_subtotal_amount_micros``. + export_charge_tax_amount_micros (int): + Output only. The sum of taxes on the invoice + level export charges, in micros. + + This field is a member of `oneof`_ ``_export_charge_tax_amount_micros``. + export_charge_total_amount_micros (int): + Output only. The total amount of invoice + level export charges, in micros. + + This field is a member of `oneof`_ ``_export_charge_total_amount_micros``. + subtotal_amount_micros (int): + Output only. The pretax subtotal amount, in micros. This is + equal to the sum of the AccountBudgetSummary subtotal + amounts and Invoice.adjustments_subtotal_amount_micros. + + This field is a member of `oneof`_ ``_subtotal_amount_micros``. + tax_amount_micros (int): + Output only. The sum of all taxes on the + invoice, in micros. This equals the sum of the + AccountBudgetSummary tax amounts, plus taxes not + associated with a specific account budget. + + This field is a member of `oneof`_ ``_tax_amount_micros``. + total_amount_micros (int): + Output only. The total amount, in micros. This equals the + sum of Invoice.subtotal_amount_micros, + Invoice.tax_amount_micros, + Invoice.regulatory_costs_subtotal_amount_micros, and + Invoice.export_charge_subtotal_amount_micros (which is + separated into a separate line item starting with V14.1). + + This field is a member of `oneof`_ ``_total_amount_micros``. + corrected_invoice (str): + Output only. The resource name of the original invoice + corrected, wrote off, or canceled by this invoice, if + applicable. If ``corrected_invoice`` is set, + ``replaced_invoices`` will not be set. Invoice resource + names have the form: + + ``customers/{customer_id}/invoices/{invoice_id}`` + + This field is a member of `oneof`_ ``_corrected_invoice``. + replaced_invoices (MutableSequence[str]): + Output only. The resource name of the original invoice(s) + being rebilled or replaced by this invoice, if applicable. + There might be multiple replaced invoices due to invoice + consolidation. The replaced invoices may not belong to the + same payments account. If ``replaced_invoices`` is set, + ``corrected_invoice`` will not be set. Invoice resource + names have the form: + + ``customers/{customer_id}/invoices/{invoice_id}`` + pdf_url (str): + Output only. The URL to a PDF copy of the + invoice. Users need to pass in their OAuth token + to request the PDF with this URL. + + This field is a member of `oneof`_ ``_pdf_url``. + account_budget_summaries (MutableSequence[google.ads.googleads.v24.resources.types.Invoice.AccountBudgetSummary]): + Output only. The list of summarized account + budget information associated with this invoice. + account_summaries (MutableSequence[google.ads.googleads.v24.resources.types.Invoice.AccountSummary]): + Output only. The list of summarized account + information associated with this invoice. + """ + + class AccountSummary(proto.Message): + r"""Represents a summarized view at account level. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer (str): + Output only. The account associated with the + account summary. + + This field is a member of `oneof`_ ``_customer``. + billing_correction_subtotal_amount_micros (int): + Output only. Pretax billing correction + subtotal amount, in micros. + + This field is a member of `oneof`_ ``_billing_correction_subtotal_amount_micros``. + billing_correction_tax_amount_micros (int): + Output only. Tax on billing correction, in + micros. + + This field is a member of `oneof`_ ``_billing_correction_tax_amount_micros``. + billing_correction_total_amount_micros (int): + Output only. Total billing correction amount, + in micros. + + This field is a member of `oneof`_ ``_billing_correction_total_amount_micros``. + coupon_adjustment_subtotal_amount_micros (int): + Output only. Pretax coupon adjustment + subtotal amount, in micros. + + This field is a member of `oneof`_ ``_coupon_adjustment_subtotal_amount_micros``. + coupon_adjustment_tax_amount_micros (int): + Output only. Tax on coupon adjustment, in + micros. + + This field is a member of `oneof`_ ``_coupon_adjustment_tax_amount_micros``. + coupon_adjustment_total_amount_micros (int): + Output only. Total coupon adjustment amount, + in micros. + + This field is a member of `oneof`_ ``_coupon_adjustment_total_amount_micros``. + excess_credit_adjustment_subtotal_amount_micros (int): + Output only. Pretax excess credit adjustment + subtotal amount, in micros. + + This field is a member of `oneof`_ ``_excess_credit_adjustment_subtotal_amount_micros``. + excess_credit_adjustment_tax_amount_micros (int): + Output only. Tax on excess credit adjustment, + in micros. + + This field is a member of `oneof`_ ``_excess_credit_adjustment_tax_amount_micros``. + excess_credit_adjustment_total_amount_micros (int): + Output only. Total excess credit adjustment + amount, in micros. + + This field is a member of `oneof`_ ``_excess_credit_adjustment_total_amount_micros``. + regulatory_costs_subtotal_amount_micros (int): + Output only. Pretax regulatory costs subtotal + amount, in micros. + + This field is a member of `oneof`_ ``_regulatory_costs_subtotal_amount_micros``. + regulatory_costs_tax_amount_micros (int): + Output only. Tax on regulatory costs, in + micros. + + This field is a member of `oneof`_ ``_regulatory_costs_tax_amount_micros``. + regulatory_costs_total_amount_micros (int): + Output only. Total regulatory costs amount, + in micros. + + This field is a member of `oneof`_ ``_regulatory_costs_total_amount_micros``. + export_charge_subtotal_amount_micros (int): + Output only. Pretax export charge subtotal + amount, in micros. + + This field is a member of `oneof`_ ``_export_charge_subtotal_amount_micros``. + export_charge_tax_amount_micros (int): + Output only. Tax on export charge, in micros. + + This field is a member of `oneof`_ ``_export_charge_tax_amount_micros``. + export_charge_total_amount_micros (int): + Output only. Total export charge amount, in + micros. + + This field is a member of `oneof`_ ``_export_charge_total_amount_micros``. + subtotal_amount_micros (int): + Output only. Total pretax subtotal amount + attributable to the account during the service + period, in micros. + + This field is a member of `oneof`_ ``_subtotal_amount_micros``. + tax_amount_micros (int): + Output only. Total tax amount attributable to + the account during the service period, in + micros. + + This field is a member of `oneof`_ ``_tax_amount_micros``. + total_amount_micros (int): + Output only. Total amount attributable to the account during + the service period, in micros. This equals the sum of the + subtotal_amount_micros and tax_amount_micros. + + This field is a member of `oneof`_ ``_total_amount_micros``. + regulatory_cost_summaries (MutableSequence[google.ads.googleads.v24.resources.types.Invoice.RegulatoryCostSummary]): + Output only. The list of regulatory cost + information associated with this account. + adjustment_summaries (MutableSequence[google.ads.googleads.v24.resources.types.Invoice.AdjustmentSummary]): + Output only. The list of adjustment + information associated with this account. + """ + + customer: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + billing_correction_subtotal_amount_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + billing_correction_tax_amount_micros: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + billing_correction_total_amount_micros: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + coupon_adjustment_subtotal_amount_micros: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + coupon_adjustment_tax_amount_micros: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + coupon_adjustment_total_amount_micros: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + excess_credit_adjustment_subtotal_amount_micros: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + excess_credit_adjustment_tax_amount_micros: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + excess_credit_adjustment_total_amount_micros: int = proto.Field( + proto.INT64, + number=10, + optional=True, + ) + regulatory_costs_subtotal_amount_micros: int = proto.Field( + proto.INT64, + number=11, + optional=True, + ) + regulatory_costs_tax_amount_micros: int = proto.Field( + proto.INT64, + number=12, + optional=True, + ) + regulatory_costs_total_amount_micros: int = proto.Field( + proto.INT64, + number=13, + optional=True, + ) + export_charge_subtotal_amount_micros: int = proto.Field( + proto.INT64, + number=17, + optional=True, + ) + export_charge_tax_amount_micros: int = proto.Field( + proto.INT64, + number=18, + optional=True, + ) + export_charge_total_amount_micros: int = proto.Field( + proto.INT64, + number=19, + optional=True, + ) + subtotal_amount_micros: int = proto.Field( + proto.INT64, + number=14, + optional=True, + ) + tax_amount_micros: int = proto.Field( + proto.INT64, + number=15, + optional=True, + ) + total_amount_micros: int = proto.Field( + proto.INT64, + number=16, + optional=True, + ) + regulatory_cost_summaries: MutableSequence[ + "Invoice.RegulatoryCostSummary" + ] = proto.RepeatedField( + proto.MESSAGE, + number=20, + message="Invoice.RegulatoryCostSummary", + ) + adjustment_summaries: MutableSequence["Invoice.AdjustmentSummary"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=21, + message="Invoice.AdjustmentSummary", + ) + ) + + class AccountBudgetSummary(proto.Message): + r"""Represents a summarized account budget billable cost. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer (str): + Output only. The resource name of the customer associated + with this account budget. This contains the customer ID, + which appears on the invoice PDF as "Account ID". Customer + resource names have the form: + + ``customers/{customer_id}`` + + This field is a member of `oneof`_ ``_customer``. + customer_descriptive_name (str): + Output only. The descriptive name of the + account budget's customer. It appears on the + invoice PDF as "Account". + + This field is a member of `oneof`_ ``_customer_descriptive_name``. + account_budget (str): + Output only. The resource name of the account budget + associated with this summarized billable cost. AccountBudget + resource names have the form: + + ``customers/{customer_id}/accountBudgets/{account_budget_id}`` + + This field is a member of `oneof`_ ``_account_budget``. + account_budget_name (str): + Output only. The name of the account budget. + It appears on the invoice PDF as "Account + budget". + + This field is a member of `oneof`_ ``_account_budget_name``. + purchase_order_number (str): + Output only. The purchase order number of the + account budget. It appears on the invoice PDF as + "Purchase order". + + This field is a member of `oneof`_ ``_purchase_order_number``. + subtotal_amount_micros (int): + Output only. The pretax subtotal amount + attributable to this budget during the service + period, in micros. + + This field is a member of `oneof`_ ``_subtotal_amount_micros``. + tax_amount_micros (int): + Output only. The tax amount attributable to + this budget during the service period, in + micros. + + This field is a member of `oneof`_ ``_tax_amount_micros``. + total_amount_micros (int): + Output only. The total amount attributable to + this budget during the service period, in + micros. This equals the sum of the account + budget subtotal amount and the account budget + tax amount. + + This field is a member of `oneof`_ ``_total_amount_micros``. + billable_activity_date_range (google.ads.googleads.v24.common.types.DateRange): + Output only. The billable activity date range + of the account budget, within the service date + range of this invoice. The end date is + inclusive. This can be different from the + account budget's start and end time. + served_amount_micros (int): + Output only. The pretax served amount + attributable to this budget during the service + period, in micros. This is only useful to + reconcile invoice and delivery data. + + This field is a member of `oneof`_ ``_served_amount_micros``. + billed_amount_micros (int): + Output only. The pretax billed amount + attributable to this budget during the service + period, in micros. This does not account for any + adjustments. + + This field is a member of `oneof`_ ``_billed_amount_micros``. + overdelivery_amount_micros (int): + Output only. The pretax overdelivery amount + attributable to this budget during the service + period, in micros (negative value). + + This field is a member of `oneof`_ ``_overdelivery_amount_micros``. + invalid_activity_amount_micros (int): + Output only. The pretax invalid activity + amount attributable to this budget in previous + months, in micros (negative value). + + This field is a member of `oneof`_ ``_invalid_activity_amount_micros``. + invalid_activity_summaries (MutableSequence[google.ads.googleads.v24.resources.types.Invoice.InvalidActivitySummary]): + Output only. The list of summarized invalid + activity credits with original linkages. + campaign_summaries (MutableSequence[google.ads.googleads.v24.resources.types.Invoice.CampaignSummary]): + Output only. The list of summarized campaign + level information associated with this account + budget. + """ + + customer: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + customer_descriptive_name: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + account_budget: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + account_budget_name: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + purchase_order_number: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + subtotal_amount_micros: int = proto.Field( + proto.INT64, + number=15, + optional=True, + ) + tax_amount_micros: int = proto.Field( + proto.INT64, + number=16, + optional=True, + ) + total_amount_micros: int = proto.Field( + proto.INT64, + number=17, + optional=True, + ) + billable_activity_date_range: dates.DateRange = proto.Field( + proto.MESSAGE, + number=9, + message=dates.DateRange, + ) + served_amount_micros: int = proto.Field( + proto.INT64, + number=18, + optional=True, + ) + billed_amount_micros: int = proto.Field( + proto.INT64, + number=19, + optional=True, + ) + overdelivery_amount_micros: int = proto.Field( + proto.INT64, + number=20, + optional=True, + ) + invalid_activity_amount_micros: int = proto.Field( + proto.INT64, + number=21, + optional=True, + ) + invalid_activity_summaries: MutableSequence[ + "Invoice.InvalidActivitySummary" + ] = proto.RepeatedField( + proto.MESSAGE, + number=22, + message="Invoice.InvalidActivitySummary", + ) + campaign_summaries: MutableSequence["Invoice.CampaignSummary"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=23, + message="Invoice.CampaignSummary", + ) + ) + + class InvalidActivitySummary(proto.Message): + r"""Details about the invalid activity for the invoice that + contain additional details about invoice against which + corrections are made. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + original_month_of_service (google.ads.googleads.v24.enums.types.MonthOfYearEnum.MonthOfYear): + Output only. Original month of service + related to this invalid activity credit. + + This field is a member of `oneof`_ ``_original_month_of_service``. + original_year_of_service (str): + Output only. Original year of service related + to this invalid activity credit. + + This field is a member of `oneof`_ ``_original_year_of_service``. + original_invoice_id (str): + Output only. Original invoice number related + to this invalid activity credit. + + This field is a member of `oneof`_ ``_original_invoice_id``. + original_account_budget_name (str): + Output only. Original account budget name + related to this invalid activity credit. + + This field is a member of `oneof`_ ``_original_account_budget_name``. + original_purchase_order_number (str): + Output only. Original purchase order number + related to this invalid activity credit. + + This field is a member of `oneof`_ ``_original_purchase_order_number``. + amount_micros (int): + Output only. Invalid activity amount in + micros. + + This field is a member of `oneof`_ ``_amount_micros``. + """ + + original_month_of_service: month_of_year.MonthOfYearEnum.MonthOfYear = ( + proto.Field( + proto.ENUM, + number=1, + optional=True, + enum=month_of_year.MonthOfYearEnum.MonthOfYear, + ) + ) + original_year_of_service: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + original_invoice_id: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + original_account_budget_name: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + original_purchase_order_number: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + amount_micros: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + + class CampaignSummary(proto.Message): + r"""Represents campaign level billable cost information + associated with an account budget. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + campaign_description (str): + Output only. The description of the campaign. + This is generally the same as the campaign name, + but may differ. + + This field is a member of `oneof`_ ``_campaign_description``. + quantity (int): + Output only. The quantity served for the + given unit of measure. + + This field is a member of `oneof`_ ``_quantity``. + unit_of_measure (google.ads.googleads.v24.enums.types.UnitOfMeasureEnum.UnitOfMeasure): + Output only. The unit of measure for the + quantity served. + + This field is a member of `oneof`_ ``_unit_of_measure``. + amount_micros (int): + Output only. The amount attributable to this campaign for + the given unit of measure during the service period, in + micros. The currency code for this amount is the same as the + Invoice.currency_code. + + This field is a member of `oneof`_ ``_amount_micros``. + """ + + campaign_description: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + quantity: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + unit_of_measure: ( + gage_unit_of_measure.UnitOfMeasureEnum.UnitOfMeasure + ) = proto.Field( + proto.ENUM, + number=3, + optional=True, + enum=gage_unit_of_measure.UnitOfMeasureEnum.UnitOfMeasure, + ) + amount_micros: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + + class RegulatoryCostSummary(proto.Message): + r"""Represents regulatory cost information associated with an + account. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + regulatory_fee_type (google.ads.googleads.v24.enums.types.RegulatoryFeeTypeEnum.RegulatoryFeeType): + Output only. The type of regulatory fee. + + This field is a member of `oneof`_ ``_regulatory_fee_type``. + amount_micros (int): + Output only. The amount of the regulatory fee, in micros. + The currency code for this amount is the same as the + Invoice.currency_code. + + This field is a member of `oneof`_ ``_amount_micros``. + """ + + regulatory_fee_type: ( + gage_regulatory_fee_type.RegulatoryFeeTypeEnum.RegulatoryFeeType + ) = proto.Field( + proto.ENUM, + number=1, + optional=True, + enum=gage_regulatory_fee_type.RegulatoryFeeTypeEnum.RegulatoryFeeType, + ) + amount_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + class AdjustmentSummary(proto.Message): + r"""Represents adjustment information associated with an account. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + adjustment_description (str): + Output only. The description of the + adjustment. Example: Incentive Adjustment, + discount. + + This field is a member of `oneof`_ ``_adjustment_description``. + amount_micros (int): + Output only. The amount of the adjustment, in micros. The + currency code for this amount is the same as the + Invoice.currency_code. + + This field is a member of `oneof`_ ``_amount_micros``. + """ + + adjustment_description: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + amount_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: str = proto.Field( + proto.STRING, + number=25, + optional=True, + ) + type_: invoice_type.InvoiceTypeEnum.InvoiceType = proto.Field( + proto.ENUM, + number=3, + enum=invoice_type.InvoiceTypeEnum.InvoiceType, + ) + billing_setup: str = proto.Field( + proto.STRING, + number=26, + optional=True, + ) + payments_account_id: str = proto.Field( + proto.STRING, + number=27, + optional=True, + ) + payments_profile_id: str = proto.Field( + proto.STRING, + number=28, + optional=True, + ) + issue_date: str = proto.Field( + proto.STRING, + number=29, + optional=True, + ) + due_date: str = proto.Field( + proto.STRING, + number=30, + optional=True, + ) + service_date_range: dates.DateRange = proto.Field( + proto.MESSAGE, + number=9, + message=dates.DateRange, + ) + currency_code: str = proto.Field( + proto.STRING, + number=31, + optional=True, + ) + adjustments_subtotal_amount_micros: int = proto.Field( + proto.INT64, + number=19, + ) + adjustments_tax_amount_micros: int = proto.Field( + proto.INT64, + number=20, + ) + adjustments_total_amount_micros: int = proto.Field( + proto.INT64, + number=21, + ) + regulatory_costs_subtotal_amount_micros: int = proto.Field( + proto.INT64, + number=22, + ) + regulatory_costs_tax_amount_micros: int = proto.Field( + proto.INT64, + number=23, + ) + regulatory_costs_total_amount_micros: int = proto.Field( + proto.INT64, + number=24, + ) + export_charge_subtotal_amount_micros: int = proto.Field( + proto.INT64, + number=40, + optional=True, + ) + export_charge_tax_amount_micros: int = proto.Field( + proto.INT64, + number=41, + optional=True, + ) + export_charge_total_amount_micros: int = proto.Field( + proto.INT64, + number=42, + optional=True, + ) + subtotal_amount_micros: int = proto.Field( + proto.INT64, + number=33, + optional=True, + ) + tax_amount_micros: int = proto.Field( + proto.INT64, + number=34, + optional=True, + ) + total_amount_micros: int = proto.Field( + proto.INT64, + number=35, + optional=True, + ) + corrected_invoice: str = proto.Field( + proto.STRING, + number=36, + optional=True, + ) + replaced_invoices: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=37, + ) + pdf_url: str = proto.Field( + proto.STRING, + number=38, + optional=True, + ) + account_budget_summaries: MutableSequence[AccountBudgetSummary] = ( + proto.RepeatedField( + proto.MESSAGE, + number=18, + message=AccountBudgetSummary, + ) + ) + account_summaries: MutableSequence[AccountSummary] = proto.RepeatedField( + proto.MESSAGE, + number=39, + message=AccountSummary, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/keyword_plan.py b/google/ads/googleads/v24/resources/types/keyword_plan.py new file mode 100644 index 000000000..dab68f604 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/keyword_plan.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import dates +from google.ads.googleads.v24.enums.types import keyword_plan_forecast_interval + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlan", + "KeywordPlanForecastPeriod", + }, +) + + +class KeywordPlan(proto.Message): + r"""A Keyword Planner plan. + Max number of saved keyword plans: 10000. + It's possible to remove plans if limit is reached. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the Keyword Planner plan. + KeywordPlan resource names have the form: + + ``customers/{customer_id}/keywordPlans/{kp_plan_id}`` + id (int): + Output only. The ID of the keyword plan. + + This field is a member of `oneof`_ ``_id``. + name (str): + The name of the keyword plan. + + This field is required and should not be empty + when creating new keyword plans. + + This field is a member of `oneof`_ ``_name``. + forecast_period (google.ads.googleads.v24.resources.types.KeywordPlanForecastPeriod): + The date period used for forecasting the + plan. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + forecast_period: "KeywordPlanForecastPeriod" = proto.Field( + proto.MESSAGE, + number=4, + message="KeywordPlanForecastPeriod", + ) + + +class KeywordPlanForecastPeriod(proto.Message): + r"""The forecasting period associated with the keyword plan. + + 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: + date_interval (google.ads.googleads.v24.enums.types.KeywordPlanForecastIntervalEnum.KeywordPlanForecastInterval): + A future date range relative to the current + date used for forecasting. + + This field is a member of `oneof`_ ``interval``. + date_range (google.ads.googleads.v24.common.types.DateRange): + The custom date range used for forecasting. + It cannot be greater than a year. + The start and end dates must be in the future. + Otherwise, an error will be returned when the + forecasting action is performed. The start and + end dates are inclusive. + + This field is a member of `oneof`_ ``interval``. + """ + + date_interval: ( + keyword_plan_forecast_interval.KeywordPlanForecastIntervalEnum.KeywordPlanForecastInterval + ) = proto.Field( + proto.ENUM, + number=1, + oneof="interval", + enum=keyword_plan_forecast_interval.KeywordPlanForecastIntervalEnum.KeywordPlanForecastInterval, + ) + date_range: dates.DateRange = proto.Field( + proto.MESSAGE, + number=2, + oneof="interval", + message=dates.DateRange, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/keyword_plan_ad_group.py b/google/ads/googleads/v24/resources/types/keyword_plan_ad_group.py new file mode 100644 index 000000000..853caf80f --- /dev/null +++ b/google/ads/googleads/v24/resources/types/keyword_plan_ad_group.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanAdGroup", + }, +) + + +class KeywordPlanAdGroup(proto.Message): + r"""A Keyword Planner ad group. + Max number of keyword plan ad groups per plan: 200. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the Keyword Planner ad + group. KeywordPlanAdGroup resource names have the form: + + ``customers/{customer_id}/keywordPlanAdGroups/{kp_ad_group_id}`` + keyword_plan_campaign (str): + The keyword plan campaign to which this ad + group belongs. + + This field is a member of `oneof`_ ``_keyword_plan_campaign``. + id (int): + Output only. The ID of the keyword plan ad + group. + + This field is a member of `oneof`_ ``_id``. + name (str): + The name of the keyword plan ad group. + + This field is required and should not be empty + when creating keyword plan ad group. + + This field is a member of `oneof`_ ``_name``. + cpc_bid_micros (int): + A default ad group max cpc bid in micros in + account currency for all biddable keywords under + the keyword plan ad group. If not set, will + inherit from parent campaign. + + This field is a member of `oneof`_ ``_cpc_bid_micros``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + keyword_plan_campaign: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + id: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + cpc_bid_micros: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/keyword_plan_ad_group_keyword.py b/google/ads/googleads/v24/resources/types/keyword_plan_ad_group_keyword.py new file mode 100644 index 000000000..37462f8e6 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/keyword_plan_ad_group_keyword.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import keyword_match_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanAdGroupKeyword", + }, +) + + +class KeywordPlanAdGroupKeyword(proto.Message): + r"""A Keyword Plan ad group keyword. + Max number of keyword plan keywords per plan: 10000. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the Keyword Plan ad group + keyword. KeywordPlanAdGroupKeyword resource names have the + form: + + ``customers/{customer_id}/keywordPlanAdGroupKeywords/{kp_ad_group_keyword_id}`` + keyword_plan_ad_group (str): + The Keyword Plan ad group to which this + keyword belongs. + + This field is a member of `oneof`_ ``_keyword_plan_ad_group``. + id (int): + Output only. The ID of the Keyword Plan + keyword. + + This field is a member of `oneof`_ ``_id``. + text (str): + The keyword text. + + This field is a member of `oneof`_ ``_text``. + match_type (google.ads.googleads.v24.enums.types.KeywordMatchTypeEnum.KeywordMatchType): + The keyword match type. + cpc_bid_micros (int): + A keyword level max cpc bid in micros (for + example, $1 = 1mm). The currency is the same as + the account currency code. This will override + any CPC bid set at the keyword plan ad group + level. Not applicable for negative keywords. + (negative = true) This field is Optional. + + This field is a member of `oneof`_ ``_cpc_bid_micros``. + negative (bool): + Immutable. If true, the keyword is negative. + + This field is a member of `oneof`_ ``_negative``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + keyword_plan_ad_group: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + id: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + text: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + match_type: keyword_match_type.KeywordMatchTypeEnum.KeywordMatchType = ( + proto.Field( + proto.ENUM, + number=5, + enum=keyword_match_type.KeywordMatchTypeEnum.KeywordMatchType, + ) + ) + cpc_bid_micros: int = proto.Field( + proto.INT64, + number=11, + optional=True, + ) + negative: bool = proto.Field( + proto.BOOL, + number=12, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/keyword_plan_campaign.py b/google/ads/googleads/v24/resources/types/keyword_plan_campaign.py new file mode 100644 index 000000000..6fbd52246 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/keyword_plan_campaign.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + keyword_plan_network as gage_keyword_plan_network, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanCampaign", + "KeywordPlanGeoTarget", + }, +) + + +class KeywordPlanCampaign(proto.Message): + r"""A Keyword Plan campaign. + Max number of keyword plan campaigns per plan allowed: 1. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the Keyword Plan campaign. + KeywordPlanCampaign resource names have the form: + + ``customers/{customer_id}/keywordPlanCampaigns/{kp_campaign_id}`` + keyword_plan (str): + The keyword plan this campaign belongs to. + + This field is a member of `oneof`_ ``_keyword_plan``. + id (int): + Output only. The ID of the Keyword Plan + campaign. + + This field is a member of `oneof`_ ``_id``. + name (str): + The name of the Keyword Plan campaign. + + This field is required and should not be empty + when creating Keyword Plan campaigns. + + This field is a member of `oneof`_ ``_name``. + language_constants (MutableSequence[str]): + The languages targeted for the Keyword Plan + campaign. Max allowed: 1. + keyword_plan_network (google.ads.googleads.v24.enums.types.KeywordPlanNetworkEnum.KeywordPlanNetwork): + Targeting network. + + This field is required and should not be empty + when creating Keyword Plan campaigns. + cpc_bid_micros (int): + A default max cpc bid in micros, and in the + account currency, for all ad groups under the + campaign. + + This field is required and should not be empty + when creating Keyword Plan campaigns. + + This field is a member of `oneof`_ ``_cpc_bid_micros``. + geo_targets (MutableSequence[google.ads.googleads.v24.resources.types.KeywordPlanGeoTarget]): + The geo targets. + Max number allowed: 20. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + keyword_plan: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + id: int = proto.Field( + proto.INT64, + number=10, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + language_constants: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=12, + ) + keyword_plan_network: ( + gage_keyword_plan_network.KeywordPlanNetworkEnum.KeywordPlanNetwork + ) = proto.Field( + proto.ENUM, + number=6, + enum=gage_keyword_plan_network.KeywordPlanNetworkEnum.KeywordPlanNetwork, + ) + cpc_bid_micros: int = proto.Field( + proto.INT64, + number=13, + optional=True, + ) + geo_targets: MutableSequence["KeywordPlanGeoTarget"] = proto.RepeatedField( + proto.MESSAGE, + number=8, + message="KeywordPlanGeoTarget", + ) + + +class KeywordPlanGeoTarget(proto.Message): + r"""A geo target. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + geo_target_constant (str): + Required. The resource name of the geo + target. + + This field is a member of `oneof`_ ``_geo_target_constant``. + """ + + geo_target_constant: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/keyword_plan_campaign_keyword.py b/google/ads/googleads/v24/resources/types/keyword_plan_campaign_keyword.py new file mode 100644 index 000000000..26d02cd73 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/keyword_plan_campaign_keyword.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import keyword_match_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordPlanCampaignKeyword", + }, +) + + +class KeywordPlanCampaignKeyword(proto.Message): + r"""A Keyword Plan Campaign keyword. + Only negative keywords are supported for Campaign Keyword. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the Keyword Plan Campaign + keyword. KeywordPlanCampaignKeyword resource names have the + form: + + ``customers/{customer_id}/keywordPlanCampaignKeywords/{kp_campaign_keyword_id}`` + keyword_plan_campaign (str): + The Keyword Plan campaign to which this + negative keyword belongs. + + This field is a member of `oneof`_ ``_keyword_plan_campaign``. + id (int): + Output only. The ID of the Keyword Plan + negative keyword. + + This field is a member of `oneof`_ ``_id``. + text (str): + The keyword text. + + This field is a member of `oneof`_ ``_text``. + match_type (google.ads.googleads.v24.enums.types.KeywordMatchTypeEnum.KeywordMatchType): + The keyword match type. + negative (bool): + Immutable. If true, the keyword is negative. + Must be set to true. Only negative campaign + keywords are supported. + + This field is a member of `oneof`_ ``_negative``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + keyword_plan_campaign: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + id: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + text: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + match_type: keyword_match_type.KeywordMatchTypeEnum.KeywordMatchType = ( + proto.Field( + proto.ENUM, + number=5, + enum=keyword_match_type.KeywordMatchTypeEnum.KeywordMatchType, + ) + ) + negative: bool = proto.Field( + proto.BOOL, + number=11, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/keyword_theme_constant.py b/google/ads/googleads/v24/resources/types/keyword_theme_constant.py new file mode 100644 index 000000000..8cdc9511b --- /dev/null +++ b/google/ads/googleads/v24/resources/types/keyword_theme_constant.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordThemeConstant", + }, +) + + +class KeywordThemeConstant(proto.Message): + r"""A Smart Campaign keyword theme constant. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the keyword theme + constant. Keyword theme constant resource names have the + form: + + ``keywordThemeConstants/{keyword_theme_id}~{sub_keyword_theme_id}`` + country_code (str): + Output only. The ISO-3166 Alpha-2 country + code of the constant, eg. "US". To display and + query matching purpose, the keyword theme needs + to be localized. + + This field is a member of `oneof`_ ``_country_code``. + language_code (str): + Output only. The ISO-639-1 language code with + 2 letters of the constant, eg. "en". To display + and query matching purpose, the keyword theme + needs to be localized. + + This field is a member of `oneof`_ ``_language_code``. + display_name (str): + Output only. The display name of the keyword + theme or sub keyword theme. + + This field is a member of `oneof`_ ``_display_name``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + country_code: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + language_code: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + display_name: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/keyword_view.py b/google/ads/googleads/v24/resources/types/keyword_view.py new file mode 100644 index 000000000..f308e347c --- /dev/null +++ b/google/ads/googleads/v24/resources/types/keyword_view.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "KeywordView", + }, +) + + +class KeywordView(proto.Message): + r"""A keyword view. + + Attributes: + resource_name (str): + Output only. The resource name of the keyword view. Keyword + view resource names have the form: + + ``customers/{customer_id}/keywordViews/{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/label.py b/google/ads/googleads/v24/resources/types/label.py new file mode 100644 index 000000000..3099114fb --- /dev/null +++ b/google/ads/googleads/v24/resources/types/label.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import text_label as gagc_text_label +from google.ads.googleads.v24.enums.types import label_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "Label", + }, +) + + +class Label(proto.Message): + r"""A label. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. Name of the resource. Label resource names have + the form: ``customers/{customer_id}/labels/{label_id}`` + id (int): + Output only. ID of the label. Read only. + + This field is a member of `oneof`_ ``_id``. + name (str): + The name of the label. + + This field is required and should not be empty + when creating a new label. + + The length of this string should be between 1 + and 80, inclusive. + + This field is a member of `oneof`_ ``_name``. + status (google.ads.googleads.v24.enums.types.LabelStatusEnum.LabelStatus): + Output only. Status of the label. Read only. + text_label (google.ads.googleads.v24.common.types.TextLabel): + A type of label displaying text on a colored + background. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + status: label_status.LabelStatusEnum.LabelStatus = proto.Field( + proto.ENUM, + number=4, + enum=label_status.LabelStatusEnum.LabelStatus, + ) + text_label: gagc_text_label.TextLabel = proto.Field( + proto.MESSAGE, + number=5, + message=gagc_text_label.TextLabel, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/landing_page_view.py b/google/ads/googleads/v24/resources/types/landing_page_view.py new file mode 100644 index 000000000..325e85b7a --- /dev/null +++ b/google/ads/googleads/v24/resources/types/landing_page_view.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "LandingPageView", + }, +) + + +class LandingPageView(proto.Message): + r"""A landing page view with metrics aggregated at the unexpanded + final URL level. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the landing page view. + Landing page view resource names have the form: + + ``customers/{customer_id}/landingPageViews/{unexpanded_final_url_fingerprint}`` + unexpanded_final_url (str): + Output only. The advertiser-specified final + URL. + + This field is a member of `oneof`_ ``_unexpanded_final_url``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + unexpanded_final_url: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/language_constant.py b/google/ads/googleads/v24/resources/types/language_constant.py new file mode 100644 index 000000000..b21f60ae8 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/language_constant.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "LanguageConstant", + }, +) + + +class LanguageConstant(proto.Message): + r"""A language. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the language constant. + Language constant resource names have the form: + + ``languageConstants/{criterion_id}`` + id (int): + Output only. The ID of the language constant. + + This field is a member of `oneof`_ ``_id``. + code (str): + Output only. The language code, for example, "en_US", + "en_AU", "es", "fr", etc. + + This field is a member of `oneof`_ ``_code``. + name (str): + Output only. The full name of the language in + English, for example, "English (US)", "Spanish", + etc. + + This field is a member of `oneof`_ ``_name``. + targetable (bool): + Output only. Whether the language is + targetable. + + This field is a member of `oneof`_ ``_targetable``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + code: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + targetable: bool = proto.Field( + proto.BOOL, + number=9, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/lead_form_submission_data.py b/google/ads/googleads/v24/resources/types/lead_form_submission_data.py new file mode 100644 index 000000000..63dcd7df8 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/lead_form_submission_data.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import lead_form_field_user_input_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "LeadFormSubmissionData", + "LeadFormSubmissionField", + "CustomLeadFormSubmissionField", + }, +) + + +class LeadFormSubmissionData(proto.Message): + r"""Data from lead form submissions. + + Attributes: + resource_name (str): + Output only. The resource name of the lead form submission + data. Lead form submission data resource names have the + form: + + ``customers/{customer_id}/leadFormSubmissionData/{lead_form_submission_data_id}`` + id (str): + Output only. ID of this lead form submission. + asset (str): + Output only. Asset associated with the + submitted lead form. + campaign (str): + Output only. Campaign associated with the + submitted lead form. + lead_form_submission_fields (MutableSequence[google.ads.googleads.v24.resources.types.LeadFormSubmissionField]): + Output only. Submission data associated with + a lead form. + custom_lead_form_submission_fields (MutableSequence[google.ads.googleads.v24.resources.types.CustomLeadFormSubmissionField]): + Output only. Submission data associated with + a custom lead form. + ad_group (str): + Output only. AdGroup associated with the + submitted lead form. + ad_group_ad (str): + Output only. AdGroupAd associated with the + submitted lead form. + gclid (str): + Output only. Google Click Id associated with + the submissed lead form. + submission_date_time (str): + Output only. The date and time at which the lead form was + submitted. The format is "yyyy-mm-dd hh:mm:ss+\|-hh:mm", for + example, "2019-01-01 12:32:45-08:00". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: str = proto.Field( + proto.STRING, + number=2, + ) + asset: str = proto.Field( + proto.STRING, + number=3, + ) + campaign: str = proto.Field( + proto.STRING, + number=4, + ) + lead_form_submission_fields: MutableSequence["LeadFormSubmissionField"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=5, + message="LeadFormSubmissionField", + ) + ) + custom_lead_form_submission_fields: MutableSequence[ + "CustomLeadFormSubmissionField" + ] = proto.RepeatedField( + proto.MESSAGE, + number=10, + message="CustomLeadFormSubmissionField", + ) + ad_group: str = proto.Field( + proto.STRING, + number=6, + ) + ad_group_ad: str = proto.Field( + proto.STRING, + number=7, + ) + gclid: str = proto.Field( + proto.STRING, + number=8, + ) + submission_date_time: str = proto.Field( + proto.STRING, + number=9, + ) + + +class LeadFormSubmissionField(proto.Message): + r"""Fields in the submitted lead form. + + Attributes: + field_type (google.ads.googleads.v24.enums.types.LeadFormFieldUserInputTypeEnum.LeadFormFieldUserInputType): + Output only. Field type for lead form fields. + field_value (str): + Output only. Field value for lead form + fields. + """ + + field_type: ( + lead_form_field_user_input_type.LeadFormFieldUserInputTypeEnum.LeadFormFieldUserInputType + ) = proto.Field( + proto.ENUM, + number=1, + enum=lead_form_field_user_input_type.LeadFormFieldUserInputTypeEnum.LeadFormFieldUserInputType, + ) + field_value: str = proto.Field( + proto.STRING, + number=2, + ) + + +class CustomLeadFormSubmissionField(proto.Message): + r"""Fields in the submitted custom question + + Attributes: + question_text (str): + Output only. Question text for custom + question, maximum number of characters is 300. + field_value (str): + Output only. Field value for custom question + response, maximum number of characters is 70. + """ + + question_text: str = proto.Field( + proto.STRING, + number=1, + ) + field_value: str = proto.Field( + proto.STRING, + number=2, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/life_event.py b/google/ads/googleads/v24/resources/types/life_event.py new file mode 100644 index 000000000..2ac55c819 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/life_event.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import ( + criterion_category_availability, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "LifeEvent", + }, +) + + +class LifeEvent(proto.Message): + r"""A life event: a particular interest-based vertical to be + targeted to reach users when they are in the midst of important + life milestones. + + Attributes: + resource_name (str): + Output only. The resource name of the life event. Life event + resource names have the form: + + ``customers/{customer_id}/lifeEvents/{life_event_id}`` + id (int): + Output only. The ID of the life event. + name (str): + Output only. The name of the life event, for + example,"Recently Moved". + parent (str): + Output only. The parent of the life_event. + launched_to_all (bool): + Output only. True if the life event is + launched to all channels and locales. + availabilities (MutableSequence[google.ads.googleads.v24.common.types.CriterionCategoryAvailability]): + Output only. Availability information of the + life event. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + ) + name: str = proto.Field( + proto.STRING, + number=3, + ) + parent: str = proto.Field( + proto.STRING, + number=4, + ) + launched_to_all: bool = proto.Field( + proto.BOOL, + number=5, + ) + availabilities: MutableSequence[ + criterion_category_availability.CriterionCategoryAvailability + ] = proto.RepeatedField( + proto.MESSAGE, + number=6, + message=criterion_category_availability.CriterionCategoryAvailability, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/local_services_employee.py b/google/ads/googleads/v24/resources/types/local_services_employee.py new file mode 100644 index 000000000..6dc830417 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/local_services_employee.py @@ -0,0 +1,308 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import local_services_employee_status +from google.ads.googleads.v24.enums.types import local_services_employee_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesEmployee", + "UniversityDegree", + "Residency", + "Fellowship", + }, +) + + +class LocalServicesEmployee(proto.Message): + r"""A local services employee resource. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the Local Services + Verification. Local Services Verification resource names + have the form: + + ``customers/{customer_id}/localServicesEmployees/{gls_employee_id}`` + id (int): + Output only. The ID of the employee. + + This field is a member of `oneof`_ ``_id``. + creation_date_time (str): + Output only. Timestamp of employee creation. + The format is "YYYY-MM-DD HH:MM:SS" in the + Google Ads account's timezone. Examples: + "2018-03-05 09:15:00" or "2018-02-01 14:34:30". + status (google.ads.googleads.v24.enums.types.LocalServicesEmployeeStatusEnum.LocalServicesEmployeeStatus): + Output only. Employee status, such as DELETED + or ENABLED. + type_ (google.ads.googleads.v24.enums.types.LocalServicesEmployeeTypeEnum.LocalServicesEmployeeType): + Output only. Employee type. + university_degrees (MutableSequence[google.ads.googleads.v24.resources.types.UniversityDegree]): + Output only. A list of degrees this employee + has obtained, and wants to feature. + residencies (MutableSequence[google.ads.googleads.v24.resources.types.Residency]): + Output only. The institutions where the + employee has completed their residency. + fellowships (MutableSequence[google.ads.googleads.v24.resources.types.Fellowship]): + Output only. The institutions where the + employee has completed their fellowship. + job_title (str): + Output only. Job title for this employee, + such as "Senior partner" in legal verticals. + + This field is a member of `oneof`_ ``_job_title``. + year_started_practicing (int): + Output only. The year that this employee + started practicing in this field. + + This field is a member of `oneof`_ ``_year_started_practicing``. + languages_spoken (MutableSequence[str]): + Output only. Languages that the employee + speaks, represented as language tags from + https://developers.google.com/admin-sdk/directory/v1/languages + category_ids (MutableSequence[str]): + Output only. Category of the employee. A list of Local + Services category IDs can be found at + https://developers.google.com/google-ads/api/data/codes-formats#local_services_ids. + national_provider_id_number (str): + Output only. NPI id associated with the + employee. + + This field is a member of `oneof`_ ``_national_provider_id_number``. + email_address (str): + Output only. Email address of the employee. + + This field is a member of `oneof`_ ``_email_address``. + first_name (str): + Output only. First name of the employee. + + This field is a member of `oneof`_ ``_first_name``. + middle_name (str): + Output only. Middle name of the employee. + + This field is a member of `oneof`_ ``_middle_name``. + last_name (str): + Output only. Last name of the employee. + + This field is a member of `oneof`_ ``_last_name``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + creation_date_time: str = proto.Field( + proto.STRING, + number=3, + ) + status: ( + local_services_employee_status.LocalServicesEmployeeStatusEnum.LocalServicesEmployeeStatus + ) = proto.Field( + proto.ENUM, + number=4, + enum=local_services_employee_status.LocalServicesEmployeeStatusEnum.LocalServicesEmployeeStatus, + ) + type_: ( + local_services_employee_type.LocalServicesEmployeeTypeEnum.LocalServicesEmployeeType + ) = proto.Field( + proto.ENUM, + number=5, + enum=local_services_employee_type.LocalServicesEmployeeTypeEnum.LocalServicesEmployeeType, + ) + university_degrees: MutableSequence["UniversityDegree"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=6, + message="UniversityDegree", + ) + ) + residencies: MutableSequence["Residency"] = proto.RepeatedField( + proto.MESSAGE, + number=7, + message="Residency", + ) + fellowships: MutableSequence["Fellowship"] = proto.RepeatedField( + proto.MESSAGE, + number=8, + message="Fellowship", + ) + job_title: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + year_started_practicing: int = proto.Field( + proto.INT32, + number=10, + optional=True, + ) + languages_spoken: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=11, + ) + category_ids: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=12, + ) + national_provider_id_number: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + email_address: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + first_name: str = proto.Field( + proto.STRING, + number=15, + optional=True, + ) + middle_name: str = proto.Field( + proto.STRING, + number=16, + optional=True, + ) + last_name: str = proto.Field( + proto.STRING, + number=17, + optional=True, + ) + + +class UniversityDegree(proto.Message): + r"""A list of degrees this employee has obtained, and wants to + feature. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + institution_name (str): + Output only. Name of the university at which + the degree was obtained. + + This field is a member of `oneof`_ ``_institution_name``. + degree (str): + Output only. Name of the degree obtained. + + This field is a member of `oneof`_ ``_degree``. + graduation_year (int): + Output only. Year of graduation. + + This field is a member of `oneof`_ ``_graduation_year``. + """ + + institution_name: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + degree: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + graduation_year: int = proto.Field( + proto.INT32, + number=3, + optional=True, + ) + + +class Residency(proto.Message): + r"""Details about the employee's medical residency. + Residency is a stage of graduate medical education in which a + qualified medical professional practices under the supervision + of a senior clinician. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + institution_name (str): + Output only. Name of the institution at which + the residency was completed. + + This field is a member of `oneof`_ ``_institution_name``. + completion_year (int): + Output only. Year of completion. + + This field is a member of `oneof`_ ``_completion_year``. + """ + + institution_name: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + completion_year: int = proto.Field( + proto.INT32, + number=2, + optional=True, + ) + + +class Fellowship(proto.Message): + r"""Details about the employee's medical Fellowship. + Fellowship is a period of medical training that the professional + undertakes after finishing their residency. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + institution_name (str): + Output only. Name of the instutition at which + the fellowship was completed. + + This field is a member of `oneof`_ ``_institution_name``. + completion_year (int): + Output only. Year of completion. + + This field is a member of `oneof`_ ``_completion_year``. + """ + + institution_name: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + completion_year: int = proto.Field( + proto.INT32, + number=2, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/local_services_lead.py b/google/ads/googleads/v24/resources/types/local_services_lead.py new file mode 100644 index 000000000..5a2b64472 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/local_services_lead.py @@ -0,0 +1,252 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + local_services_lead_credit_state, +) +from google.ads.googleads.v24.enums.types import local_services_lead_status +from google.ads.googleads.v24.enums.types import local_services_lead_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesLead", + "ContactDetails", + "Note", + "CreditDetails", + }, +) + + +class LocalServicesLead(proto.Message): + r"""Data from Local Services Lead. + Contains details of Lead which is generated when user calls, + messages or books service from advertiser. + More info: https://ads.google.com/local-services-ads + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the local services lead + data. Local Services Lead resource name have the form + + ``customers/{customer_id}/localServicesLead/{local_services_lead_id}`` + id (int): + Output only. ID of this Lead. + category_id (str): + Output only. Service category of the lead. For example: + ``xcat:service_area_business_hvac``, + ``xcat:service_area_business_real_estate_agent``, etc. For + more details see: + https://developers.google.com/google-ads/api/data/codes-formats#local_services_ids + service_id (str): + Output only. Service for the category. For example: + ``buyer_agent``, ``seller_agent`` for the category of + ``xcat:service_area_business_real_estate_agent``. + contact_details (google.ads.googleads.v24.resources.types.ContactDetails): + Output only. Lead's contact details. + lead_type (google.ads.googleads.v24.enums.types.LocalServicesLeadTypeEnum.LeadType): + Output only. Type of Local Services lead: + phone, message, booking, etc. + lead_status (google.ads.googleads.v24.enums.types.LocalServicesLeadStatusEnum.LeadStatus): + Output only. Current status of lead. + creation_date_time (str): + Output only. The date time at which lead was + created by Local Services Ads. The format is + "YYYY-MM-DD HH:MM:SS" in the Google Ads + account's timezone. Examples: "2018-03-05 + 09:15:00" or "2018-02-01 14:34:30". + locale (str): + Output only. Language used by the Local + Services provider linked to lead. See + https://developers.google.com/google-ads/api/data/codes-formats#locales + note (google.ads.googleads.v24.resources.types.Note): + Output only. Note added by advertiser for the + lead. + + This field is a member of `oneof`_ ``_note``. + lead_charged (bool): + Output only. True if the advertiser was + charged for the lead. + credit_details (google.ads.googleads.v24.resources.types.CreditDetails): + Output only. Credit details of the lead. + + This field is a member of `oneof`_ ``_credit_details``. + lead_feedback_submitted (bool): + Output only. True if the advertiser submitted + feedback for the lead. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + ) + category_id: str = proto.Field( + proto.STRING, + number=3, + ) + service_id: str = proto.Field( + proto.STRING, + number=4, + ) + contact_details: "ContactDetails" = proto.Field( + proto.MESSAGE, + number=5, + message="ContactDetails", + ) + lead_type: local_services_lead_type.LocalServicesLeadTypeEnum.LeadType = ( + proto.Field( + proto.ENUM, + number=6, + enum=local_services_lead_type.LocalServicesLeadTypeEnum.LeadType, + ) + ) + lead_status: ( + local_services_lead_status.LocalServicesLeadStatusEnum.LeadStatus + ) = proto.Field( + proto.ENUM, + number=7, + enum=local_services_lead_status.LocalServicesLeadStatusEnum.LeadStatus, + ) + creation_date_time: str = proto.Field( + proto.STRING, + number=8, + ) + locale: str = proto.Field( + proto.STRING, + number=9, + ) + note: "Note" = proto.Field( + proto.MESSAGE, + number=10, + optional=True, + message="Note", + ) + lead_charged: bool = proto.Field( + proto.BOOL, + number=11, + ) + credit_details: "CreditDetails" = proto.Field( + proto.MESSAGE, + number=12, + optional=True, + message="CreditDetails", + ) + lead_feedback_submitted: bool = proto.Field( + proto.BOOL, + number=13, + ) + + +class ContactDetails(proto.Message): + r"""Fields containing consumer contact details. + + Attributes: + phone_number (str): + Output only. Phone number of the consumer for + the lead. This can be a real phone number or a + tracking number. The phone number is returned in + E164 format. See + https://support.google.com/google-ads/answer/16355235?hl=en + to learn more. Example: +16504519489. + email (str): + Output only. Consumer email address. + consumer_name (str): + Output only. Consumer name if consumer + provided name from Message or Booking form on + google.com + """ + + phone_number: str = proto.Field( + proto.STRING, + number=1, + ) + email: str = proto.Field( + proto.STRING, + number=2, + ) + consumer_name: str = proto.Field( + proto.STRING, + number=3, + ) + + +class Note(proto.Message): + r"""Represents a note added to a lead by the advertiser. + Advertisers can edit notes, which will reset edit time and + change description. + + Attributes: + edit_date_time (str): + Output only. The date time when lead note was + edited. The format is "YYYY-MM-DD HH:MM:SS" in + the Google Ads account's timezone. Examples: + + "2018-03-05 09:15:00" or "2018-02-01 14:34:30". + description (str): + Output only. Content of lead note. + """ + + edit_date_time: str = proto.Field( + proto.STRING, + number=1, + ) + description: str = proto.Field( + proto.STRING, + number=2, + ) + + +class CreditDetails(proto.Message): + r"""Represents the credit details of a lead. + + Attributes: + credit_state (google.ads.googleads.v24.enums.types.LocalServicesCreditStateEnum.CreditState): + Output only. Credit state of the lead. + credit_state_last_update_date_time (str): + Output only. The date time when the credit + state of the lead was last updated. The format + is "YYYY-MM-DD HH:MM:SS" in the Google Ads + account's timezone. Examples: "2018-03-05 + 09:15:00" or "2018-02-01 14:34:30". + """ + + credit_state: ( + local_services_lead_credit_state.LocalServicesCreditStateEnum.CreditState + ) = proto.Field( + proto.ENUM, + number=1, + enum=local_services_lead_credit_state.LocalServicesCreditStateEnum.CreditState, + ) + credit_state_last_update_date_time: str = proto.Field( + proto.STRING, + number=2, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/local_services_lead_conversation.py b/google/ads/googleads/v24/resources/types/local_services_lead_conversation.py new file mode 100644 index 000000000..aad2d1742 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/local_services_lead_conversation.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + local_services_conversation_type, +) +from google.ads.googleads.v24.enums.types import local_services_participant_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesLeadConversation", + "PhoneCallDetails", + "MessageDetails", + }, +) + + +class LocalServicesLeadConversation(proto.Message): + r"""Data from Local Services Lead Conversation. + Contains details of Lead Conversation which is generated when + user calls, messages or books service from advertiser. These are + appended to a Lead. More info: + https://ads.google.com/local-services-ads + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the local services lead + conversation data. Local Services Lead Conversation resource + name have the form + + ``customers/{customer_id}/localServicesLeadConversation/{local_services_lead_conversation_id}`` + id (int): + Output only. ID of this Lead Conversation. + conversation_channel (google.ads.googleads.v24.enums.types.LocalServicesLeadConversationTypeEnum.ConversationType): + Output only. Type of GLS lead conversation, EMAIL, MESSAGE, + PHONE_CALL, SMS, etc. + participant_type (google.ads.googleads.v24.enums.types.LocalServicesParticipantTypeEnum.ParticipantType): + Output only. Type of participant in the lead + conversation, ADVERTISER or CONSUMER. + lead (str): + Output only. Resource name of Lead associated + to the Lead Conversation. + event_date_time (str): + Output only. The date time at which lead + conversation was created by Local Services Ads. + The format is "YYYY-MM-DD HH:MM:SS" in the + Google Ads account's timezone. Examples: + "2018-03-05 09:15:00" or "2018-02-01 14:34:30". + phone_call_details (google.ads.googleads.v24.resources.types.PhoneCallDetails): + Output only. Details of phone call conversation in case of + PHONE_CALL. + + This field is a member of `oneof`_ ``_phone_call_details``. + message_details (google.ads.googleads.v24.resources.types.MessageDetails): + Output only. Details of message conversation + in case of EMAIL, MESSAGE or SMS. + + This field is a member of `oneof`_ ``_message_details``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + ) + conversation_channel: ( + local_services_conversation_type.LocalServicesLeadConversationTypeEnum.ConversationType + ) = proto.Field( + proto.ENUM, + number=3, + enum=local_services_conversation_type.LocalServicesLeadConversationTypeEnum.ConversationType, + ) + participant_type: ( + local_services_participant_type.LocalServicesParticipantTypeEnum.ParticipantType + ) = proto.Field( + proto.ENUM, + number=4, + enum=local_services_participant_type.LocalServicesParticipantTypeEnum.ParticipantType, + ) + lead: str = proto.Field( + proto.STRING, + number=5, + ) + event_date_time: str = proto.Field( + proto.STRING, + number=6, + ) + phone_call_details: "PhoneCallDetails" = proto.Field( + proto.MESSAGE, + number=7, + optional=True, + message="PhoneCallDetails", + ) + message_details: "MessageDetails" = proto.Field( + proto.MESSAGE, + number=8, + optional=True, + message="MessageDetails", + ) + + +class PhoneCallDetails(proto.Message): + r"""Represents details of a phone call conversation. + + Attributes: + call_duration_millis (int): + Output only. The duration (in milliseconds) + of the phone call (end to end). + call_recording_url (str): + Output only. URL to the call recording audio + file. + """ + + call_duration_millis: int = proto.Field( + proto.INT64, + number=1, + ) + call_recording_url: str = proto.Field( + proto.STRING, + number=2, + ) + + +class MessageDetails(proto.Message): + r"""Represents details of text message in case of email, message + or SMS. + + Attributes: + text (str): + Output only. Textual content of the message. + attachment_urls (MutableSequence[str]): + Output only. URL to the SMS or email + attachments. These URLs can be used to download + the contents of the attachment by using the + developer token. + """ + + text: str = proto.Field( + proto.STRING, + number=1, + ) + attachment_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/local_services_verification_artifact.py b/google/ads/googleads/v24/resources/types/local_services_verification_artifact.py new file mode 100644 index 000000000..6e2fbf4f6 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/local_services_verification_artifact.py @@ -0,0 +1,476 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import local_services +from google.ads.googleads.v24.enums.types import ( + local_services_business_registration_check_rejection_reason, +) +from google.ads.googleads.v24.enums.types import ( + local_services_business_registration_type, +) +from google.ads.googleads.v24.enums.types import ( + local_services_insurance_rejection_reason, +) +from google.ads.googleads.v24.enums.types import ( + local_services_license_rejection_reason, +) +from google.ads.googleads.v24.enums.types import ( + local_services_verification_artifact_status, +) +from google.ads.googleads.v24.enums.types import ( + local_services_verification_artifact_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "LocalServicesVerificationArtifact", + "BackgroundCheckVerificationArtifact", + "InsuranceVerificationArtifact", + "LicenseVerificationArtifact", + "BusinessRegistrationCheckVerificationArtifact", + "BusinessRegistrationNumber", + "BusinessRegistrationDocument", + }, +) + + +class LocalServicesVerificationArtifact(proto.Message): + r"""A local services verification resource. + + 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: + resource_name (str): + Immutable. The resource name of the Local Services + Verification. Local Services Verification resource names + have the form: + + ``customers/{customer_id}/localServicesVerificationArtifacts/{verification_artifact_id}`` + id (int): + Output only. The ID of the verification + artifact. + + This field is a member of `oneof`_ ``_id``. + creation_date_time (str): + Output only. The timestamp when this + verification artifact was created. The format is + "YYYY-MM-DD HH:MM:SS" in the Google Ads + account's timezone. Examples: "2018-03-05 + 09:15:00" or "2018-02-01 14:34:30". + status (google.ads.googleads.v24.enums.types.LocalServicesVerificationArtifactStatusEnum.LocalServicesVerificationArtifactStatus): + Output only. The status of the verification + artifact. + artifact_type (google.ads.googleads.v24.enums.types.LocalServicesVerificationArtifactTypeEnum.LocalServicesVerificationArtifactType): + Output only. The type of the verification + artifact. + background_check_verification_artifact (google.ads.googleads.v24.resources.types.BackgroundCheckVerificationArtifact): + Output only. A background check verification + artifact. + + This field is a member of `oneof`_ ``artifact_data``. + insurance_verification_artifact (google.ads.googleads.v24.resources.types.InsuranceVerificationArtifact): + Output only. An insurance verification + artifact. + + This field is a member of `oneof`_ ``artifact_data``. + license_verification_artifact (google.ads.googleads.v24.resources.types.LicenseVerificationArtifact): + Output only. A license verification artifact. + + This field is a member of `oneof`_ ``artifact_data``. + business_registration_check_verification_artifact (google.ads.googleads.v24.resources.types.BusinessRegistrationCheckVerificationArtifact): + Output only. A business registration check + verification artifact. + + This field is a member of `oneof`_ ``artifact_data``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + creation_date_time: str = proto.Field( + proto.STRING, + number=3, + ) + status: ( + local_services_verification_artifact_status.LocalServicesVerificationArtifactStatusEnum.LocalServicesVerificationArtifactStatus + ) = proto.Field( + proto.ENUM, + number=4, + enum=local_services_verification_artifact_status.LocalServicesVerificationArtifactStatusEnum.LocalServicesVerificationArtifactStatus, + ) + artifact_type: ( + local_services_verification_artifact_type.LocalServicesVerificationArtifactTypeEnum.LocalServicesVerificationArtifactType + ) = proto.Field( + proto.ENUM, + number=5, + enum=local_services_verification_artifact_type.LocalServicesVerificationArtifactTypeEnum.LocalServicesVerificationArtifactType, + ) + background_check_verification_artifact: ( + "BackgroundCheckVerificationArtifact" + ) = proto.Field( + proto.MESSAGE, + number=6, + oneof="artifact_data", + message="BackgroundCheckVerificationArtifact", + ) + insurance_verification_artifact: "InsuranceVerificationArtifact" = ( + proto.Field( + proto.MESSAGE, + number=7, + oneof="artifact_data", + message="InsuranceVerificationArtifact", + ) + ) + license_verification_artifact: "LicenseVerificationArtifact" = proto.Field( + proto.MESSAGE, + number=8, + oneof="artifact_data", + message="LicenseVerificationArtifact", + ) + business_registration_check_verification_artifact: ( + "BusinessRegistrationCheckVerificationArtifact" + ) = proto.Field( + proto.MESSAGE, + number=9, + oneof="artifact_data", + message="BusinessRegistrationCheckVerificationArtifact", + ) + + +class BackgroundCheckVerificationArtifact(proto.Message): + r"""A proto holding information specific to local services + background check. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + case_url (str): + Output only. URL to access background case. + + This field is a member of `oneof`_ ``_case_url``. + final_adjudication_date_time (str): + Output only. The timestamp when this + background check case result was adjudicated. + The format is "YYYY-MM-DD HH:MM:SS" in the + Google Ads account's timezone. Examples: + "2018-03-05 09:15:00" or "2018-02-01 14:34:30". + + This field is a member of `oneof`_ ``_final_adjudication_date_time``. + """ + + case_url: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + final_adjudication_date_time: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class InsuranceVerificationArtifact(proto.Message): + r"""A proto holding information specific to a local services + insurance. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + amount_micros (int): + Output only. Insurance amount. This is + measured in "micros" of the currency mentioned + in the insurance document. + + This field is a member of `oneof`_ ``_amount_micros``. + rejection_reason (google.ads.googleads.v24.enums.types.LocalServicesInsuranceRejectionReasonEnum.LocalServicesInsuranceRejectionReason): + Output only. Insurance document's rejection + reason. + + This field is a member of `oneof`_ ``_rejection_reason``. + insurance_document_readonly (google.ads.googleads.v24.common.types.LocalServicesDocumentReadOnly): + Output only. The readonly field containing + the information for an uploaded insurance + document. + + This field is a member of `oneof`_ ``_insurance_document_readonly``. + expiration_date_time (str): + Output only. The timestamp when this + insurance expires. The format is "YYYY-MM-DD + HH:MM:SS" in the Google Ads account's timezone. + Examples: "2018-03-05 09:15:00" or "2018-02-01 + 14:34:30". + + This field is a member of `oneof`_ ``_expiration_date_time``. + """ + + amount_micros: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + rejection_reason: ( + local_services_insurance_rejection_reason.LocalServicesInsuranceRejectionReasonEnum.LocalServicesInsuranceRejectionReason + ) = proto.Field( + proto.ENUM, + number=2, + optional=True, + enum=local_services_insurance_rejection_reason.LocalServicesInsuranceRejectionReasonEnum.LocalServicesInsuranceRejectionReason, + ) + insurance_document_readonly: ( + local_services.LocalServicesDocumentReadOnly + ) = proto.Field( + proto.MESSAGE, + number=3, + optional=True, + message=local_services.LocalServicesDocumentReadOnly, + ) + expiration_date_time: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + + +class LicenseVerificationArtifact(proto.Message): + r"""A proto holding information specific to a local services + license. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + license_type (str): + Output only. License type / name. + + This field is a member of `oneof`_ ``_license_type``. + license_number (str): + Output only. License number. + + This field is a member of `oneof`_ ``_license_number``. + licensee_first_name (str): + Output only. First name of the licensee. + + This field is a member of `oneof`_ ``_licensee_first_name``. + licensee_last_name (str): + Output only. Last name of the licensee. + + This field is a member of `oneof`_ ``_licensee_last_name``. + rejection_reason (google.ads.googleads.v24.enums.types.LocalServicesLicenseRejectionReasonEnum.LocalServicesLicenseRejectionReason): + Output only. License rejection reason. + + This field is a member of `oneof`_ ``_rejection_reason``. + license_document_readonly (google.ads.googleads.v24.common.types.LocalServicesDocumentReadOnly): + Output only. The readonly field containing + the information for an uploaded license + document. + + This field is a member of `oneof`_ ``_license_document_readonly``. + expiration_date_time (str): + Output only. The timestamp when this license + expires. The format is "YYYY-MM-DD HH:MM:SS" in + the Google Ads account's timezone. Examples: + "2018-03-05 09:15:00" or "2018-02-01 14:34:30". + + This field is a member of `oneof`_ ``_expiration_date_time``. + """ + + license_type: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + license_number: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + licensee_first_name: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + licensee_last_name: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + rejection_reason: ( + local_services_license_rejection_reason.LocalServicesLicenseRejectionReasonEnum.LocalServicesLicenseRejectionReason + ) = proto.Field( + proto.ENUM, + number=5, + optional=True, + enum=local_services_license_rejection_reason.LocalServicesLicenseRejectionReasonEnum.LocalServicesLicenseRejectionReason, + ) + license_document_readonly: local_services.LocalServicesDocumentReadOnly = ( + proto.Field( + proto.MESSAGE, + number=6, + optional=True, + message=local_services.LocalServicesDocumentReadOnly, + ) + ) + expiration_date_time: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + + +class BusinessRegistrationCheckVerificationArtifact(proto.Message): + r"""A proto holding information specific to a local services + business registration check. + + 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: + registration_type (google.ads.googleads.v24.enums.types.LocalServicesBusinessRegistrationTypeEnum.LocalServicesBusinessRegistrationType): + Output only. The type of business + registration check (number, document). + + This field is a member of `oneof`_ ``_registration_type``. + check_id (str): + Output only. The id of the check, such as vat_tax_id, + representing "VAT Tax ID" requirement. + + This field is a member of `oneof`_ ``_check_id``. + rejection_reason (google.ads.googleads.v24.enums.types.LocalServicesBusinessRegistrationCheckRejectionReasonEnum.LocalServicesBusinessRegistrationCheckRejectionReason): + Output only. Registration document rejection + reason. + + This field is a member of `oneof`_ ``_rejection_reason``. + registration_number (google.ads.googleads.v24.resources.types.BusinessRegistrationNumber): + Output only. Message storing government + issued number for the business. + + This field is a member of `oneof`_ ``business_registration``. + registration_document (google.ads.googleads.v24.resources.types.BusinessRegistrationDocument): + Output only. Message storing document info + for the business. + + This field is a member of `oneof`_ ``business_registration``. + """ + + registration_type: ( + local_services_business_registration_type.LocalServicesBusinessRegistrationTypeEnum.LocalServicesBusinessRegistrationType + ) = proto.Field( + proto.ENUM, + number=3, + optional=True, + enum=local_services_business_registration_type.LocalServicesBusinessRegistrationTypeEnum.LocalServicesBusinessRegistrationType, + ) + check_id: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + rejection_reason: ( + local_services_business_registration_check_rejection_reason.LocalServicesBusinessRegistrationCheckRejectionReasonEnum.LocalServicesBusinessRegistrationCheckRejectionReason + ) = proto.Field( + proto.ENUM, + number=5, + optional=True, + enum=local_services_business_registration_check_rejection_reason.LocalServicesBusinessRegistrationCheckRejectionReasonEnum.LocalServicesBusinessRegistrationCheckRejectionReason, + ) + registration_number: "BusinessRegistrationNumber" = proto.Field( + proto.MESSAGE, + number=1, + oneof="business_registration", + message="BusinessRegistrationNumber", + ) + registration_document: "BusinessRegistrationDocument" = proto.Field( + proto.MESSAGE, + number=2, + oneof="business_registration", + message="BusinessRegistrationDocument", + ) + + +class BusinessRegistrationNumber(proto.Message): + r"""A proto holding information specific to a local services + business registration number. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + number (str): + Output only. Government-issued number for the + business. + + This field is a member of `oneof`_ ``_number``. + """ + + number: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class BusinessRegistrationDocument(proto.Message): + r"""A proto holding information specific to a local services + business registration document. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + document_readonly (google.ads.googleads.v24.common.types.LocalServicesDocumentReadOnly): + Output only. The readonly field containing + the information for an uploaded business + registration document. + + This field is a member of `oneof`_ ``_document_readonly``. + """ + + document_readonly: local_services.LocalServicesDocumentReadOnly = ( + proto.Field( + proto.MESSAGE, + number=1, + optional=True, + message=local_services.LocalServicesDocumentReadOnly, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/location_interest_view.py b/google/ads/googleads/v24/resources/types/location_interest_view.py new file mode 100644 index 000000000..eace2b005 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/location_interest_view.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "LocationInterestView", + }, +) + + +class LocationInterestView(proto.Message): + r"""A location interest view summarizes the performance of + adgroup location interest criteria. + + Attributes: + resource_name (str): + Output only. The resource name of the location interest + view. Location interest view resource names have the form: + + ``customers/{customer_id}/locationInterestViews/{campaign_id}~{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/location_view.py b/google/ads/googleads/v24/resources/types/location_view.py new file mode 100644 index 000000000..ac682b9a6 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/location_view.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "LocationView", + }, +) + + +class LocationView(proto.Message): + r"""A location view summarizes the performance of campaigns by a + Location criterion. If no Location criterion is set, no results are + returned; instead, use geographic_view or user_location_view for + visitor location data. + + Attributes: + resource_name (str): + Output only. The resource name of the location view. + Location view resource names have the form: + + ``customers/{customer_id}/locationViews/{campaign_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/managed_placement_view.py b/google/ads/googleads/v24/resources/types/managed_placement_view.py new file mode 100644 index 000000000..c7076c185 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/managed_placement_view.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ManagedPlacementView", + }, +) + + +class ManagedPlacementView(proto.Message): + r"""A managed placement view. + + Attributes: + resource_name (str): + Output only. The resource name of the Managed Placement + view. Managed placement view resource names have the form: + + ``customers/{customer_id}/managedPlacementViews/{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/matched_location_interest_view.py b/google/ads/googleads/v24/resources/types/matched_location_interest_view.py new file mode 100644 index 000000000..68e5d1001 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/matched_location_interest_view.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "MatchedLocationInterestView", + }, +) + + +class MatchedLocationInterestView(proto.Message): + r"""A view that reports metrics for locations where users showed + interest, and which matched the advertiser's location interest + targeting (defined as geo targets at the AdGroup level). The + data is aggregated at the country level by default. This view is + currently only available for AI Max campaigns. + + Attributes: + resource_name (str): + Output only. The resource name of the matched location + interest view. Matched location interest view resource names + have the form: + + ``customers/{customer_id}/matchedLocationInterestViews/{country_criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/media_file.py b/google/ads/googleads/v24/resources/types/media_file.py new file mode 100644 index 000000000..5d168884d --- /dev/null +++ b/google/ads/googleads/v24/resources/types/media_file.py @@ -0,0 +1,307 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import media_type +from google.ads.googleads.v24.enums.types import mime_type as gage_mime_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "MediaFile", + "MediaImage", + "MediaBundle", + "MediaAudio", + "MediaVideo", + }, +) + + +class MediaFile(proto.Message): + r"""A media file. + + 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: + resource_name (str): + Immutable. The resource name of the media file. Media file + resource names have the form: + + ``customers/{customer_id}/mediaFiles/{media_file_id}`` + id (int): + Output only. The ID of the media file. + + This field is a member of `oneof`_ ``_id``. + type_ (google.ads.googleads.v24.enums.types.MediaTypeEnum.MediaType): + Immutable. Type of the media file. + mime_type (google.ads.googleads.v24.enums.types.MimeTypeEnum.MimeType): + Output only. The mime type of the media file. + source_url (str): + Immutable. The URL of where the original + media file was downloaded from (or a file name). + Only used for media of type AUDIO and IMAGE. + + This field is a member of `oneof`_ ``_source_url``. + name (str): + Immutable. The name of the media file. The + name can be used by clients to help identify + previously uploaded media. + + This field is a member of `oneof`_ ``_name``. + file_size (int): + Output only. The size of the media file in + bytes. + + This field is a member of `oneof`_ ``_file_size``. + image (google.ads.googleads.v24.resources.types.MediaImage): + Immutable. Encapsulates an Image. + + This field is a member of `oneof`_ ``mediatype``. + media_bundle (google.ads.googleads.v24.resources.types.MediaBundle): + Immutable. A ZIP archive media the content of + which contains HTML5 assets. + + This field is a member of `oneof`_ ``mediatype``. + audio (google.ads.googleads.v24.resources.types.MediaAudio): + Output only. Encapsulates an Audio. + + This field is a member of `oneof`_ ``mediatype``. + video (google.ads.googleads.v24.resources.types.MediaVideo): + Immutable. Encapsulates a Video. + + This field is a member of `oneof`_ ``mediatype``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=12, + optional=True, + ) + type_: media_type.MediaTypeEnum.MediaType = proto.Field( + proto.ENUM, + number=5, + enum=media_type.MediaTypeEnum.MediaType, + ) + mime_type: gage_mime_type.MimeTypeEnum.MimeType = proto.Field( + proto.ENUM, + number=6, + enum=gage_mime_type.MimeTypeEnum.MimeType, + ) + source_url: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + file_size: int = proto.Field( + proto.INT64, + number=15, + optional=True, + ) + image: "MediaImage" = proto.Field( + proto.MESSAGE, + number=3, + oneof="mediatype", + message="MediaImage", + ) + media_bundle: "MediaBundle" = proto.Field( + proto.MESSAGE, + number=4, + oneof="mediatype", + message="MediaBundle", + ) + audio: "MediaAudio" = proto.Field( + proto.MESSAGE, + number=10, + oneof="mediatype", + message="MediaAudio", + ) + video: "MediaVideo" = proto.Field( + proto.MESSAGE, + number=11, + oneof="mediatype", + message="MediaVideo", + ) + + +class MediaImage(proto.Message): + r"""Encapsulates an Image. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + data (bytes): + Immutable. Raw image data. + + This field is a member of `oneof`_ ``_data``. + full_size_image_url (str): + Output only. The url to the full size version + of the image. + + This field is a member of `oneof`_ ``_full_size_image_url``. + preview_size_image_url (str): + Output only. The url to the preview size + version of the image. + + This field is a member of `oneof`_ ``_preview_size_image_url``. + """ + + data: bytes = proto.Field( + proto.BYTES, + number=4, + optional=True, + ) + full_size_image_url: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + preview_size_image_url: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + + +class MediaBundle(proto.Message): + r"""Represents a ZIP archive media the content of which contains + HTML5 assets. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + data (bytes): + Immutable. Raw zipped data. + + This field is a member of `oneof`_ ``_data``. + url (str): + Output only. The url to access the uploaded + zipped data. For example, + https://tpc.googlesyndication.com/simgad/123 + This field is read-only. + + This field is a member of `oneof`_ ``_url``. + """ + + data: bytes = proto.Field( + proto.BYTES, + number=3, + optional=True, + ) + url: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class MediaAudio(proto.Message): + r"""Encapsulates an Audio. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + ad_duration_millis (int): + Output only. The duration of the Audio in + milliseconds. + + This field is a member of `oneof`_ ``_ad_duration_millis``. + """ + + ad_duration_millis: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + +class MediaVideo(proto.Message): + r"""Encapsulates a Video. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + ad_duration_millis (int): + Output only. The duration of the Video in + milliseconds. + + This field is a member of `oneof`_ ``_ad_duration_millis``. + youtube_video_id (str): + Immutable. The YouTube video ID (as seen in + YouTube URLs). Adding prefix + "https://www.youtube.com/watch?v=" to this ID + will get the YouTube streaming URL for this + video. + + This field is a member of `oneof`_ ``_youtube_video_id``. + advertising_id_code (str): + Output only. The Advertising Digital + Identification code for this video, as defined + by the American Association of Advertising + Agencies, used mainly for television + commercials. + + This field is a member of `oneof`_ ``_advertising_id_code``. + isci_code (str): + Output only. The Industry Standard Commercial + Identifier code for this video, used mainly for + television commercials. + + This field is a member of `oneof`_ ``_isci_code``. + """ + + ad_duration_millis: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + youtube_video_id: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + advertising_id_code: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + isci_code: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/mobile_app_category_constant.py b/google/ads/googleads/v24/resources/types/mobile_app_category_constant.py new file mode 100644 index 000000000..15c6ac547 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/mobile_app_category_constant.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "MobileAppCategoryConstant", + }, +) + + +class MobileAppCategoryConstant(proto.Message): + r"""A mobile application category constant. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the mobile app category + constant. Mobile app category constant resource names have + the form: + + ``mobileAppCategoryConstants/{mobile_app_category_id}`` + id (int): + Output only. The ID of the mobile app + category constant. + + This field is a member of `oneof`_ ``_id``. + name (str): + Output only. Mobile app category name. + + This field is a member of `oneof`_ ``_name``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT32, + number=4, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/mobile_device_constant.py b/google/ads/googleads/v24/resources/types/mobile_device_constant.py new file mode 100644 index 000000000..9494aa4ff --- /dev/null +++ b/google/ads/googleads/v24/resources/types/mobile_device_constant.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import mobile_device_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "MobileDeviceConstant", + }, +) + + +class MobileDeviceConstant(proto.Message): + r"""A mobile device constant. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the mobile device + constant. Mobile device constant resource names have the + form: + + ``mobileDeviceConstants/{criterion_id}`` + id (int): + Output only. The ID of the mobile device + constant. + + This field is a member of `oneof`_ ``_id``. + name (str): + Output only. The name of the mobile device. + + This field is a member of `oneof`_ ``_name``. + manufacturer_name (str): + Output only. The manufacturer of the mobile + device. + + This field is a member of `oneof`_ ``_manufacturer_name``. + operating_system_name (str): + Output only. The operating system of the + mobile device. + + This field is a member of `oneof`_ ``_operating_system_name``. + type_ (google.ads.googleads.v24.enums.types.MobileDeviceTypeEnum.MobileDeviceType): + Output only. The type of mobile device. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + manufacturer_name: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + operating_system_name: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + type_: mobile_device_type.MobileDeviceTypeEnum.MobileDeviceType = ( + proto.Field( + proto.ENUM, + number=6, + enum=mobile_device_type.MobileDeviceTypeEnum.MobileDeviceType, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/offline_conversion_upload_client_summary.py b/google/ads/googleads/v24/resources/types/offline_conversion_upload_client_summary.py new file mode 100644 index 000000000..6523eb7fa --- /dev/null +++ b/google/ads/googleads/v24/resources/types/offline_conversion_upload_client_summary.py @@ -0,0 +1,383 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + offline_conversion_diagnostic_status_enum, +) +from google.ads.googleads.v24.enums.types import ( + offline_event_upload_client_enum, +) +from google.ads.googleads.v24.errors.types import ( + collection_size_error as gage_collection_size_error, +) +from google.ads.googleads.v24.errors.types import ( + conversion_adjustment_upload_error as gage_conversion_adjustment_upload_error, +) +from google.ads.googleads.v24.errors.types import ( + conversion_upload_error as gage_conversion_upload_error, +) +from google.ads.googleads.v24.errors.types import date_error as gage_date_error +from google.ads.googleads.v24.errors.types import ( + distinct_error as gage_distinct_error, +) +from google.ads.googleads.v24.errors.types import ( + field_error as gage_field_error, +) +from google.ads.googleads.v24.errors.types import ( + mutate_error as gage_mutate_error, +) +from google.ads.googleads.v24.errors.types import ( + not_allowlisted_error as gage_not_allowlisted_error, +) +from google.ads.googleads.v24.errors.types import ( + string_format_error as gage_string_format_error, +) +from google.ads.googleads.v24.errors.types import ( + string_length_error as gage_string_length_error, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "OfflineConversionUploadClientSummary", + "OfflineConversionSummary", + "OfflineConversionAlert", + "OfflineConversionError", + }, +) + + +class OfflineConversionUploadClientSummary(proto.Message): + r"""Offline conversion upload summary at customer level. + + Attributes: + resource_name (str): + Output only. The resource name of the offline conversion + upload summary at customer level. Offline conversion upload + client summary resource names have the form: + + ``customers/{customer_id}/offlineConversionUploadClientSummaries/{client}`` + client (google.ads.googleads.v24.enums.types.OfflineEventUploadClientEnum.OfflineEventUploadClient): + Output only. Client type of the upload event. + status (google.ads.googleads.v24.enums.types.OfflineConversionDiagnosticStatusEnum.OfflineConversionDiagnosticStatus): + Output only. Overall status for offline + conversion client summary. Status is generated + from most recent calendar day with upload stats. + total_event_count (int): + Output only. Total count of uploaded events. + successful_event_count (int): + Output only. Total count of successful + uploaded events. + success_rate (float): + Output only. Successful rate. + pending_event_count (int): + Output only. Total count of pending uploaded + events. + pending_rate (float): + Output only. The ratio of total pending + events to total events. + last_upload_date_time (str): + Output only. Date for the latest upload + batch. The format is "yyyy-mm-dd hh:mm:ss", and + it's in the time zone of the Google Ads account. + daily_summaries (MutableSequence[google.ads.googleads.v24.resources.types.OfflineConversionSummary]): + Output only. Summary of history stats by last + N days. + job_summaries (MutableSequence[google.ads.googleads.v24.resources.types.OfflineConversionSummary]): + Output only. Summary of history stats by last + N jobs. + alerts (MutableSequence[google.ads.googleads.v24.resources.types.OfflineConversionAlert]): + Output only. Details for each error code. + Alerts are generated from most recent calendar + day with upload stats. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + client: ( + offline_event_upload_client_enum.OfflineEventUploadClientEnum.OfflineEventUploadClient + ) = proto.Field( + proto.ENUM, + number=2, + enum=offline_event_upload_client_enum.OfflineEventUploadClientEnum.OfflineEventUploadClient, + ) + status: ( + offline_conversion_diagnostic_status_enum.OfflineConversionDiagnosticStatusEnum.OfflineConversionDiagnosticStatus + ) = proto.Field( + proto.ENUM, + number=3, + enum=offline_conversion_diagnostic_status_enum.OfflineConversionDiagnosticStatusEnum.OfflineConversionDiagnosticStatus, + ) + total_event_count: int = proto.Field( + proto.INT64, + number=4, + ) + successful_event_count: int = proto.Field( + proto.INT64, + number=5, + ) + success_rate: float = proto.Field( + proto.DOUBLE, + number=6, + ) + pending_event_count: int = proto.Field( + proto.INT64, + number=11, + ) + pending_rate: float = proto.Field( + proto.DOUBLE, + number=12, + ) + last_upload_date_time: str = proto.Field( + proto.STRING, + number=7, + ) + daily_summaries: MutableSequence["OfflineConversionSummary"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=8, + message="OfflineConversionSummary", + ) + ) + job_summaries: MutableSequence["OfflineConversionSummary"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=9, + message="OfflineConversionSummary", + ) + ) + alerts: MutableSequence["OfflineConversionAlert"] = proto.RepeatedField( + proto.MESSAGE, + number=10, + message="OfflineConversionAlert", + ) + + +class OfflineConversionSummary(proto.Message): + r"""Historical upload summary, grouped by upload date or job. + + 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: + successful_count (int): + Output only. Total count of successful event. + failed_count (int): + Output only. Total count of failed event. + pending_count (int): + Output only. Total count of pending uploaded + event. + job_id (int): + Output only. Dimension key for last N jobs. + + This field is a member of `oneof`_ ``dimension_key``. + upload_date (str): + Output only. Dimension key for last N days. + + This field is a member of `oneof`_ ``dimension_key``. + """ + + successful_count: int = proto.Field( + proto.INT64, + number=3, + ) + failed_count: int = proto.Field( + proto.INT64, + number=4, + ) + pending_count: int = proto.Field( + proto.INT64, + number=5, + ) + job_id: int = proto.Field( + proto.INT64, + number=1, + oneof="dimension_key", + ) + upload_date: str = proto.Field( + proto.STRING, + number=2, + oneof="dimension_key", + ) + + +class OfflineConversionAlert(proto.Message): + r"""Alert for offline conversion client summary. + + Attributes: + error (google.ads.googleads.v24.resources.types.OfflineConversionError): + Output only. Error for offline conversion + client alert. + error_percentage (float): + Output only. Percentage of the error, the range of this + field should be [0, 1.0]. + """ + + error: "OfflineConversionError" = proto.Field( + proto.MESSAGE, + number=1, + message="OfflineConversionError", + ) + error_percentage: float = proto.Field( + proto.DOUBLE, + number=2, + ) + + +class OfflineConversionError(proto.Message): + r"""Possible errors for offline conversion client summary. + + 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: + collection_size_error (google.ads.googleads.v24.errors.types.CollectionSizeErrorEnum.CollectionSizeError): + Output only. Collection size error. + + This field is a member of `oneof`_ ``error_code``. + conversion_adjustment_upload_error (google.ads.googleads.v24.errors.types.ConversionAdjustmentUploadErrorEnum.ConversionAdjustmentUploadError): + Output only. Conversion adjustment upload + error. + + This field is a member of `oneof`_ ``error_code``. + conversion_upload_error (google.ads.googleads.v24.errors.types.ConversionUploadErrorEnum.ConversionUploadError): + Output only. Conversion upload error. + + This field is a member of `oneof`_ ``error_code``. + date_error (google.ads.googleads.v24.errors.types.DateErrorEnum.DateError): + Output only. Date error. + + This field is a member of `oneof`_ ``error_code``. + distinct_error (google.ads.googleads.v24.errors.types.DistinctErrorEnum.DistinctError): + Output only. Distinct error. + + This field is a member of `oneof`_ ``error_code``. + field_error (google.ads.googleads.v24.errors.types.FieldErrorEnum.FieldError): + Output only. Field error. + + This field is a member of `oneof`_ ``error_code``. + mutate_error (google.ads.googleads.v24.errors.types.MutateErrorEnum.MutateError): + Output only. Mutate error. + + This field is a member of `oneof`_ ``error_code``. + not_allowlisted_error (google.ads.googleads.v24.errors.types.NotAllowlistedErrorEnum.NotAllowlistedError): + Output only. Not allowlisted error. + + This field is a member of `oneof`_ ``error_code``. + string_format_error (google.ads.googleads.v24.errors.types.StringFormatErrorEnum.StringFormatError): + Output only. String format error. + + This field is a member of `oneof`_ ``error_code``. + string_length_error (google.ads.googleads.v24.errors.types.StringLengthErrorEnum.StringLengthError): + Output only. String length error. + + This field is a member of `oneof`_ ``error_code``. + """ + + collection_size_error: ( + gage_collection_size_error.CollectionSizeErrorEnum.CollectionSizeError + ) = proto.Field( + proto.ENUM, + number=1, + oneof="error_code", + enum=gage_collection_size_error.CollectionSizeErrorEnum.CollectionSizeError, + ) + conversion_adjustment_upload_error: ( + gage_conversion_adjustment_upload_error.ConversionAdjustmentUploadErrorEnum.ConversionAdjustmentUploadError + ) = proto.Field( + proto.ENUM, + number=2, + oneof="error_code", + enum=gage_conversion_adjustment_upload_error.ConversionAdjustmentUploadErrorEnum.ConversionAdjustmentUploadError, + ) + conversion_upload_error: ( + gage_conversion_upload_error.ConversionUploadErrorEnum.ConversionUploadError + ) = proto.Field( + proto.ENUM, + number=3, + oneof="error_code", + enum=gage_conversion_upload_error.ConversionUploadErrorEnum.ConversionUploadError, + ) + date_error: gage_date_error.DateErrorEnum.DateError = proto.Field( + proto.ENUM, + number=4, + oneof="error_code", + enum=gage_date_error.DateErrorEnum.DateError, + ) + distinct_error: gage_distinct_error.DistinctErrorEnum.DistinctError = ( + proto.Field( + proto.ENUM, + number=5, + oneof="error_code", + enum=gage_distinct_error.DistinctErrorEnum.DistinctError, + ) + ) + field_error: gage_field_error.FieldErrorEnum.FieldError = proto.Field( + proto.ENUM, + number=6, + oneof="error_code", + enum=gage_field_error.FieldErrorEnum.FieldError, + ) + mutate_error: gage_mutate_error.MutateErrorEnum.MutateError = proto.Field( + proto.ENUM, + number=7, + oneof="error_code", + enum=gage_mutate_error.MutateErrorEnum.MutateError, + ) + not_allowlisted_error: ( + gage_not_allowlisted_error.NotAllowlistedErrorEnum.NotAllowlistedError + ) = proto.Field( + proto.ENUM, + number=8, + oneof="error_code", + enum=gage_not_allowlisted_error.NotAllowlistedErrorEnum.NotAllowlistedError, + ) + string_format_error: ( + gage_string_format_error.StringFormatErrorEnum.StringFormatError + ) = proto.Field( + proto.ENUM, + number=9, + oneof="error_code", + enum=gage_string_format_error.StringFormatErrorEnum.StringFormatError, + ) + string_length_error: ( + gage_string_length_error.StringLengthErrorEnum.StringLengthError + ) = proto.Field( + proto.ENUM, + number=10, + oneof="error_code", + enum=gage_string_length_error.StringLengthErrorEnum.StringLengthError, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/offline_conversion_upload_conversion_action_summary.py b/google/ads/googleads/v24/resources/types/offline_conversion_upload_conversion_action_summary.py new file mode 100644 index 000000000..7cd75573f --- /dev/null +++ b/google/ads/googleads/v24/resources/types/offline_conversion_upload_conversion_action_summary.py @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + offline_conversion_diagnostic_status_enum, +) +from google.ads.googleads.v24.enums.types import ( + offline_event_upload_client_enum, +) +from google.ads.googleads.v24.resources.types import ( + offline_conversion_upload_client_summary, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "OfflineConversionUploadConversionActionSummary", + }, +) + + +class OfflineConversionUploadConversionActionSummary(proto.Message): + r"""Offline conversion upload summary at conversion action level. + + Attributes: + resource_name (str): + Output only. The resource name of the offline conversion + upload summary at conversion action level. Offline + conversion upload conversion action summary resource names + have the form: + + ``customers/{customer_id}/offlineConversionUploadConversionActionSummaries/{conversion_action_id}~{client}`` + client (google.ads.googleads.v24.enums.types.OfflineEventUploadClientEnum.OfflineEventUploadClient): + Output only. Client type of the upload event. + conversion_action_id (int): + Output only. Conversion action id. + conversion_action_name (str): + Output only. The name of the conversion + action. + status (google.ads.googleads.v24.enums.types.OfflineConversionDiagnosticStatusEnum.OfflineConversionDiagnosticStatus): + Output only. Overall status for offline + conversion upload conversion action summary. + Status is generated from most recent calendar + day with upload stats. + total_event_count (int): + Output only. Total count of uploaded events. + successful_event_count (int): + Output only. Total count of successful + uploaded events. + pending_event_count (int): + Output only. Total count of pending uploaded + events. + last_upload_date_time (str): + Output only. Date for the latest upload + batch. The format is "yyyy-mm-dd hh:mm:ss", and + it's in the time zone of the Google Ads account. + daily_summaries (MutableSequence[google.ads.googleads.v24.resources.types.OfflineConversionSummary]): + Output only. Summary of history stats by last + N days. + job_summaries (MutableSequence[google.ads.googleads.v24.resources.types.OfflineConversionSummary]): + Output only. Summary of history stats by last + N jobs. + alerts (MutableSequence[google.ads.googleads.v24.resources.types.OfflineConversionAlert]): + Output only. Details for each error code. + Alerts are generated from most recent calendar + day with upload stats. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + client: ( + offline_event_upload_client_enum.OfflineEventUploadClientEnum.OfflineEventUploadClient + ) = proto.Field( + proto.ENUM, + number=2, + enum=offline_event_upload_client_enum.OfflineEventUploadClientEnum.OfflineEventUploadClient, + ) + conversion_action_id: int = proto.Field( + proto.INT64, + number=3, + ) + conversion_action_name: str = proto.Field( + proto.STRING, + number=4, + ) + status: ( + offline_conversion_diagnostic_status_enum.OfflineConversionDiagnosticStatusEnum.OfflineConversionDiagnosticStatus + ) = proto.Field( + proto.ENUM, + number=5, + enum=offline_conversion_diagnostic_status_enum.OfflineConversionDiagnosticStatusEnum.OfflineConversionDiagnosticStatus, + ) + total_event_count: int = proto.Field( + proto.INT64, + number=6, + ) + successful_event_count: int = proto.Field( + proto.INT64, + number=7, + ) + pending_event_count: int = proto.Field( + proto.INT64, + number=8, + ) + last_upload_date_time: str = proto.Field( + proto.STRING, + number=9, + ) + daily_summaries: MutableSequence[ + offline_conversion_upload_client_summary.OfflineConversionSummary + ] = proto.RepeatedField( + proto.MESSAGE, + number=10, + message=offline_conversion_upload_client_summary.OfflineConversionSummary, + ) + job_summaries: MutableSequence[ + offline_conversion_upload_client_summary.OfflineConversionSummary + ] = proto.RepeatedField( + proto.MESSAGE, + number=11, + message=offline_conversion_upload_client_summary.OfflineConversionSummary, + ) + alerts: MutableSequence[ + offline_conversion_upload_client_summary.OfflineConversionAlert + ] = proto.RepeatedField( + proto.MESSAGE, + number=12, + message=offline_conversion_upload_client_summary.OfflineConversionAlert, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/offline_user_data_job.py b/google/ads/googleads/v24/resources/types/offline_user_data_job.py new file mode 100644 index 000000000..3b5113598 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/offline_user_data_job.py @@ -0,0 +1,170 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import offline_user_data +from google.ads.googleads.v24.enums.types import ( + offline_user_data_job_failure_reason, +) +from google.ads.googleads.v24.enums.types import ( + offline_user_data_job_match_rate_range, +) +from google.ads.googleads.v24.enums.types import offline_user_data_job_status +from google.ads.googleads.v24.enums.types import offline_user_data_job_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "OfflineUserDataJob", + "OfflineUserDataJobMetadata", + }, +) + + +class OfflineUserDataJob(proto.Message): + r"""A job containing offline user data of store visitors, or user + list members that will be processed asynchronously. The uploaded + data isn't readable and the processing results of the job can + only be read using GoogleAdsService.Search/SearchStream. + + 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: + resource_name (str): + Immutable. The resource name of the offline user data job. + Offline user data job resource names have the form: + + ``customers/{customer_id}/offlineUserDataJobs/{offline_user_data_job_id}`` + id (int): + Output only. ID of this offline user data + job. + + This field is a member of `oneof`_ ``_id``. + external_id (int): + Immutable. User specified job ID. + + This field is a member of `oneof`_ ``_external_id``. + type_ (google.ads.googleads.v24.enums.types.OfflineUserDataJobTypeEnum.OfflineUserDataJobType): + Immutable. Type of the job. + status (google.ads.googleads.v24.enums.types.OfflineUserDataJobStatusEnum.OfflineUserDataJobStatus): + Output only. Status of the job. + failure_reason (google.ads.googleads.v24.enums.types.OfflineUserDataJobFailureReasonEnum.OfflineUserDataJobFailureReason): + Output only. Reason for the processing + failure, if status is FAILED. + operation_metadata (google.ads.googleads.v24.resources.types.OfflineUserDataJobMetadata): + Output only. Metadata of offline user data + job depicting match rate range. + customer_match_user_list_metadata (google.ads.googleads.v24.common.types.CustomerMatchUserListMetadata): + Immutable. Metadata for data updates to a + CRM-based user list. + + This field is a member of `oneof`_ ``metadata``. + store_sales_metadata (google.ads.googleads.v24.common.types.StoreSalesMetadata): + Immutable. Metadata for store sales data + update. + + This field is a member of `oneof`_ ``metadata``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + external_id: int = proto.Field( + proto.INT64, + number=10, + optional=True, + ) + type_: ( + offline_user_data_job_type.OfflineUserDataJobTypeEnum.OfflineUserDataJobType + ) = proto.Field( + proto.ENUM, + number=4, + enum=offline_user_data_job_type.OfflineUserDataJobTypeEnum.OfflineUserDataJobType, + ) + status: ( + offline_user_data_job_status.OfflineUserDataJobStatusEnum.OfflineUserDataJobStatus + ) = proto.Field( + proto.ENUM, + number=5, + enum=offline_user_data_job_status.OfflineUserDataJobStatusEnum.OfflineUserDataJobStatus, + ) + failure_reason: ( + offline_user_data_job_failure_reason.OfflineUserDataJobFailureReasonEnum.OfflineUserDataJobFailureReason + ) = proto.Field( + proto.ENUM, + number=6, + enum=offline_user_data_job_failure_reason.OfflineUserDataJobFailureReasonEnum.OfflineUserDataJobFailureReason, + ) + operation_metadata: "OfflineUserDataJobMetadata" = proto.Field( + proto.MESSAGE, + number=11, + message="OfflineUserDataJobMetadata", + ) + customer_match_user_list_metadata: ( + offline_user_data.CustomerMatchUserListMetadata + ) = proto.Field( + proto.MESSAGE, + number=7, + oneof="metadata", + message=offline_user_data.CustomerMatchUserListMetadata, + ) + store_sales_metadata: offline_user_data.StoreSalesMetadata = proto.Field( + proto.MESSAGE, + number=8, + oneof="metadata", + message=offline_user_data.StoreSalesMetadata, + ) + + +class OfflineUserDataJobMetadata(proto.Message): + r"""Metadata of offline user data job. + + Attributes: + match_rate_range (google.ads.googleads.v24.enums.types.OfflineUserDataJobMatchRateRangeEnum.OfflineUserDataJobMatchRateRange): + Output only. Match rate of the Customer Match + user list upload. Describes the estimated match + rate when the status of the job is "RUNNING" and + final match rate when the final match rate is + available after the status of the job is + "SUCCESS/FAILED". + """ + + match_rate_range: ( + offline_user_data_job_match_rate_range.OfflineUserDataJobMatchRateRangeEnum.OfflineUserDataJobMatchRateRange + ) = proto.Field( + proto.ENUM, + number=1, + enum=offline_user_data_job_match_rate_range.OfflineUserDataJobMatchRateRangeEnum.OfflineUserDataJobMatchRateRange, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/operating_system_version_constant.py b/google/ads/googleads/v24/resources/types/operating_system_version_constant.py new file mode 100644 index 000000000..467893026 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/operating_system_version_constant.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + operating_system_version_operator_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "OperatingSystemVersionConstant", + }, +) + + +class OperatingSystemVersionConstant(proto.Message): + r"""A mobile operating system version or a range of versions, depending + on ``operator_type``. List of available mobile platforms at + https://developers.google.com/google-ads/api/reference/data/codes-formats#mobile-platforms + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the operating system + version constant. Operating system version constant resource + names have the form: + + ``operatingSystemVersionConstants/{criterion_id}`` + id (int): + Output only. The ID of the operating system + version. + + This field is a member of `oneof`_ ``_id``. + name (str): + Output only. Name of the operating system. + + This field is a member of `oneof`_ ``_name``. + os_major_version (int): + Output only. The OS Major Version number. + + This field is a member of `oneof`_ ``_os_major_version``. + os_minor_version (int): + Output only. The OS Minor Version number. + + This field is a member of `oneof`_ ``_os_minor_version``. + operator_type (google.ads.googleads.v24.enums.types.OperatingSystemVersionOperatorTypeEnum.OperatingSystemVersionOperatorType): + Output only. Determines whether this constant + represents a single version or a range of + versions. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + os_major_version: int = proto.Field( + proto.INT32, + number=9, + optional=True, + ) + os_minor_version: int = proto.Field( + proto.INT32, + number=10, + optional=True, + ) + operator_type: ( + operating_system_version_operator_type.OperatingSystemVersionOperatorTypeEnum.OperatingSystemVersionOperatorType + ) = proto.Field( + proto.ENUM, + number=6, + enum=operating_system_version_operator_type.OperatingSystemVersionOperatorTypeEnum.OperatingSystemVersionOperatorType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/paid_organic_search_term_view.py b/google/ads/googleads/v24/resources/types/paid_organic_search_term_view.py new file mode 100644 index 000000000..7886ac353 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/paid_organic_search_term_view.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "PaidOrganicSearchTermView", + }, +) + + +class PaidOrganicSearchTermView(proto.Message): + r"""A paid organic search term view providing a view of search + stats across ads and organic listings aggregated by search term + at the ad group level. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the search term view. + Search term view resource names have the form: + + ``customers/{customer_id}/paidOrganicSearchTermViews/{campaign_id}~ {ad_group_id}~{URL-base64 search term}`` + search_term (str): + Output only. The search term. + + This field is a member of `oneof`_ ``_search_term``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + search_term: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/parental_status_view.py b/google/ads/googleads/v24/resources/types/parental_status_view.py new file mode 100644 index 000000000..b75d3e229 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/parental_status_view.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ParentalStatusView", + }, +) + + +class ParentalStatusView(proto.Message): + r"""A parental status view. + + Attributes: + resource_name (str): + Output only. The resource name of the parental status view. + Parental Status view resource names have the form: + + ``customers/{customer_id}/parentalStatusViews/{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/payments_account.py b/google/ads/googleads/v24/resources/types/payments_account.py new file mode 100644 index 000000000..5354d99cc --- /dev/null +++ b/google/ads/googleads/v24/resources/types/payments_account.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "PaymentsAccount", + }, +) + + +class PaymentsAccount(proto.Message): + r"""A payments account, which can be used to set up billing for + an Ads customer. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the payments account. + PaymentsAccount resource names have the form: + + ``customers/{customer_id}/paymentsAccounts/{payments_account_id}`` + payments_account_id (str): + Output only. A 16 digit ID used to identify a + payments account. + + This field is a member of `oneof`_ ``_payments_account_id``. + name (str): + Output only. The name of the payments + account. + + This field is a member of `oneof`_ ``_name``. + currency_code (str): + Output only. The currency code of the + payments account. A subset of the currency codes + derived from the ISO 4217 standard is supported. + + This field is a member of `oneof`_ ``_currency_code``. + payments_profile_id (str): + Output only. A 12 digit ID used to identify + the payments profile associated with the + payments account. + + This field is a member of `oneof`_ ``_payments_profile_id``. + secondary_payments_profile_id (str): + Output only. A secondary payments profile ID + present in uncommon situations, for example, + when a sequential liability agreement has been + arranged. + + This field is a member of `oneof`_ ``_secondary_payments_profile_id``. + paying_manager_customer (str): + Output only. Paying manager of this payment + account. + + This field is a member of `oneof`_ ``_paying_manager_customer``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + payments_account_id: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + currency_code: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + payments_profile_id: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + secondary_payments_profile_id: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + paying_manager_customer: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/per_store_view.py b/google/ads/googleads/v24/resources/types/per_store_view.py new file mode 100644 index 000000000..c0d76b1b0 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/per_store_view.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "PerStoreView", + }, +) + + +class PerStoreView(proto.Message): + r"""A per store view. + This view provides per store impression reach and local action + conversion stats for advertisers. + + Attributes: + resource_name (str): + Output only. The resource name of the per store view. Per + Store view resource names have the form: + + ``customers/{customer_id}/perStoreViews/{place_id}`` + place_id (str): + Output only. The place ID of the per store + view. + address1 (str): + Output only. First line of the store's + address. + address2 (str): + Output only. Second line of the store's + address. + business_name (str): + Output only. The name of the business. + city (str): + Output only. The city where the store is + located. + country_code (str): + Output only. The two-letter country code for + the store's location (e.g., "US"). + phone_number (str): + Output only. The phone number of the store. + postal_code (str): + Output only. The postal code of the store's + address. + province (str): + Output only. The province or state of the + store's address. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + place_id: str = proto.Field( + proto.STRING, + number=2, + ) + address1: str = proto.Field( + proto.STRING, + number=3, + ) + address2: str = proto.Field( + proto.STRING, + number=4, + ) + business_name: str = proto.Field( + proto.STRING, + number=5, + ) + city: str = proto.Field( + proto.STRING, + number=6, + ) + country_code: str = proto.Field( + proto.STRING, + number=7, + ) + phone_number: str = proto.Field( + proto.STRING, + number=8, + ) + postal_code: str = proto.Field( + proto.STRING, + number=9, + ) + province: str = proto.Field( + proto.STRING, + number=10, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/performance_max_placement_view.py b/google/ads/googleads/v24/resources/types/performance_max_placement_view.py new file mode 100644 index 000000000..6ba787562 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/performance_max_placement_view.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + placement_type as gage_placement_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "PerformanceMaxPlacementView", + }, +) + + +class PerformanceMaxPlacementView(proto.Message): + r"""A view with impression metrics for Performance Max campaign + placements. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the Performance Max + placement view. Performance Max placement view resource + names have the form: + + ``customers/{customer_id}/performanceMaxPlacementViews/{base_64_placement}`` + placement (str): + Output only. The default placement string, + such as the website URL, mobile application ID, + or a YouTube video ID. + + This field is a member of `oneof`_ ``_placement``. + display_name (str): + Output only. The name displayed to represent + the placement, such as the URL name for + websites, YouTube video name for YouTube videos, + and translated mobile app name for mobile apps. + + This field is a member of `oneof`_ ``_display_name``. + target_url (str): + Output only. URL of the placement, for + example, website, link to the mobile application + in app store, or a YouTube video URL. + + This field is a member of `oneof`_ ``_target_url``. + placement_type (google.ads.googleads.v24.enums.types.PlacementTypeEnum.PlacementType): + Output only. Type of the placement. Possible values for + Performance Max placements are WEBSITE, MOBILE_APPLICATION, + or YOUTUBE_VIDEO. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + placement: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + display_name: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + target_url: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + placement_type: gage_placement_type.PlacementTypeEnum.PlacementType = ( + proto.Field( + proto.ENUM, + number=5, + enum=gage_placement_type.PlacementTypeEnum.PlacementType, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/product_category_constant.py b/google/ads/googleads/v24/resources/types/product_category_constant.py new file mode 100644 index 000000000..029944aa3 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/product_category_constant.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import product_category_level +from google.ads.googleads.v24.enums.types import product_category_state + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ProductCategoryConstant", + }, +) + + +class ProductCategoryConstant(proto.Message): + r"""A Product Category. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the product category. + Product category resource names have the form: + + ``productCategoryConstants/{level}~{category_id}`` + category_id (int): + Output only. The ID of the product category. + + This ID is equivalent to the google_product_category ID as + described in this article: + https://support.google.com/merchants/answer/6324436. + product_category_constant_parent (str): + Output only. Resource name of the parent + product category. + + This field is a member of `oneof`_ ``_product_category_constant_parent``. + level (google.ads.googleads.v24.enums.types.ProductCategoryLevelEnum.ProductCategoryLevel): + Output only. Level of the product category. + state (google.ads.googleads.v24.enums.types.ProductCategoryStateEnum.ProductCategoryState): + Output only. State of the product category. + localizations (MutableSequence[google.ads.googleads.v24.resources.types.ProductCategoryConstant.ProductCategoryLocalization]): + Output only. List of all available + localizations of the product category. + """ + + class ProductCategoryLocalization(proto.Message): + r"""Localization for the product category. + + Attributes: + region_code (str): + Output only. Upper-case two-letter ISO 3166-1 + country code of the localized category. + language_code (str): + Output only. Two-letter ISO 639-1 language + code of the localized category. + value (str): + Output only. The name of the category in the + specified locale. + """ + + region_code: str = proto.Field( + proto.STRING, + number=1, + ) + language_code: str = proto.Field( + proto.STRING, + number=2, + ) + value: str = proto.Field( + proto.STRING, + number=3, + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + category_id: int = proto.Field( + proto.INT64, + number=2, + ) + product_category_constant_parent: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + level: ( + product_category_level.ProductCategoryLevelEnum.ProductCategoryLevel + ) = proto.Field( + proto.ENUM, + number=4, + enum=product_category_level.ProductCategoryLevelEnum.ProductCategoryLevel, + ) + state: ( + product_category_state.ProductCategoryStateEnum.ProductCategoryState + ) = proto.Field( + proto.ENUM, + number=5, + enum=product_category_state.ProductCategoryStateEnum.ProductCategoryState, + ) + localizations: MutableSequence[ProductCategoryLocalization] = ( + proto.RepeatedField( + proto.MESSAGE, + number=6, + message=ProductCategoryLocalization, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/product_group_view.py b/google/ads/googleads/v24/resources/types/product_group_view.py new file mode 100644 index 000000000..ae393010a --- /dev/null +++ b/google/ads/googleads/v24/resources/types/product_group_view.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ProductGroupView", + }, +) + + +class ProductGroupView(proto.Message): + r"""A product group view. + + Attributes: + resource_name (str): + Output only. The resource name of the product group view. + Product group view resource names have the form: + + ``customers/{customer_id}/productGroupViews/{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/product_link.py b/google/ads/googleads/v24/resources/types/product_link.py new file mode 100644 index 000000000..9f3cd0b2e --- /dev/null +++ b/google/ads/googleads/v24/resources/types/product_link.py @@ -0,0 +1,253 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import linked_product_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ProductLink", + "DataPartnerIdentifier", + "GoogleAdsIdentifier", + "MerchantCenterIdentifier", + "AdvertisingPartnerIdentifier", + "AdvertisingPartnerProperties", + }, +) + + +class ProductLink(proto.Message): + r"""Represents the data sharing connection between a Google + Ads customer and another product. + + 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: + resource_name (str): + Immutable. Resource name of the product link. ProductLink + resource names have the form: + + ``customers/{customer_id}/productLinks/{product_link_id}`` + product_link_id (int): + Output only. The ID of the link. + This field is read only. + + This field is a member of `oneof`_ ``_product_link_id``. + type_ (google.ads.googleads.v24.enums.types.LinkedProductTypeEnum.LinkedProductType): + Output only. The type of the linked product. + data_partner (google.ads.googleads.v24.resources.types.DataPartnerIdentifier): + Immutable. Data partner link. + + This field is a member of `oneof`_ ``linked_product``. + google_ads (google.ads.googleads.v24.resources.types.GoogleAdsIdentifier): + Immutable. Google Ads link. + + This field is a member of `oneof`_ ``linked_product``. + merchant_center (google.ads.googleads.v24.resources.types.MerchantCenterIdentifier): + Immutable. Google Merchant Center link. + + This field is a member of `oneof`_ ``linked_product``. + advertising_partner (google.ads.googleads.v24.resources.types.AdvertisingPartnerIdentifier): + Output only. Advertising Partner link. + + This field is a member of `oneof`_ ``linked_product``. + advertising_partner_properties (google.ads.googleads.v24.resources.types.AdvertisingPartnerProperties): + Output only. Advertising Partner link + properties. These properties are only applicable + when the link is for an Advertising Partner. + + This field is a member of `oneof`_ ``product_link_properties``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + product_link_id: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + type_: linked_product_type.LinkedProductTypeEnum.LinkedProductType = ( + proto.Field( + proto.ENUM, + number=3, + enum=linked_product_type.LinkedProductTypeEnum.LinkedProductType, + ) + ) + data_partner: "DataPartnerIdentifier" = proto.Field( + proto.MESSAGE, + number=4, + oneof="linked_product", + message="DataPartnerIdentifier", + ) + google_ads: "GoogleAdsIdentifier" = proto.Field( + proto.MESSAGE, + number=5, + oneof="linked_product", + message="GoogleAdsIdentifier", + ) + merchant_center: "MerchantCenterIdentifier" = proto.Field( + proto.MESSAGE, + number=12, + oneof="linked_product", + message="MerchantCenterIdentifier", + ) + advertising_partner: "AdvertisingPartnerIdentifier" = proto.Field( + proto.MESSAGE, + number=13, + oneof="linked_product", + message="AdvertisingPartnerIdentifier", + ) + advertising_partner_properties: "AdvertisingPartnerProperties" = ( + proto.Field( + proto.MESSAGE, + number=15, + oneof="product_link_properties", + message="AdvertisingPartnerProperties", + ) + ) + + +class DataPartnerIdentifier(proto.Message): + r"""The identifier for Data Partner account. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + data_partner_id (int): + Immutable. The customer ID of the Data + partner account. This field is required and + should not be empty when creating a new data + partner link. It is unable to be modified after + the creation of the link. + + This field is a member of `oneof`_ ``_data_partner_id``. + """ + + data_partner_id: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + + +class GoogleAdsIdentifier(proto.Message): + r"""The identifier for Google Ads account. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer (str): + Immutable. The resource name of the Google + Ads account. This field is required and should + not be empty when creating a new Google Ads + link. It is unable to be modified after the + creation of the link. + + This field is a member of `oneof`_ ``_customer``. + """ + + customer: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class MerchantCenterIdentifier(proto.Message): + r"""The identifier for Google Merchant Center account + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + merchant_center_id (int): + Immutable. The customer ID of the Google + Merchant Center account. This field is required + and should not be empty when creating a new + Merchant Center link. It is unable to be + modified after the creation of the link. + + This field is a member of `oneof`_ ``_merchant_center_id``. + """ + + merchant_center_id: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + + +class AdvertisingPartnerIdentifier(proto.Message): + r"""The identifier for the Advertising Partner Google Ads + account. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer (str): + Output only. The resource name of the + advertising partner Google Ads account. This + field is required and should not be empty when + creating a new Advertising Partner link. It is + unable to be modified after the creation of the + link. + + This field is a member of `oneof`_ ``_customer``. + """ + + customer: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class AdvertisingPartnerProperties(proto.Message): + r"""Properties specific to an Advertising Partner link. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + allowed_domain (str): + Output only. The allowed domain for the + Advertising Partner link. The advertising + partner will only be able to advertise on this + domain. The field is immutable. + + This field is a member of `oneof`_ ``_allowed_domain``. + """ + + allowed_domain: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/product_link_invitation.py b/google/ads/googleads/v24/resources/types/product_link_invitation.py new file mode 100644 index 000000000..27b623e48 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/product_link_invitation.py @@ -0,0 +1,218 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import linked_product_type +from google.ads.googleads.v24.enums.types import product_link_invitation_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ProductLinkInvitation", + "HotelCenterLinkInvitationIdentifier", + "MerchantCenterLinkInvitationIdentifier", + "AdvertisingPartnerLinkInvitationIdentifier", + "AdvertisingPartnerLinkInvitationProperties", + }, +) + + +class ProductLinkInvitation(proto.Message): + r"""Represents an invitation for data sharing connection between + a Google Ads account and another account. + + 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: + resource_name (str): + Immutable. The resource name of a product link invitation. + Product link invitation resource names have the form: + + ``customers/{customer_id}/productLinkInvitations/{product_link_invitation_id}`` + product_link_invitation_id (int): + Output only. The ID of the product link + invitation. This field is read only. + status (google.ads.googleads.v24.enums.types.ProductLinkInvitationStatusEnum.ProductLinkInvitationStatus): + Output only. The status of the product link + invitation. This field is read only. + type_ (google.ads.googleads.v24.enums.types.LinkedProductTypeEnum.LinkedProductType): + Output only. The type of the invited account. + This field is read only and can be used for + filtering invitations with {@code + GoogleAdsService.SearchGoogleAdsRequest}. + hotel_center (google.ads.googleads.v24.resources.types.HotelCenterLinkInvitationIdentifier): + Output only. Hotel link invitation. + + This field is a member of `oneof`_ ``invited_account``. + merchant_center (google.ads.googleads.v24.resources.types.MerchantCenterLinkInvitationIdentifier): + Output only. Merchant Center link invitation. + + This field is a member of `oneof`_ ``invited_account``. + advertising_partner (google.ads.googleads.v24.resources.types.AdvertisingPartnerLinkInvitationIdentifier): + Output only. Advertising Partner link + invitation. + + This field is a member of `oneof`_ ``invited_account``. + advertising_partner_properties (google.ads.googleads.v24.resources.types.AdvertisingPartnerLinkInvitationProperties): + Output only. Advertising Partner link + invitation properties. These properties are only + applicable when the link is for an Advertising + Partner. + + This field is a member of `oneof`_ ``invited_account_properties``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + product_link_invitation_id: int = proto.Field( + proto.INT64, + number=2, + ) + status: ( + product_link_invitation_status.ProductLinkInvitationStatusEnum.ProductLinkInvitationStatus + ) = proto.Field( + proto.ENUM, + number=3, + enum=product_link_invitation_status.ProductLinkInvitationStatusEnum.ProductLinkInvitationStatus, + ) + type_: linked_product_type.LinkedProductTypeEnum.LinkedProductType = ( + proto.Field( + proto.ENUM, + number=6, + enum=linked_product_type.LinkedProductTypeEnum.LinkedProductType, + ) + ) + hotel_center: "HotelCenterLinkInvitationIdentifier" = proto.Field( + proto.MESSAGE, + number=4, + oneof="invited_account", + message="HotelCenterLinkInvitationIdentifier", + ) + merchant_center: "MerchantCenterLinkInvitationIdentifier" = proto.Field( + proto.MESSAGE, + number=5, + oneof="invited_account", + message="MerchantCenterLinkInvitationIdentifier", + ) + advertising_partner: "AdvertisingPartnerLinkInvitationIdentifier" = ( + proto.Field( + proto.MESSAGE, + number=7, + oneof="invited_account", + message="AdvertisingPartnerLinkInvitationIdentifier", + ) + ) + advertising_partner_properties: ( + "AdvertisingPartnerLinkInvitationProperties" + ) = proto.Field( + proto.MESSAGE, + number=8, + oneof="invited_account_properties", + message="AdvertisingPartnerLinkInvitationProperties", + ) + + +class HotelCenterLinkInvitationIdentifier(proto.Message): + r"""The identifier for Hotel account. + + Attributes: + hotel_center_id (int): + Output only. The hotel center id of the hotel + account. This field is read only + """ + + hotel_center_id: int = proto.Field( + proto.INT64, + number=1, + ) + + +class MerchantCenterLinkInvitationIdentifier(proto.Message): + r"""The identifier for Merchant Center Account. + + Attributes: + merchant_center_id (int): + Output only. The Merchant Center id of the + Merchant account. This field is read only + """ + + merchant_center_id: int = proto.Field( + proto.INT64, + number=1, + ) + + +class AdvertisingPartnerLinkInvitationIdentifier(proto.Message): + r"""The identifier for the Advertising Partner Google Ads + account. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer (str): + Immutable. The resource name of the + advertising partner Google Ads account. This + field is read only. + + This field is a member of `oneof`_ ``_customer``. + """ + + customer: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class AdvertisingPartnerLinkInvitationProperties(proto.Message): + r"""Properties specific to an Advertising Partner link + invitation. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + allowed_domain (str): + Immutable. The allowed domain for the + Advertising Partner link invitation. The + advertising partner will only be able to + advertise on this domain. The field is immutable + after the creation of the link invitation. + + This field is a member of `oneof`_ ``_allowed_domain``. + """ + + allowed_domain: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/qualifying_question.py b/google/ads/googleads/v24/resources/types/qualifying_question.py new file mode 100644 index 000000000..ec942758f --- /dev/null +++ b/google/ads/googleads/v24/resources/types/qualifying_question.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "QualifyingQuestion", + }, +) + + +class QualifyingQuestion(proto.Message): + r"""Qualifying Questions for Lead Form. + + Attributes: + resource_name (str): + Output only. The resource name of the + qualifying question. + 'qualifyingQuestions/{qualifyingQuestionId}' + qualifying_question_id (int): + Output only. The id of the qualifying + question. + locale (str): + Output only. The locale of the qualifying + question. + text (str): + Output only. The qualifying question. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + qualifying_question_id: int = proto.Field( + proto.INT64, + number=2, + ) + locale: str = proto.Field( + proto.STRING, + number=3, + ) + text: str = proto.Field( + proto.STRING, + number=4, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/recommendation.py b/google/ads/googleads/v24/resources/types/recommendation.py new file mode 100644 index 000000000..5cb051cfc --- /dev/null +++ b/google/ads/googleads/v24/resources/types/recommendation.py @@ -0,0 +1,2101 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.enums.types import ad_strength as gage_ad_strength +from google.ads.googleads.v24.enums.types import ( + app_bidding_goal as gage_app_bidding_goal, +) +from google.ads.googleads.v24.enums.types import keyword_match_type +from google.ads.googleads.v24.enums.types import recommendation_type +from google.ads.googleads.v24.enums.types import ( + shopping_add_products_to_campaign_recommendation_enum, +) +from google.ads.googleads.v24.enums.types import ( + target_cpa_opt_in_recommendation_goal, +) +from google.ads.googleads.v24.resources.types import ad as gagr_ad +from google.ads.googleads.v24.resources.types import asset + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "Recommendation", + }, +) + + +class Recommendation(proto.Message): + r"""A recommendation. + + 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: + resource_name (str): + Immutable. The resource name of the recommendation. + + ``customers/{customer_id}/recommendations/{recommendation_id}`` + type_ (google.ads.googleads.v24.enums.types.RecommendationTypeEnum.RecommendationType): + Output only. The type of recommendation. + impact (google.ads.googleads.v24.resources.types.Recommendation.RecommendationImpact): + Output only. The impact on account + performance as a result of applying the + recommendation. + campaign_budget (str): + Output only. The budget targeted by this recommendation. + This will be set only when the recommendation affects a + single campaign budget. + + This field will be set for the following recommendation + types: CAMPAIGN_BUDGET, FORECASTING_CAMPAIGN_BUDGET, + MARGINAL_ROI_CAMPAIGN_BUDGET, MOVE_UNUSED_BUDGET + + This field is a member of `oneof`_ ``_campaign_budget``. + campaign (str): + Output only. The campaign targeted by this recommendation. + + This field will be set for the following recommendation + types: CALL_EXTENSION, CALLOUT_EXTENSION, + ENHANCED_CPC_OPT_IN, USE_BROAD_MATCH_KEYWORD, KEYWORD, + KEYWORD_MATCH_TYPE, + UPGRADE_LOCAL_CAMPAIGN_TO_PERFORMANCE_MAX, + MAXIMIZE_CLICKS_OPT_IN, MAXIMIZE_CONVERSIONS_OPT_IN, + OPTIMIZE_AD_ROTATION, RESPONSIVE_SEARCH_AD, + RESPONSIVE_SEARCH_AD_ASSET, SEARCH_PARTNERS_OPT_IN, + DISPLAY_EXPANSION_OPT_IN, SITELINK_EXTENSION, + TARGET_CPA_OPT_IN, TARGET_ROAS_OPT_IN, TEXT_AD, + UPGRADE_SMART_SHOPPING_CAMPAIGN_TO_PERFORMANCE_MAX, + RAISE_TARGET_CPA_BID_TOO_LOW, FORECASTING_SET_TARGET_ROAS, + SHOPPING_ADD_AGE_GROUP, SHOPPING_ADD_COLOR, + SHOPPING_ADD_GENDER, SHOPPING_ADD_SIZE, SHOPPING_ADD_GTIN, + SHOPPING_ADD_MORE_IDENTIFIERS, + SHOPPING_ADD_PRODUCTS_TO_CAMPAIGN, + SHOPPING_FIX_DISAPPROVED_PRODUCTS, + SHOPPING_MIGRATE_REGULAR_SHOPPING_CAMPAIGN_OFFERS_TO_PERFORMANCE_MAX, + DYNAMIC_IMAGE_EXTENSION_OPT_IN, RAISE_TARGET_CPA, + LOWER_TARGET_ROAS, FORECASTING_SET_TARGET_CPA, + SET_TARGET_CPA, SET_TARGET_ROAS, + MAXIMIZE_CONVERSION_VALUE_OPT_IN, + IMPROVE_GOOGLE_TAG_COVERAGE, + PERFORMANCE_MAX_FINAL_URL_OPT_IN + + This field is a member of `oneof`_ ``_campaign``. + ad_group (str): + Output only. The ad group targeted by this recommendation. + This will be set only when the recommendation affects a + single ad group. + + This field will be set for the following recommendation + types: KEYWORD, OPTIMIZE_AD_ROTATION, RESPONSIVE_SEARCH_AD, + RESPONSIVE_SEARCH_AD_ASSET, TEXT_AD + + This field is a member of `oneof`_ ``_ad_group``. + dismissed (bool): + Output only. Whether the recommendation is + dismissed or not. + + This field is a member of `oneof`_ ``_dismissed``. + campaigns (MutableSequence[str]): + Output only. The campaigns targeted by this recommendation. + + This field will be set for the following recommendation + types: CAMPAIGN_BUDGET, FORECASTING_CAMPAIGN_BUDGET, + MARGINAL_ROI_CAMPAIGN_BUDGET and MOVE_UNUSED_BUDGET + campaign_budget_recommendation (google.ads.googleads.v24.resources.types.Recommendation.CampaignBudgetRecommendation): + Output only. The campaign budget + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + forecasting_campaign_budget_recommendation (google.ads.googleads.v24.resources.types.Recommendation.CampaignBudgetRecommendation): + Output only. The forecasting campaign budget + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + keyword_recommendation (google.ads.googleads.v24.resources.types.Recommendation.KeywordRecommendation): + Output only. The keyword recommendation. + + This field is a member of `oneof`_ ``recommendation``. + text_ad_recommendation (google.ads.googleads.v24.resources.types.Recommendation.TextAdRecommendation): + Output only. Add expanded text ad + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + target_cpa_opt_in_recommendation (google.ads.googleads.v24.resources.types.Recommendation.TargetCpaOptInRecommendation): + Output only. The TargetCPA opt-in + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + maximize_conversions_opt_in_recommendation (google.ads.googleads.v24.resources.types.Recommendation.MaximizeConversionsOptInRecommendation): + Output only. The MaximizeConversions Opt-In + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + enhanced_cpc_opt_in_recommendation (google.ads.googleads.v24.resources.types.Recommendation.EnhancedCpcOptInRecommendation): + Output only. The Enhanced Cost-Per-Click + Opt-In recommendation. + + This field is a member of `oneof`_ ``recommendation``. + search_partners_opt_in_recommendation (google.ads.googleads.v24.resources.types.Recommendation.SearchPartnersOptInRecommendation): + Output only. The Search Partners Opt-In + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + maximize_clicks_opt_in_recommendation (google.ads.googleads.v24.resources.types.Recommendation.MaximizeClicksOptInRecommendation): + Output only. The MaximizeClicks Opt-In + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + optimize_ad_rotation_recommendation (google.ads.googleads.v24.resources.types.Recommendation.OptimizeAdRotationRecommendation): + Output only. The Optimize Ad Rotation + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + keyword_match_type_recommendation (google.ads.googleads.v24.resources.types.Recommendation.KeywordMatchTypeRecommendation): + Output only. The keyword match type + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + move_unused_budget_recommendation (google.ads.googleads.v24.resources.types.Recommendation.MoveUnusedBudgetRecommendation): + Output only. The move unused budget + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + target_roas_opt_in_recommendation (google.ads.googleads.v24.resources.types.Recommendation.TargetRoasOptInRecommendation): + Output only. The Target ROAS opt-in + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + responsive_search_ad_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ResponsiveSearchAdRecommendation): + Output only. The add responsive search ad + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + marginal_roi_campaign_budget_recommendation (google.ads.googleads.v24.resources.types.Recommendation.CampaignBudgetRecommendation): + Output only. The marginal ROI campaign budget + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + use_broad_match_keyword_recommendation (google.ads.googleads.v24.resources.types.Recommendation.UseBroadMatchKeywordRecommendation): + Output only. The use broad match keyword + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + responsive_search_ad_asset_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ResponsiveSearchAdAssetRecommendation): + Output only. The responsive search ad asset + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + upgrade_smart_shopping_campaign_to_performance_max_recommendation (google.ads.googleads.v24.resources.types.Recommendation.UpgradeSmartShoppingCampaignToPerformanceMaxRecommendation): + Output only. The upgrade a Smart Shopping + campaign to a Performance Max campaign + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + responsive_search_ad_improve_ad_strength_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ResponsiveSearchAdImproveAdStrengthRecommendation): + Output only. The responsive search ad improve + ad strength recommendation. + + This field is a member of `oneof`_ ``recommendation``. + display_expansion_opt_in_recommendation (google.ads.googleads.v24.resources.types.Recommendation.DisplayExpansionOptInRecommendation): + Output only. The Display Expansion opt-in + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + upgrade_local_campaign_to_performance_max_recommendation (google.ads.googleads.v24.resources.types.Recommendation.UpgradeLocalCampaignToPerformanceMaxRecommendation): + Output only. The upgrade a Local campaign to + a Performance Max campaign recommendation. + + This field is a member of `oneof`_ ``recommendation``. + raise_target_cpa_bid_too_low_recommendation (google.ads.googleads.v24.resources.types.Recommendation.RaiseTargetCpaBidTooLowRecommendation): + Output only. The raise target CPA bid too low + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + forecasting_set_target_roas_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ForecastingSetTargetRoasRecommendation): + Output only. The forecasting set target ROAS + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + callout_asset_recommendation (google.ads.googleads.v24.resources.types.Recommendation.CalloutAssetRecommendation): + Output only. The callout asset + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + sitelink_asset_recommendation (google.ads.googleads.v24.resources.types.Recommendation.SitelinkAssetRecommendation): + Output only. The sitelink asset + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + call_asset_recommendation (google.ads.googleads.v24.resources.types.Recommendation.CallAssetRecommendation): + Output only. The call asset recommendation. + + This field is a member of `oneof`_ ``recommendation``. + shopping_add_age_group_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ShoppingOfferAttributeRecommendation): + Output only. The shopping add age group + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + shopping_add_color_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ShoppingOfferAttributeRecommendation): + Output only. The shopping add color + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + shopping_add_gender_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ShoppingOfferAttributeRecommendation): + Output only. The shopping add gender + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + shopping_add_gtin_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ShoppingOfferAttributeRecommendation): + Output only. The shopping add GTIN + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + shopping_add_more_identifiers_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ShoppingOfferAttributeRecommendation): + Output only. The shopping add more + identifiers recommendation. + + This field is a member of `oneof`_ ``recommendation``. + shopping_add_size_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ShoppingOfferAttributeRecommendation): + Output only. The shopping add size + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + shopping_add_products_to_campaign_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ShoppingAddProductsToCampaignRecommendation): + Output only. The shopping add products to + campaign recommendation. + + This field is a member of `oneof`_ ``recommendation``. + shopping_fix_disapproved_products_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ShoppingFixDisapprovedProductsRecommendation): + Output only. The shopping fix disapproved + products recommendation. + + This field is a member of `oneof`_ ``recommendation``. + shopping_target_all_offers_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ShoppingTargetAllOffersRecommendation): + Output only. The shopping target all offers + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + shopping_fix_suspended_merchant_center_account_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ShoppingMerchantCenterAccountSuspensionRecommendation): + Output only. The shopping fix suspended + Merchant Center account recommendation. + + This field is a member of `oneof`_ ``recommendation``. + shopping_fix_merchant_center_account_suspension_warning_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ShoppingMerchantCenterAccountSuspensionRecommendation): + Output only. The shopping fix Merchant Center + account suspension warning recommendation. + + This field is a member of `oneof`_ ``recommendation``. + shopping_migrate_regular_shopping_campaign_offers_to_performance_max_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ShoppingMigrateRegularShoppingCampaignOffersToPerformanceMaxRecommendation): + Output only. The shopping migrate Regular + Shopping Campaign offers to Performance Max + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + dynamic_image_extension_opt_in_recommendation (google.ads.googleads.v24.resources.types.Recommendation.DynamicImageExtensionOptInRecommendation): + Output only. Recommendation to enable dynamic + image extensions on the account, allowing Google + to find the best images from ad landing pages + and complement text ads. + + This field is a member of `oneof`_ ``recommendation``. + raise_target_cpa_recommendation (google.ads.googleads.v24.resources.types.Recommendation.RaiseTargetCpaRecommendation): + Output only. Recommendation to raise Target + CPA. + + This field is a member of `oneof`_ ``recommendation``. + lower_target_roas_recommendation (google.ads.googleads.v24.resources.types.Recommendation.LowerTargetRoasRecommendation): + Output only. Recommendation to lower Target + ROAS. + + This field is a member of `oneof`_ ``recommendation``. + performance_max_opt_in_recommendation (google.ads.googleads.v24.resources.types.Recommendation.PerformanceMaxOptInRecommendation): + Output only. The Performance Max Opt In + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + improve_performance_max_ad_strength_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ImprovePerformanceMaxAdStrengthRecommendation): + Output only. The improve Performance Max ad + strength recommendation. + + This field is a member of `oneof`_ ``recommendation``. + migrate_dynamic_search_ads_campaign_to_performance_max_recommendation (google.ads.googleads.v24.resources.types.Recommendation.MigrateDynamicSearchAdsCampaignToPerformanceMaxRecommendation): + Output only. The Dynamic Search Ads to + Performance Max migration recommendation. + + This field is a member of `oneof`_ ``recommendation``. + forecasting_set_target_cpa_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ForecastingSetTargetCpaRecommendation): + Output only. The forecasting set target CPA + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + set_target_cpa_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ForecastingSetTargetCpaRecommendation): + Output only. The set target CPA + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + set_target_roas_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ForecastingSetTargetRoasRecommendation): + Output only. The set target ROAS + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + maximize_conversion_value_opt_in_recommendation (google.ads.googleads.v24.resources.types.Recommendation.MaximizeConversionValueOptInRecommendation): + Output only. The Maximize Conversion Value + opt-in recommendation. + + This field is a member of `oneof`_ ``recommendation``. + improve_google_tag_coverage_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ImproveGoogleTagCoverageRecommendation): + Output only. Recommendation to deploy Google + Tag on more pages. + + This field is a member of `oneof`_ ``recommendation``. + performance_max_final_url_opt_in_recommendation (google.ads.googleads.v24.resources.types.Recommendation.PerformanceMaxFinalUrlOptInRecommendation): + Output only. Recommendation to turn on Final + URL expansion for your Performance Max + campaigns. + + This field is a member of `oneof`_ ``recommendation``. + refresh_customer_match_list_recommendation (google.ads.googleads.v24.resources.types.Recommendation.RefreshCustomerMatchListRecommendation): + Output only. The refresh customer list + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + custom_audience_opt_in_recommendation (google.ads.googleads.v24.resources.types.Recommendation.CustomAudienceOptInRecommendation): + Output only. The custom audience opt in + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + lead_form_asset_recommendation (google.ads.googleads.v24.resources.types.Recommendation.LeadFormAssetRecommendation): + Output only. The lead form asset + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + improve_demand_gen_ad_strength_recommendation (google.ads.googleads.v24.resources.types.Recommendation.ImproveDemandGenAdStrengthRecommendation): + Output only. The improve Demand Gen ad + strength recommendation. + + This field is a member of `oneof`_ ``recommendation``. + """ + + class MerchantInfo(proto.Message): + r"""The Merchant Center account details. + + Attributes: + id (int): + Output only. The Merchant Center account ID. + name (str): + Output only. The name of the Merchant Center + account. + multi_client (bool): + Output only. Whether the Merchant Center + account is a Multi-Client account (MCA). + """ + + id: int = proto.Field( + proto.INT64, + number=1, + ) + name: str = proto.Field( + proto.STRING, + number=2, + ) + multi_client: bool = proto.Field( + proto.BOOL, + number=3, + ) + + class RecommendationImpact(proto.Message): + r"""The impact of making the change as described in the + recommendation. Some types of recommendations may not have + impact information. + + Attributes: + base_metrics (google.ads.googleads.v24.resources.types.Recommendation.RecommendationMetrics): + Output only. Base metrics at the time the + recommendation was generated. + potential_metrics (google.ads.googleads.v24.resources.types.Recommendation.RecommendationMetrics): + Output only. Estimated metrics if the + recommendation is applied. + """ + + base_metrics: "Recommendation.RecommendationMetrics" = proto.Field( + proto.MESSAGE, + number=1, + message="Recommendation.RecommendationMetrics", + ) + potential_metrics: "Recommendation.RecommendationMetrics" = proto.Field( + proto.MESSAGE, + number=2, + message="Recommendation.RecommendationMetrics", + ) + + class RecommendationMetrics(proto.Message): + r"""Weekly account performance metrics. For some recommendation + types, these are averaged over the past 90-day period and hence + can be fractional. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + impressions (float): + Output only. Number of ad impressions. + + This field is a member of `oneof`_ ``_impressions``. + clicks (float): + Output only. Number of ad clicks. + + This field is a member of `oneof`_ ``_clicks``. + cost_micros (int): + Output only. Cost (in micros) for + advertising, in the local currency for the + account. + + This field is a member of `oneof`_ ``_cost_micros``. + conversions (float): + Output only. Number of conversions. + + This field is a member of `oneof`_ ``_conversions``. + conversions_value (float): + Output only. Sum of the conversion value of + the conversions. + + This field is a member of `oneof`_ ``_conversions_value``. + video_views (float): + Output only. Number of video views for a + video ad campaign. + + This field is a member of `oneof`_ ``_video_views``. + """ + + impressions: float = proto.Field( + proto.DOUBLE, + number=6, + optional=True, + ) + clicks: float = proto.Field( + proto.DOUBLE, + number=7, + optional=True, + ) + cost_micros: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + conversions: float = proto.Field( + proto.DOUBLE, + number=9, + optional=True, + ) + conversions_value: float = proto.Field( + proto.DOUBLE, + number=11, + optional=True, + ) + video_views: float = proto.Field( + proto.DOUBLE, + number=10, + optional=True, + ) + + class CampaignBudgetRecommendation(proto.Message): + r"""The budget recommendation for budget constrained campaigns. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + current_budget_amount_micros (int): + Output only. The current budget amount in + micros. + + This field is a member of `oneof`_ ``_current_budget_amount_micros``. + recommended_budget_amount_micros (int): + Output only. The recommended budget amount in + micros. + + This field is a member of `oneof`_ ``_recommended_budget_amount_micros``. + budget_options (MutableSequence[google.ads.googleads.v24.resources.types.Recommendation.CampaignBudgetRecommendation.CampaignBudgetRecommendationOption]): + Output only. The budget amounts and + associated impact estimates for some values of + possible budget amounts. + """ + + class CampaignBudgetRecommendationOption(proto.Message): + r"""The impact estimates for a given budget amount. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + budget_amount_micros (int): + Output only. The budget amount for this + option. + + This field is a member of `oneof`_ ``_budget_amount_micros``. + impact (google.ads.googleads.v24.resources.types.Recommendation.RecommendationImpact): + Output only. The impact estimate if budget is + changed to amount specified in this option. + """ + + budget_amount_micros: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + impact: "Recommendation.RecommendationImpact" = proto.Field( + proto.MESSAGE, + number=2, + message="Recommendation.RecommendationImpact", + ) + + current_budget_amount_micros: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + recommended_budget_amount_micros: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + budget_options: MutableSequence[ + "Recommendation.CampaignBudgetRecommendation.CampaignBudgetRecommendationOption" + ] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="Recommendation.CampaignBudgetRecommendation.CampaignBudgetRecommendationOption", + ) + + class KeywordRecommendation(proto.Message): + r"""The keyword recommendation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + keyword (google.ads.googleads.v24.common.types.KeywordInfo): + Output only. The recommended keyword. + search_terms (MutableSequence[google.ads.googleads.v24.resources.types.Recommendation.KeywordRecommendation.SearchTerm]): + Output only. A list of search terms this + keyword matches. The same search term may be + repeated for multiple keywords. + recommended_cpc_bid_micros (int): + Output only. The recommended CPC + (cost-per-click) bid. + + This field is a member of `oneof`_ ``_recommended_cpc_bid_micros``. + """ + + class SearchTerm(proto.Message): + r"""Information about a search term as related to a keyword + recommendation. + + Attributes: + text (str): + Output only. The text of the search term. + estimated_weekly_search_count (int): + Output only. Estimated number of historical + weekly searches for this search term. + """ + + text: str = proto.Field( + proto.STRING, + number=1, + ) + estimated_weekly_search_count: int = proto.Field( + proto.INT64, + number=2, + ) + + keyword: criteria.KeywordInfo = proto.Field( + proto.MESSAGE, + number=1, + message=criteria.KeywordInfo, + ) + search_terms: MutableSequence[ + "Recommendation.KeywordRecommendation.SearchTerm" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="Recommendation.KeywordRecommendation.SearchTerm", + ) + recommended_cpc_bid_micros: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + + class TextAdRecommendation(proto.Message): + r"""The text ad recommendation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + ad (google.ads.googleads.v24.resources.types.Ad): + Output only. Recommended ad. + creation_date (str): + Output only. Creation date of the recommended + ad. YYYY-MM-DD format, for example, 2018-04-17. + + This field is a member of `oneof`_ ``_creation_date``. + auto_apply_date (str): + Output only. Date, if present, is the + earliest when the recommendation will be auto + applied. YYYY-MM-DD format, for example, + 2018-04-17. + + This field is a member of `oneof`_ ``_auto_apply_date``. + """ + + ad: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=1, + message=gagr_ad.Ad, + ) + creation_date: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + auto_apply_date: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + + class TargetCpaOptInRecommendation(proto.Message): + r"""The Target CPA opt-in recommendation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + options (MutableSequence[google.ads.googleads.v24.resources.types.Recommendation.TargetCpaOptInRecommendation.TargetCpaOptInRecommendationOption]): + Output only. The available goals and + corresponding options for Target CPA strategy. + recommended_target_cpa_micros (int): + Output only. The recommended average CPA + target. See required budget amount and impact of + using this recommendation in options list. + + This field is a member of `oneof`_ ``_recommended_target_cpa_micros``. + """ + + class TargetCpaOptInRecommendationOption(proto.Message): + r"""The Target CPA opt-in option with impact estimate. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + goal (google.ads.googleads.v24.enums.types.TargetCpaOptInRecommendationGoalEnum.TargetCpaOptInRecommendationGoal): + Output only. The goal achieved by this + option. + target_cpa_micros (int): + Output only. Average CPA target. + + This field is a member of `oneof`_ ``_target_cpa_micros``. + required_campaign_budget_amount_micros (int): + Output only. The minimum campaign budget, in + local currency for the account, required to + achieve the target CPA. Amount is specified in + micros, where one million is equivalent to one + currency unit. + + This field is a member of `oneof`_ ``_required_campaign_budget_amount_micros``. + impact (google.ads.googleads.v24.resources.types.Recommendation.RecommendationImpact): + Output only. The impact estimate if this + option is selected. + """ + + goal: ( + target_cpa_opt_in_recommendation_goal.TargetCpaOptInRecommendationGoalEnum.TargetCpaOptInRecommendationGoal + ) = proto.Field( + proto.ENUM, + number=1, + enum=target_cpa_opt_in_recommendation_goal.TargetCpaOptInRecommendationGoalEnum.TargetCpaOptInRecommendationGoal, + ) + target_cpa_micros: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + required_campaign_budget_amount_micros: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + impact: "Recommendation.RecommendationImpact" = proto.Field( + proto.MESSAGE, + number=4, + message="Recommendation.RecommendationImpact", + ) + + options: MutableSequence[ + "Recommendation.TargetCpaOptInRecommendation.TargetCpaOptInRecommendationOption" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="Recommendation.TargetCpaOptInRecommendation.TargetCpaOptInRecommendationOption", + ) + recommended_target_cpa_micros: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + + class MaximizeConversionsOptInRecommendation(proto.Message): + r"""The Maximize Conversions Opt-In recommendation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + recommended_budget_amount_micros (int): + Output only. The recommended new budget + amount. + + This field is a member of `oneof`_ ``_recommended_budget_amount_micros``. + """ + + recommended_budget_amount_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + class EnhancedCpcOptInRecommendation(proto.Message): + r"""The Enhanced Cost-Per-Click Opt-In recommendation.""" + + class SearchPartnersOptInRecommendation(proto.Message): + r"""The Search Partners Opt-In recommendation.""" + + class MaximizeClicksOptInRecommendation(proto.Message): + r"""The Maximize Clicks opt-in recommendation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + recommended_budget_amount_micros (int): + Output only. The recommended new budget + amount. Only set if the current budget is too + high. + + This field is a member of `oneof`_ ``_recommended_budget_amount_micros``. + """ + + recommended_budget_amount_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + class OptimizeAdRotationRecommendation(proto.Message): + r"""The Optimize Ad Rotation recommendation.""" + + class CalloutAssetRecommendation(proto.Message): + r"""The callout asset recommendation. + + Attributes: + recommended_campaign_callout_assets (MutableSequence[google.ads.googleads.v24.resources.types.Asset]): + Output only. New callout extension assets + recommended at the campaign level. + recommended_customer_callout_assets (MutableSequence[google.ads.googleads.v24.resources.types.Asset]): + Output only. New callout extension assets + recommended at the customer level. + """ + + recommended_campaign_callout_assets: MutableSequence[asset.Asset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=asset.Asset, + ) + ) + recommended_customer_callout_assets: MutableSequence[asset.Asset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message=asset.Asset, + ) + ) + + class SitelinkAssetRecommendation(proto.Message): + r"""The sitelink asset recommendation. + + Attributes: + recommended_campaign_sitelink_assets (MutableSequence[google.ads.googleads.v24.resources.types.Asset]): + Output only. New sitelink assets recommended + at the campaign level. + recommended_customer_sitelink_assets (MutableSequence[google.ads.googleads.v24.resources.types.Asset]): + Output only. New sitelink assets recommended + at the customer level. + """ + + recommended_campaign_sitelink_assets: MutableSequence[asset.Asset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=asset.Asset, + ) + ) + recommended_customer_sitelink_assets: MutableSequence[asset.Asset] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message=asset.Asset, + ) + ) + + class CallAssetRecommendation(proto.Message): + r"""The call asset recommendation.""" + + class KeywordMatchTypeRecommendation(proto.Message): + r"""The keyword match type recommendation. + + Attributes: + keyword (google.ads.googleads.v24.common.types.KeywordInfo): + Output only. The existing keyword where the + match type should be more broad. + recommended_match_type (google.ads.googleads.v24.enums.types.KeywordMatchTypeEnum.KeywordMatchType): + Output only. The recommended new match type. + """ + + keyword: criteria.KeywordInfo = proto.Field( + proto.MESSAGE, + number=1, + message=criteria.KeywordInfo, + ) + recommended_match_type: ( + keyword_match_type.KeywordMatchTypeEnum.KeywordMatchType + ) = proto.Field( + proto.ENUM, + number=2, + enum=keyword_match_type.KeywordMatchTypeEnum.KeywordMatchType, + ) + + class MoveUnusedBudgetRecommendation(proto.Message): + r"""The move unused budget recommendation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + excess_campaign_budget (str): + Output only. The excess budget's resource_name. + + This field is a member of `oneof`_ ``_excess_campaign_budget``. + budget_recommendation (google.ads.googleads.v24.resources.types.Recommendation.CampaignBudgetRecommendation): + Output only. The recommendation for the + constrained budget to increase. + """ + + excess_campaign_budget: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + budget_recommendation: "Recommendation.CampaignBudgetRecommendation" = ( + proto.Field( + proto.MESSAGE, + number=2, + message="Recommendation.CampaignBudgetRecommendation", + ) + ) + + class TargetRoasOptInRecommendation(proto.Message): + r"""The Target ROAS opt-in recommendation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + recommended_target_roas (float): + Output only. The recommended target ROAS + (revenue per unit of spend). The value is + between 0.01 and 1000.0, inclusive. + + This field is a member of `oneof`_ ``_recommended_target_roas``. + required_campaign_budget_amount_micros (int): + Output only. The minimum campaign budget, in + local currency for the account, required to + achieve the target ROAS. Amount is specified in + micros, where one million is equivalent to one + currency unit. + + This field is a member of `oneof`_ ``_required_campaign_budget_amount_micros``. + """ + + recommended_target_roas: float = proto.Field( + proto.DOUBLE, + number=1, + optional=True, + ) + required_campaign_budget_amount_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + class ResponsiveSearchAdAssetRecommendation(proto.Message): + r"""The add responsive search ad asset recommendation. + + Attributes: + current_ad (google.ads.googleads.v24.resources.types.Ad): + Output only. The current ad to be updated. + recommended_assets (google.ads.googleads.v24.resources.types.Ad): + Output only. The recommended assets. This is + populated only with the new headlines and/or + descriptions, and is otherwise empty. + """ + + current_ad: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=3, + message=gagr_ad.Ad, + ) + recommended_assets: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad.Ad, + ) + + class ResponsiveSearchAdImproveAdStrengthRecommendation(proto.Message): + r"""The responsive search ad improve ad strength recommendation. + + Attributes: + current_ad (google.ads.googleads.v24.resources.types.Ad): + Output only. The current ad to be updated. + recommended_ad (google.ads.googleads.v24.resources.types.Ad): + Output only. The updated ad. + """ + + current_ad: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=1, + message=gagr_ad.Ad, + ) + recommended_ad: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad.Ad, + ) + + class ResponsiveSearchAdRecommendation(proto.Message): + r"""The add responsive search ad recommendation. + + Attributes: + ad (google.ads.googleads.v24.resources.types.Ad): + Output only. Recommended ad. + """ + + ad: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=1, + message=gagr_ad.Ad, + ) + + class UseBroadMatchKeywordRecommendation(proto.Message): + r"""The use broad match keyword recommendation. + + Attributes: + keyword (MutableSequence[google.ads.googleads.v24.common.types.KeywordInfo]): + Output only. Sample of keywords to be + expanded to Broad Match. + suggested_keywords_count (int): + Output only. Total number of keywords to be + expanded to Broad Match in the campaign. + campaign_keywords_count (int): + Output only. Total number of keywords in the + campaign. + campaign_uses_shared_budget (bool): + Output only. Whether the associated campaign + uses a shared budget. + required_campaign_budget_amount_micros (int): + Output only. The budget recommended to avoid + becoming budget constrained after applying the + recommendation. + """ + + keyword: MutableSequence[criteria.KeywordInfo] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=criteria.KeywordInfo, + ) + suggested_keywords_count: int = proto.Field( + proto.INT64, + number=2, + ) + campaign_keywords_count: int = proto.Field( + proto.INT64, + number=3, + ) + campaign_uses_shared_budget: bool = proto.Field( + proto.BOOL, + number=4, + ) + required_campaign_budget_amount_micros: int = proto.Field( + proto.INT64, + number=5, + ) + + class UpgradeSmartShoppingCampaignToPerformanceMaxRecommendation( + proto.Message + ): + r"""The upgrade a Smart Shopping campaign to a Performance Max + campaign recommendation. + + Attributes: + merchant_id (int): + Output only. ID of Merchant Center account. + sales_country_code (str): + Output only. Country whose products from + merchant's inventory should be included. + """ + + merchant_id: int = proto.Field( + proto.INT64, + number=1, + ) + sales_country_code: str = proto.Field( + proto.STRING, + number=2, + ) + + class RaiseTargetCpaBidTooLowRecommendation(proto.Message): + r"""The raise target CPA bid too low recommendation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + recommended_target_multiplier (float): + Output only. A number greater than 1.0 + indicating the factor by which we recommend the + target CPA should be increased. + + This field is a member of `oneof`_ ``_recommended_target_multiplier``. + average_target_cpa_micros (int): + Output only. The current average target CPA + of the campaign, in micros of customer local + currency. + + This field is a member of `oneof`_ ``_average_target_cpa_micros``. + """ + + recommended_target_multiplier: float = proto.Field( + proto.DOUBLE, + number=1, + optional=True, + ) + average_target_cpa_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + class DisplayExpansionOptInRecommendation(proto.Message): + r"""The Display Expansion opt-in recommendation.""" + + class UpgradeLocalCampaignToPerformanceMaxRecommendation(proto.Message): + r"""The Upgrade Local campaign to Performance Max campaign + recommendation. + + """ + + class ForecastingSetTargetRoasRecommendation(proto.Message): + r"""The forecasting set target ROAS recommendation. + + Attributes: + recommended_target_roas (float): + Output only. The recommended target ROAS + (revenue per unit of spend). The value is + between 0.01 and 1000.0, inclusive. + campaign_budget (google.ads.googleads.v24.resources.types.Recommendation.CampaignBudget): + Output only. The campaign budget. + """ + + recommended_target_roas: float = proto.Field( + proto.DOUBLE, + number=1, + ) + campaign_budget: "Recommendation.CampaignBudget" = proto.Field( + proto.MESSAGE, + number=2, + message="Recommendation.CampaignBudget", + ) + + class ShoppingOfferAttributeRecommendation(proto.Message): + r"""The shopping recommendation to add an attribute to offers + that are demoted because it is missing. + + Attributes: + merchant (google.ads.googleads.v24.resources.types.Recommendation.MerchantInfo): + Output only. The details of the Merchant + Center account. + feed_label (str): + Output only. The campaign feed label. + offers_count (int): + Output only. The number of online, servable + offers. + demoted_offers_count (int): + Output only. The number of online, servable + offers that are demoted for missing attributes. + Visit the Merchant Center for more details. + """ + + merchant: "Recommendation.MerchantInfo" = proto.Field( + proto.MESSAGE, + number=1, + message="Recommendation.MerchantInfo", + ) + feed_label: str = proto.Field( + proto.STRING, + number=2, + ) + offers_count: int = proto.Field( + proto.INT64, + number=3, + ) + demoted_offers_count: int = proto.Field( + proto.INT64, + number=4, + ) + + class ShoppingFixDisapprovedProductsRecommendation(proto.Message): + r"""The shopping recommendation to fix disapproved products in a + Shopping Campaign Inventory. + + Attributes: + merchant (google.ads.googleads.v24.resources.types.Recommendation.MerchantInfo): + Output only. The details of the Merchant + Center account. + feed_label (str): + Output only. The feed label for the campaign. + products_count (int): + Output only. The number of products of the + campaign. + disapproved_products_count (int): + Output only. The numbers of products of the + campaign that are disapproved. + """ + + merchant: "Recommendation.MerchantInfo" = proto.Field( + proto.MESSAGE, + number=1, + message="Recommendation.MerchantInfo", + ) + feed_label: str = proto.Field( + proto.STRING, + number=2, + ) + products_count: int = proto.Field( + proto.INT64, + number=3, + ) + disapproved_products_count: int = proto.Field( + proto.INT64, + number=4, + ) + + class ShoppingTargetAllOffersRecommendation(proto.Message): + r"""The shopping recommendation to create a catch-all campaign + that targets all offers. + + Attributes: + merchant (google.ads.googleads.v24.resources.types.Recommendation.MerchantInfo): + Output only. The details of the Merchant + Center account. + untargeted_offers_count (int): + Output only. The number of untargeted offers. + feed_label (str): + Output only. The offer feed label. + """ + + merchant: "Recommendation.MerchantInfo" = proto.Field( + proto.MESSAGE, + number=1, + message="Recommendation.MerchantInfo", + ) + untargeted_offers_count: int = proto.Field( + proto.INT64, + number=2, + ) + feed_label: str = proto.Field( + proto.STRING, + number=3, + ) + + class ShoppingAddProductsToCampaignRecommendation(proto.Message): + r"""The shopping recommendation to add products to a Shopping + Campaign Inventory. + + Attributes: + merchant (google.ads.googleads.v24.resources.types.Recommendation.MerchantInfo): + Output only. The details of the Merchant + Center account. + feed_label (str): + Output only. The feed label for the campaign. + reason (google.ads.googleads.v24.enums.types.ShoppingAddProductsToCampaignRecommendationEnum.Reason): + Output only. The reason why no products are + attached to the campaign. + """ + + merchant: "Recommendation.MerchantInfo" = proto.Field( + proto.MESSAGE, + number=1, + message="Recommendation.MerchantInfo", + ) + feed_label: str = proto.Field( + proto.STRING, + number=2, + ) + reason: ( + shopping_add_products_to_campaign_recommendation_enum.ShoppingAddProductsToCampaignRecommendationEnum.Reason + ) = proto.Field( + proto.ENUM, + number=3, + enum=shopping_add_products_to_campaign_recommendation_enum.ShoppingAddProductsToCampaignRecommendationEnum.Reason, + ) + + class ShoppingMerchantCenterAccountSuspensionRecommendation(proto.Message): + r"""The shopping recommendation to fix Merchant Center account + suspension issues. + + Attributes: + merchant (google.ads.googleads.v24.resources.types.Recommendation.MerchantInfo): + Output only. The details of the Merchant + Center account. + feed_label (str): + Output only. The feed label of the campaign + for which the suspension happened. + """ + + merchant: "Recommendation.MerchantInfo" = proto.Field( + proto.MESSAGE, + number=1, + message="Recommendation.MerchantInfo", + ) + feed_label: str = proto.Field( + proto.STRING, + number=2, + ) + + class ShoppingMigrateRegularShoppingCampaignOffersToPerformanceMaxRecommendation( + proto.Message + ): + r"""The shopping recommendation to migrate Regular Shopping + Campaign targeted offers to Performance Max campaigns. + + Attributes: + merchant (google.ads.googleads.v24.resources.types.Recommendation.MerchantInfo): + Output only. The details of the Merchant + Center account. + feed_label (str): + Output only. The feed label of the offers + targeted by the campaigns sharing this + suggestion. + """ + + merchant: "Recommendation.MerchantInfo" = proto.Field( + proto.MESSAGE, + number=1, + message="Recommendation.MerchantInfo", + ) + feed_label: str = proto.Field( + proto.STRING, + number=2, + ) + + class TargetAdjustmentInfo(proto.Message): + r"""Information of a target adjustment recommendation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + shared_set (str): + Output only. The shared set resource name of + the portfolio bidding strategy where the target + is defined. Only populated if the recommendation + is portfolio level. + + This field is a member of `oneof`_ ``_shared_set``. + recommended_target_multiplier (float): + Output only. The factor by which we recommend + the target to be adjusted by. + current_average_target_micros (int): + Output only. The current average target of + the campaign or portfolio targeted by this + recommendation. + """ + + shared_set: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + recommended_target_multiplier: float = proto.Field( + proto.DOUBLE, + number=2, + ) + current_average_target_micros: int = proto.Field( + proto.INT64, + number=3, + ) + + class RaiseTargetCpaRecommendation(proto.Message): + r"""Recommendation to raise Target CPA. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_adjustment (google.ads.googleads.v24.resources.types.Recommendation.TargetAdjustmentInfo): + Output only. The relevant information + describing the recommended target adjustment. + app_bidding_goal (google.ads.googleads.v24.enums.types.AppBiddingGoalEnum.AppBiddingGoal): + Output only. Represents the goal towards + which the bidding strategy should optimize. Only + populated for App Campaigns. + + This field is a member of `oneof`_ ``_app_bidding_goal``. + """ + + target_adjustment: "Recommendation.TargetAdjustmentInfo" = proto.Field( + proto.MESSAGE, + number=1, + message="Recommendation.TargetAdjustmentInfo", + ) + app_bidding_goal: ( + gage_app_bidding_goal.AppBiddingGoalEnum.AppBiddingGoal + ) = proto.Field( + proto.ENUM, + number=2, + optional=True, + enum=gage_app_bidding_goal.AppBiddingGoalEnum.AppBiddingGoal, + ) + + class LowerTargetRoasRecommendation(proto.Message): + r"""Recommendation to lower Target ROAS. + + Attributes: + target_adjustment (google.ads.googleads.v24.resources.types.Recommendation.TargetAdjustmentInfo): + Output only. The relevant information + describing the recommended target adjustment. + """ + + target_adjustment: "Recommendation.TargetAdjustmentInfo" = proto.Field( + proto.MESSAGE, + number=1, + message="Recommendation.TargetAdjustmentInfo", + ) + + class DynamicImageExtensionOptInRecommendation(proto.Message): + r"""Recommendation to enable dynamic image extensions on the + account, allowing Google to find the best images from ad landing + pages and complement text ads. + + """ + + class CampaignBudget(proto.Message): + r"""A campaign budget shared amongst various budget + recommendation types. + + Attributes: + current_amount_micros (int): + Output only. Current budget amount. + recommended_new_amount_micros (int): + Output only. Recommended budget amount. + new_start_date (str): + Output only. The date when the new budget would start being + used. This field will be set for the following + recommendation types: FORECASTING_SET_TARGET_ROAS , + FORECASTING_SET_TARGET_CPA YYYY-MM-DD format, for example, + 2018-04-17. + """ + + current_amount_micros: int = proto.Field( + proto.INT64, + number=1, + ) + recommended_new_amount_micros: int = proto.Field( + proto.INT64, + number=2, + ) + new_start_date: str = proto.Field( + proto.STRING, + number=3, + ) + + class PerformanceMaxOptInRecommendation(proto.Message): + r"""The Performance Max Opt In recommendation.""" + + class ImprovePerformanceMaxAdStrengthRecommendation(proto.Message): + r"""Recommendation to improve the asset group strength of a + Performance Max campaign to an "Excellent" rating. + + Attributes: + asset_group (str): + Output only. The asset group resource name. + ad_strength (google.ads.googleads.v24.enums.types.AdStrengthEnum.AdStrength): + Output only. The current ad strength score of + the asset group. + """ + + asset_group: str = proto.Field( + proto.STRING, + number=1, + ) + ad_strength: gage_ad_strength.AdStrengthEnum.AdStrength = proto.Field( + proto.ENUM, + number=2, + enum=gage_ad_strength.AdStrengthEnum.AdStrength, + ) + + class MigrateDynamicSearchAdsCampaignToPerformanceMaxRecommendation( + proto.Message + ): + r"""The Dynamic Search Ads to Performance Max migration + recommendation. + + Attributes: + apply_link (str): + Output only. A link to the Google Ads UI + where the customer can manually apply the + recommendation. + """ + + apply_link: str = proto.Field( + proto.STRING, + number=1, + ) + + class ForecastingSetTargetCpaRecommendation(proto.Message): + r"""The set target CPA recommendations. + + Attributes: + recommended_target_cpa_micros (int): + Output only. The recommended target CPA. + campaign_budget (google.ads.googleads.v24.resources.types.Recommendation.CampaignBudget): + Output only. The campaign budget. + """ + + recommended_target_cpa_micros: int = proto.Field( + proto.INT64, + number=1, + ) + campaign_budget: "Recommendation.CampaignBudget" = proto.Field( + proto.MESSAGE, + number=2, + message="Recommendation.CampaignBudget", + ) + + class MaximizeConversionValueOptInRecommendation(proto.Message): + r"""Recommendation to opt into Maximize Conversion Value bidding + strategy. + + """ + + class ImproveGoogleTagCoverageRecommendation(proto.Message): + r"""Recommendation to deploy Google Tag on more pages.""" + + class PerformanceMaxFinalUrlOptInRecommendation(proto.Message): + r"""Recommendation to turn on Final URL expansion for your + Performance Max campaigns. + + """ + + class RefreshCustomerMatchListRecommendation(proto.Message): + r"""The recommendation to update a customer list that hasn't been + updated in the last 90 days. The customer receiving the + recommendation is not necessarily the owner account. The owner + account should update the customer list. + + Attributes: + user_list_id (int): + Output only. The user list ID. + user_list_name (str): + Output only. The name of the list. + days_since_last_refresh (int): + Output only. Days since last refresh. + top_spending_account (MutableSequence[google.ads.googleads.v24.resources.types.Recommendation.AccountInfo]): + Output only. The top spending account. + targeting_accounts_count (int): + Output only. User lists can be shared with other accounts by + the owner. targeting_accounts_count is the number of those + accounts that can use it for targeting. + owner_account (google.ads.googleads.v24.resources.types.Recommendation.AccountInfo): + Output only. The owner account. This is the + account that should update the customer list. + """ + + user_list_id: int = proto.Field( + proto.INT64, + number=1, + ) + user_list_name: str = proto.Field( + proto.STRING, + number=2, + ) + days_since_last_refresh: int = proto.Field( + proto.INT64, + number=3, + ) + top_spending_account: MutableSequence["Recommendation.AccountInfo"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=4, + message="Recommendation.AccountInfo", + ) + ) + targeting_accounts_count: int = proto.Field( + proto.INT64, + number=5, + ) + owner_account: "Recommendation.AccountInfo" = proto.Field( + proto.MESSAGE, + number=6, + message="Recommendation.AccountInfo", + ) + + class AccountInfo(proto.Message): + r"""Wrapper for information about a Google Ads account. + + Attributes: + customer_id (int): + Output only. The customer ID of the account. + descriptive_name (str): + Output only. The descriptive name of the + account. + """ + + customer_id: int = proto.Field( + proto.INT64, + number=1, + ) + descriptive_name: str = proto.Field( + proto.STRING, + number=2, + ) + + class CustomAudienceOptInRecommendation(proto.Message): + r"""The Custom Audience Opt In recommendation. + + Attributes: + keywords (MutableSequence[google.ads.googleads.v24.common.types.KeywordInfo]): + Output only. The list of keywords to use for + custom audience creation. + """ + + keywords: MutableSequence[criteria.KeywordInfo] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=criteria.KeywordInfo, + ) + + class LeadFormAssetRecommendation(proto.Message): + r"""The lead form asset recommendation.""" + + class ImproveDemandGenAdStrengthRecommendation(proto.Message): + r"""The improve Demand Gen ad strength recommendation. + + Attributes: + ad (str): + Output only. The resource name of the ad that + can be improved. + ad_strength (google.ads.googleads.v24.enums.types.AdStrengthEnum.AdStrength): + Output only. The current ad strength. + demand_gen_asset_action_items (MutableSequence[str]): + Output only. A list of recommendations to + improve the ad strength. + """ + + ad: str = proto.Field( + proto.STRING, + number=1, + ) + ad_strength: gage_ad_strength.AdStrengthEnum.AdStrength = proto.Field( + proto.ENUM, + number=2, + enum=gage_ad_strength.AdStrengthEnum.AdStrength, + ) + demand_gen_asset_action_items: MutableSequence[str] = ( + proto.RepeatedField( + proto.STRING, + number=3, + ) + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + type_: recommendation_type.RecommendationTypeEnum.RecommendationType = ( + proto.Field( + proto.ENUM, + number=2, + enum=recommendation_type.RecommendationTypeEnum.RecommendationType, + ) + ) + impact: RecommendationImpact = proto.Field( + proto.MESSAGE, + number=3, + message=RecommendationImpact, + ) + campaign_budget: str = proto.Field( + proto.STRING, + number=24, + optional=True, + ) + campaign: str = proto.Field( + proto.STRING, + number=25, + optional=True, + ) + ad_group: str = proto.Field( + proto.STRING, + number=26, + optional=True, + ) + dismissed: bool = proto.Field( + proto.BOOL, + number=27, + optional=True, + ) + campaigns: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=38, + ) + campaign_budget_recommendation: CampaignBudgetRecommendation = proto.Field( + proto.MESSAGE, + number=4, + oneof="recommendation", + message=CampaignBudgetRecommendation, + ) + forecasting_campaign_budget_recommendation: CampaignBudgetRecommendation = ( + proto.Field( + proto.MESSAGE, + number=22, + oneof="recommendation", + message=CampaignBudgetRecommendation, + ) + ) + keyword_recommendation: KeywordRecommendation = proto.Field( + proto.MESSAGE, + number=8, + oneof="recommendation", + message=KeywordRecommendation, + ) + text_ad_recommendation: TextAdRecommendation = proto.Field( + proto.MESSAGE, + number=9, + oneof="recommendation", + message=TextAdRecommendation, + ) + target_cpa_opt_in_recommendation: TargetCpaOptInRecommendation = ( + proto.Field( + proto.MESSAGE, + number=10, + oneof="recommendation", + message=TargetCpaOptInRecommendation, + ) + ) + maximize_conversions_opt_in_recommendation: ( + MaximizeConversionsOptInRecommendation + ) = proto.Field( + proto.MESSAGE, + number=11, + oneof="recommendation", + message=MaximizeConversionsOptInRecommendation, + ) + enhanced_cpc_opt_in_recommendation: EnhancedCpcOptInRecommendation = ( + proto.Field( + proto.MESSAGE, + number=12, + oneof="recommendation", + message=EnhancedCpcOptInRecommendation, + ) + ) + search_partners_opt_in_recommendation: SearchPartnersOptInRecommendation = ( + proto.Field( + proto.MESSAGE, + number=14, + oneof="recommendation", + message=SearchPartnersOptInRecommendation, + ) + ) + maximize_clicks_opt_in_recommendation: MaximizeClicksOptInRecommendation = ( + proto.Field( + proto.MESSAGE, + number=15, + oneof="recommendation", + message=MaximizeClicksOptInRecommendation, + ) + ) + optimize_ad_rotation_recommendation: OptimizeAdRotationRecommendation = ( + proto.Field( + proto.MESSAGE, + number=16, + oneof="recommendation", + message=OptimizeAdRotationRecommendation, + ) + ) + keyword_match_type_recommendation: KeywordMatchTypeRecommendation = ( + proto.Field( + proto.MESSAGE, + number=20, + oneof="recommendation", + message=KeywordMatchTypeRecommendation, + ) + ) + move_unused_budget_recommendation: MoveUnusedBudgetRecommendation = ( + proto.Field( + proto.MESSAGE, + number=21, + oneof="recommendation", + message=MoveUnusedBudgetRecommendation, + ) + ) + target_roas_opt_in_recommendation: TargetRoasOptInRecommendation = ( + proto.Field( + proto.MESSAGE, + number=23, + oneof="recommendation", + message=TargetRoasOptInRecommendation, + ) + ) + responsive_search_ad_recommendation: ResponsiveSearchAdRecommendation = ( + proto.Field( + proto.MESSAGE, + number=28, + oneof="recommendation", + message=ResponsiveSearchAdRecommendation, + ) + ) + marginal_roi_campaign_budget_recommendation: ( + CampaignBudgetRecommendation + ) = proto.Field( + proto.MESSAGE, + number=29, + oneof="recommendation", + message=CampaignBudgetRecommendation, + ) + use_broad_match_keyword_recommendation: ( + UseBroadMatchKeywordRecommendation + ) = proto.Field( + proto.MESSAGE, + number=30, + oneof="recommendation", + message=UseBroadMatchKeywordRecommendation, + ) + responsive_search_ad_asset_recommendation: ( + ResponsiveSearchAdAssetRecommendation + ) = proto.Field( + proto.MESSAGE, + number=31, + oneof="recommendation", + message=ResponsiveSearchAdAssetRecommendation, + ) + upgrade_smart_shopping_campaign_to_performance_max_recommendation: ( + UpgradeSmartShoppingCampaignToPerformanceMaxRecommendation + ) = proto.Field( + proto.MESSAGE, + number=32, + oneof="recommendation", + message=UpgradeSmartShoppingCampaignToPerformanceMaxRecommendation, + ) + responsive_search_ad_improve_ad_strength_recommendation: ( + ResponsiveSearchAdImproveAdStrengthRecommendation + ) = proto.Field( + proto.MESSAGE, + number=33, + oneof="recommendation", + message=ResponsiveSearchAdImproveAdStrengthRecommendation, + ) + display_expansion_opt_in_recommendation: ( + DisplayExpansionOptInRecommendation + ) = proto.Field( + proto.MESSAGE, + number=34, + oneof="recommendation", + message=DisplayExpansionOptInRecommendation, + ) + upgrade_local_campaign_to_performance_max_recommendation: ( + UpgradeLocalCampaignToPerformanceMaxRecommendation + ) = proto.Field( + proto.MESSAGE, + number=35, + oneof="recommendation", + message=UpgradeLocalCampaignToPerformanceMaxRecommendation, + ) + raise_target_cpa_bid_too_low_recommendation: ( + RaiseTargetCpaBidTooLowRecommendation + ) = proto.Field( + proto.MESSAGE, + number=36, + oneof="recommendation", + message=RaiseTargetCpaBidTooLowRecommendation, + ) + forecasting_set_target_roas_recommendation: ( + ForecastingSetTargetRoasRecommendation + ) = proto.Field( + proto.MESSAGE, + number=37, + oneof="recommendation", + message=ForecastingSetTargetRoasRecommendation, + ) + callout_asset_recommendation: CalloutAssetRecommendation = proto.Field( + proto.MESSAGE, + number=39, + oneof="recommendation", + message=CalloutAssetRecommendation, + ) + sitelink_asset_recommendation: SitelinkAssetRecommendation = proto.Field( + proto.MESSAGE, + number=40, + oneof="recommendation", + message=SitelinkAssetRecommendation, + ) + call_asset_recommendation: CallAssetRecommendation = proto.Field( + proto.MESSAGE, + number=41, + oneof="recommendation", + message=CallAssetRecommendation, + ) + shopping_add_age_group_recommendation: ( + ShoppingOfferAttributeRecommendation + ) = proto.Field( + proto.MESSAGE, + number=42, + oneof="recommendation", + message=ShoppingOfferAttributeRecommendation, + ) + shopping_add_color_recommendation: ShoppingOfferAttributeRecommendation = ( + proto.Field( + proto.MESSAGE, + number=43, + oneof="recommendation", + message=ShoppingOfferAttributeRecommendation, + ) + ) + shopping_add_gender_recommendation: ShoppingOfferAttributeRecommendation = ( + proto.Field( + proto.MESSAGE, + number=44, + oneof="recommendation", + message=ShoppingOfferAttributeRecommendation, + ) + ) + shopping_add_gtin_recommendation: ShoppingOfferAttributeRecommendation = ( + proto.Field( + proto.MESSAGE, + number=45, + oneof="recommendation", + message=ShoppingOfferAttributeRecommendation, + ) + ) + shopping_add_more_identifiers_recommendation: ( + ShoppingOfferAttributeRecommendation + ) = proto.Field( + proto.MESSAGE, + number=46, + oneof="recommendation", + message=ShoppingOfferAttributeRecommendation, + ) + shopping_add_size_recommendation: ShoppingOfferAttributeRecommendation = ( + proto.Field( + proto.MESSAGE, + number=47, + oneof="recommendation", + message=ShoppingOfferAttributeRecommendation, + ) + ) + shopping_add_products_to_campaign_recommendation: ( + ShoppingAddProductsToCampaignRecommendation + ) = proto.Field( + proto.MESSAGE, + number=48, + oneof="recommendation", + message=ShoppingAddProductsToCampaignRecommendation, + ) + shopping_fix_disapproved_products_recommendation: ( + ShoppingFixDisapprovedProductsRecommendation + ) = proto.Field( + proto.MESSAGE, + number=49, + oneof="recommendation", + message=ShoppingFixDisapprovedProductsRecommendation, + ) + shopping_target_all_offers_recommendation: ( + ShoppingTargetAllOffersRecommendation + ) = proto.Field( + proto.MESSAGE, + number=50, + oneof="recommendation", + message=ShoppingTargetAllOffersRecommendation, + ) + shopping_fix_suspended_merchant_center_account_recommendation: ( + ShoppingMerchantCenterAccountSuspensionRecommendation + ) = proto.Field( + proto.MESSAGE, + number=51, + oneof="recommendation", + message=ShoppingMerchantCenterAccountSuspensionRecommendation, + ) + shopping_fix_merchant_center_account_suspension_warning_recommendation: ( + ShoppingMerchantCenterAccountSuspensionRecommendation + ) = proto.Field( + proto.MESSAGE, + number=52, + oneof="recommendation", + message=ShoppingMerchantCenterAccountSuspensionRecommendation, + ) + shopping_migrate_regular_shopping_campaign_offers_to_performance_max_recommendation: ShoppingMigrateRegularShoppingCampaignOffersToPerformanceMaxRecommendation = proto.Field( + proto.MESSAGE, + number=53, + oneof="recommendation", + message=ShoppingMigrateRegularShoppingCampaignOffersToPerformanceMaxRecommendation, + ) + dynamic_image_extension_opt_in_recommendation: ( + DynamicImageExtensionOptInRecommendation + ) = proto.Field( + proto.MESSAGE, + number=54, + oneof="recommendation", + message=DynamicImageExtensionOptInRecommendation, + ) + raise_target_cpa_recommendation: RaiseTargetCpaRecommendation = proto.Field( + proto.MESSAGE, + number=55, + oneof="recommendation", + message=RaiseTargetCpaRecommendation, + ) + lower_target_roas_recommendation: LowerTargetRoasRecommendation = ( + proto.Field( + proto.MESSAGE, + number=56, + oneof="recommendation", + message=LowerTargetRoasRecommendation, + ) + ) + performance_max_opt_in_recommendation: PerformanceMaxOptInRecommendation = ( + proto.Field( + proto.MESSAGE, + number=57, + oneof="recommendation", + message=PerformanceMaxOptInRecommendation, + ) + ) + improve_performance_max_ad_strength_recommendation: ( + ImprovePerformanceMaxAdStrengthRecommendation + ) = proto.Field( + proto.MESSAGE, + number=58, + oneof="recommendation", + message=ImprovePerformanceMaxAdStrengthRecommendation, + ) + migrate_dynamic_search_ads_campaign_to_performance_max_recommendation: ( + MigrateDynamicSearchAdsCampaignToPerformanceMaxRecommendation + ) = proto.Field( + proto.MESSAGE, + number=59, + oneof="recommendation", + message=MigrateDynamicSearchAdsCampaignToPerformanceMaxRecommendation, + ) + forecasting_set_target_cpa_recommendation: ( + ForecastingSetTargetCpaRecommendation + ) = proto.Field( + proto.MESSAGE, + number=60, + oneof="recommendation", + message=ForecastingSetTargetCpaRecommendation, + ) + set_target_cpa_recommendation: ForecastingSetTargetCpaRecommendation = ( + proto.Field( + proto.MESSAGE, + number=61, + oneof="recommendation", + message=ForecastingSetTargetCpaRecommendation, + ) + ) + set_target_roas_recommendation: ForecastingSetTargetRoasRecommendation = ( + proto.Field( + proto.MESSAGE, + number=62, + oneof="recommendation", + message=ForecastingSetTargetRoasRecommendation, + ) + ) + maximize_conversion_value_opt_in_recommendation: ( + MaximizeConversionValueOptInRecommendation + ) = proto.Field( + proto.MESSAGE, + number=63, + oneof="recommendation", + message=MaximizeConversionValueOptInRecommendation, + ) + improve_google_tag_coverage_recommendation: ( + ImproveGoogleTagCoverageRecommendation + ) = proto.Field( + proto.MESSAGE, + number=64, + oneof="recommendation", + message=ImproveGoogleTagCoverageRecommendation, + ) + performance_max_final_url_opt_in_recommendation: ( + PerformanceMaxFinalUrlOptInRecommendation + ) = proto.Field( + proto.MESSAGE, + number=65, + oneof="recommendation", + message=PerformanceMaxFinalUrlOptInRecommendation, + ) + refresh_customer_match_list_recommendation: ( + RefreshCustomerMatchListRecommendation + ) = proto.Field( + proto.MESSAGE, + number=66, + oneof="recommendation", + message=RefreshCustomerMatchListRecommendation, + ) + custom_audience_opt_in_recommendation: CustomAudienceOptInRecommendation = ( + proto.Field( + proto.MESSAGE, + number=67, + oneof="recommendation", + message=CustomAudienceOptInRecommendation, + ) + ) + lead_form_asset_recommendation: LeadFormAssetRecommendation = proto.Field( + proto.MESSAGE, + number=68, + oneof="recommendation", + message=LeadFormAssetRecommendation, + ) + improve_demand_gen_ad_strength_recommendation: ( + ImproveDemandGenAdStrengthRecommendation + ) = proto.Field( + proto.MESSAGE, + number=69, + oneof="recommendation", + message=ImproveDemandGenAdStrengthRecommendation, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/recommendation_subscription.py b/google/ads/googleads/v24/resources/types/recommendation_subscription.py new file mode 100644 index 000000000..162476bfe --- /dev/null +++ b/google/ads/googleads/v24/resources/types/recommendation_subscription.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + recommendation_subscription_status, +) +from google.ads.googleads.v24.enums.types import recommendation_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "RecommendationSubscription", + }, +) + + +class RecommendationSubscription(proto.Message): + r"""Recommendation Subscription resource + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the recommendation + subscription. + + ``customers/{customer_id}/recommendationSubscriptions/{recommendation_type}`` + type_ (google.ads.googleads.v24.enums.types.RecommendationTypeEnum.RecommendationType): + Required. Immutable. The type of + recommendation subscribed to. + create_date_time (str): + Output only. Time in seconds when the + subscription was first created. The datetime is + in the customer's time zone and in "yyyy-MM-dd + HH:mm:ss" format. + + This field is a member of `oneof`_ ``_create_date_time``. + modify_date_time (str): + Output only. Contains the time in + microseconds, when the Recommendation + Subscription was last updated. The datetime is + in the customer's time zone and in "yyyy-MM-dd + HH:mm:ss.ssssss" format. + + This field is a member of `oneof`_ ``_modify_date_time``. + status (google.ads.googleads.v24.enums.types.RecommendationSubscriptionStatusEnum.RecommendationSubscriptionStatus): + Required. Status of the subscription, either + enabled or paused. + + This field is a member of `oneof`_ ``_status``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + type_: recommendation_type.RecommendationTypeEnum.RecommendationType = ( + proto.Field( + proto.ENUM, + number=2, + enum=recommendation_type.RecommendationTypeEnum.RecommendationType, + ) + ) + create_date_time: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + modify_date_time: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + status: ( + recommendation_subscription_status.RecommendationSubscriptionStatusEnum.RecommendationSubscriptionStatus + ) = proto.Field( + proto.ENUM, + number=5, + optional=True, + enum=recommendation_subscription_status.RecommendationSubscriptionStatusEnum.RecommendationSubscriptionStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/remarketing_action.py b/google/ads/googleads/v24/resources/types/remarketing_action.py new file mode 100644 index 000000000..6e7e96346 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/remarketing_action.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import tag_snippet + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "RemarketingAction", + }, +) + + +class RemarketingAction(proto.Message): + r"""A remarketing action. A snippet of JavaScript code that will + collect the product id and the type of page people visited + (product page, shopping cart page, purchase page, general site + visit) on an advertiser's website. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the remarketing action. + Remarketing action resource names have the form: + + ``customers/{customer_id}/remarketingActions/{remarketing_action_id}`` + id (int): + Output only. Id of the remarketing action. + + This field is a member of `oneof`_ ``_id``. + name (str): + The name of the remarketing action. + + This field is required and should not be empty + when creating new remarketing actions. + + This field is a member of `oneof`_ ``_name``. + tag_snippets (MutableSequence[google.ads.googleads.v24.common.types.TagSnippet]): + Output only. The snippets used for tracking + remarketing actions. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + tag_snippets: MutableSequence[tag_snippet.TagSnippet] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=tag_snippet.TagSnippet, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/search_term_view.py b/google/ads/googleads/v24/resources/types/search_term_view.py new file mode 100644 index 000000000..1ec4a8842 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/search_term_view.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import search_term_targeting_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "SearchTermView", + }, +) + + +class SearchTermView(proto.Message): + r"""A search term view with metrics aggregated by search term at + the ad group level. This view does not include Performance Max + data. If you are looking for Performance Max search term data, + use the CampaignSearchTermView instead. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the search term view. + Search term view resource names have the form: + + ``customers/{customer_id}/searchTermViews/{campaign_id}~{ad_group_id}~{URL-base64_search_term}`` + search_term (str): + Output only. The search term. + + This field is a member of `oneof`_ ``_search_term``. + ad_group (str): + Output only. The ad group the search term + served in. + + This field is a member of `oneof`_ ``_ad_group``. + status (google.ads.googleads.v24.enums.types.SearchTermTargetingStatusEnum.SearchTermTargetingStatus): + Output only. Indicates whether the search + term is currently one of your targeted or + excluded keywords. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + search_term: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + ad_group: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + status: ( + search_term_targeting_status.SearchTermTargetingStatusEnum.SearchTermTargetingStatus + ) = proto.Field( + proto.ENUM, + number=4, + enum=search_term_targeting_status.SearchTermTargetingStatusEnum.SearchTermTargetingStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/shared_criterion.py b/google/ads/googleads/v24/resources/types/shared_criterion.py new file mode 100644 index 000000000..549325a88 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/shared_criterion.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.enums.types import criterion_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "SharedCriterion", + }, +) + + +class SharedCriterion(proto.Message): + r"""A criterion belonging to a shared set. + + 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: + resource_name (str): + Immutable. The resource name of the shared criterion. Shared + set resource names have the form: + + ``customers/{customer_id}/sharedCriteria/{shared_set_id}~{criterion_id}`` + shared_set (str): + Immutable. The shared set to which the shared + criterion belongs. + + This field is a member of `oneof`_ ``_shared_set``. + criterion_id (int): + Output only. The ID of the criterion. + + This field is ignored for mutates. + + This field is a member of `oneof`_ ``_criterion_id``. + type_ (google.ads.googleads.v24.enums.types.CriterionTypeEnum.CriterionType): + Output only. The type of the criterion. + negative (bool): + Immutable. If true, the criterion is + excluded. If false, the criterion is targeted. + + This field is a member of `oneof`_ ``_negative``. + keyword (google.ads.googleads.v24.common.types.KeywordInfo): + Immutable. Keyword. + + This field is a member of `oneof`_ ``criterion``. + youtube_video (google.ads.googleads.v24.common.types.YouTubeVideoInfo): + Immutable. YouTube Video. + + This field is a member of `oneof`_ ``criterion``. + youtube_channel (google.ads.googleads.v24.common.types.YouTubeChannelInfo): + Immutable. YouTube Channel. + + This field is a member of `oneof`_ ``criterion``. + placement (google.ads.googleads.v24.common.types.PlacementInfo): + Immutable. Placement. + + This field is a member of `oneof`_ ``criterion``. + mobile_app_category (google.ads.googleads.v24.common.types.MobileAppCategoryInfo): + Immutable. Mobile App Category. + + This field is a member of `oneof`_ ``criterion``. + mobile_application (google.ads.googleads.v24.common.types.MobileApplicationInfo): + Immutable. Mobile application. + + This field is a member of `oneof`_ ``criterion``. + brand (google.ads.googleads.v24.common.types.BrandInfo): + Immutable. Brand. + + This field is a member of `oneof`_ ``criterion``. + webpage (google.ads.googleads.v24.common.types.WebpageInfo): + Immutable. Webpage. + + This field is a member of `oneof`_ ``criterion``. + vertical_ads_item_group_rule (google.ads.googleads.v24.common.types.VerticalAdsItemGroupRuleInfo): + Immutable. Vertical ads item group rule. + + This field is a member of `oneof`_ ``criterion``. + retail_filter (google.ads.googleads.v24.common.types.RetailFilter): + Immutable. Retail Filter. + + This field is a member of `oneof`_ ``criterion``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + shared_set: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + criterion_id: int = proto.Field( + proto.INT64, + number=11, + optional=True, + ) + type_: criterion_type.CriterionTypeEnum.CriterionType = proto.Field( + proto.ENUM, + number=4, + enum=criterion_type.CriterionTypeEnum.CriterionType, + ) + negative: bool = proto.Field( + proto.BOOL, + number=15, + optional=True, + ) + keyword: criteria.KeywordInfo = proto.Field( + proto.MESSAGE, + number=3, + oneof="criterion", + message=criteria.KeywordInfo, + ) + youtube_video: criteria.YouTubeVideoInfo = proto.Field( + proto.MESSAGE, + number=5, + oneof="criterion", + message=criteria.YouTubeVideoInfo, + ) + youtube_channel: criteria.YouTubeChannelInfo = proto.Field( + proto.MESSAGE, + number=6, + oneof="criterion", + message=criteria.YouTubeChannelInfo, + ) + placement: criteria.PlacementInfo = proto.Field( + proto.MESSAGE, + number=7, + oneof="criterion", + message=criteria.PlacementInfo, + ) + mobile_app_category: criteria.MobileAppCategoryInfo = proto.Field( + proto.MESSAGE, + number=8, + oneof="criterion", + message=criteria.MobileAppCategoryInfo, + ) + mobile_application: criteria.MobileApplicationInfo = proto.Field( + proto.MESSAGE, + number=9, + oneof="criterion", + message=criteria.MobileApplicationInfo, + ) + brand: criteria.BrandInfo = proto.Field( + proto.MESSAGE, + number=12, + oneof="criterion", + message=criteria.BrandInfo, + ) + webpage: criteria.WebpageInfo = proto.Field( + proto.MESSAGE, + number=13, + oneof="criterion", + message=criteria.WebpageInfo, + ) + vertical_ads_item_group_rule: criteria.VerticalAdsItemGroupRuleInfo = ( + proto.Field( + proto.MESSAGE, + number=14, + oneof="criterion", + message=criteria.VerticalAdsItemGroupRuleInfo, + ) + ) + retail_filter: criteria.RetailFilter = proto.Field( + proto.MESSAGE, + number=181, + oneof="criterion", + message=criteria.RetailFilter, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/shared_set.py b/google/ads/googleads/v24/resources/types/shared_set.py new file mode 100644 index 000000000..3e308ea7e --- /dev/null +++ b/google/ads/googleads/v24/resources/types/shared_set.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import shared_set_status +from google.ads.googleads.v24.enums.types import shared_set_type +from google.ads.googleads.v24.enums.types import ( + vertical_ads_item_vertical_type as gage_vertical_ads_item_vertical_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "SharedSet", + }, +) + + +class SharedSet(proto.Message): + r"""SharedSets are used for sharing criterion exclusions across + multiple campaigns. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the shared set. Shared set + resource names have the form: + + ``customers/{customer_id}/sharedSets/{shared_set_id}`` + id (int): + Output only. The ID of this shared set. Read + only. + + This field is a member of `oneof`_ ``_id``. + type_ (google.ads.googleads.v24.enums.types.SharedSetTypeEnum.SharedSetType): + Immutable. The type of this shared set: each + shared set holds only a single kind of resource. + Required. Immutable. + name (str): + The name of this shared set. Required. + Shared Sets must have names that are unique + among active shared sets of the same type. + The length of this string should be between 1 + and 255 UTF-8 bytes, inclusive. + + This field is a member of `oneof`_ ``_name``. + status (google.ads.googleads.v24.enums.types.SharedSetStatusEnum.SharedSetStatus): + Output only. The status of this shared set. + Read only. + member_count (int): + Output only. The number of shared criteria + within this shared set. Read only. + + This field is a member of `oneof`_ ``_member_count``. + reference_count (int): + Output only. The number of campaigns + associated with this shared set. Read only. + + This field is a member of `oneof`_ ``_reference_count``. + vertical_ads_item_vertical_type (google.ads.googleads.v24.enums.types.VerticalAdsItemVerticalTypeEnum.VerticalAdsItemVerticalType): + Immutable. Shared sets of type + VERTICAL_ADS_ITEM_GROUP_RULE_LIST are associated with a + particular vertical (e.g. hotels, things to do, flights, + etc.). This field is required for shared sets of type + VERTICAL_ADS_ITEM_GROUP_RULE_LIST. + + This field is a member of `oneof`_ ``_vertical_ads_item_vertical_type``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + type_: shared_set_type.SharedSetTypeEnum.SharedSetType = proto.Field( + proto.ENUM, + number=3, + enum=shared_set_type.SharedSetTypeEnum.SharedSetType, + ) + name: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + status: shared_set_status.SharedSetStatusEnum.SharedSetStatus = proto.Field( + proto.ENUM, + number=5, + enum=shared_set_status.SharedSetStatusEnum.SharedSetStatus, + ) + member_count: int = proto.Field( + proto.INT64, + number=10, + optional=True, + ) + reference_count: int = proto.Field( + proto.INT64, + number=11, + optional=True, + ) + vertical_ads_item_vertical_type: ( + gage_vertical_ads_item_vertical_type.VerticalAdsItemVerticalTypeEnum.VerticalAdsItemVerticalType + ) = proto.Field( + proto.ENUM, + number=12, + optional=True, + enum=gage_vertical_ads_item_vertical_type.VerticalAdsItemVerticalTypeEnum.VerticalAdsItemVerticalType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/shopping_performance_view.py b/google/ads/googleads/v24/resources/types/shopping_performance_view.py new file mode 100644 index 000000000..023f91445 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/shopping_performance_view.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ShoppingPerformanceView", + }, +) + + +class ShoppingPerformanceView(proto.Message): + r"""Shopping performance view. + + Provides Shopping campaign and Performance Max campaign statistics + aggregated at several product dimension levels. Product dimension + values from Merchant Center such as brand, category, custom + attributes, product condition, and product type will reflect the + state of each dimension as of the date and time when the + corresponding event was recorded. + + The number of impressions and clicks that + ``shopping_performance_view`` returns stats for may be different + from campaign reports. ``shopping_performance_view`` shows + impressions and clicks on products appearing in ads, while campaign + reports show impressions and clicks on the ads themselves. Depending + on the format, an ad can show from zero to several products, so the + numbers may not match. + + In Google Ads UI, you can query impressions and clicks of products + appearing in ads by selecting a column from "Product attributes" in + the report editor. For example, selecting the "Brand" column is + equivalent to selecting ``segments.product_brand``. + + Attributes: + resource_name (str): + Output only. The resource name of the Shopping performance + view. Shopping performance view resource names have the + form: ``customers/{customer_id}/shoppingPerformanceView`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/shopping_product.py b/google/ads/googleads/v24/resources/types/shopping_product.py new file mode 100644 index 000000000..86b05e1b4 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/shopping_product.py @@ -0,0 +1,533 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import product_availability +from google.ads.googleads.v24.enums.types import product_channel +from google.ads.googleads.v24.enums.types import product_channel_exclusivity +from google.ads.googleads.v24.enums.types import product_condition +from google.ads.googleads.v24.enums.types import product_issue_severity +from google.ads.googleads.v24.enums.types import product_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ShoppingProduct", + }, +) + + +class ShoppingProduct(proto.Message): + r"""A shopping product from Google Merchant Center that can be + advertised by campaigns. + + The resource returns currently existing products from Google + Merchant Center accounts linked with the customer. A campaign + includes a product by specifying its merchant id (or, if available, + the Multi Client Account id of the merchant) in the + ``ShoppingSetting``, and can limit the inclusion to products having + a specified feed label. Standard Shopping campaigns can also limit + the inclusion through a ``campaign_criterion.listing_scope``. + + Queries to this resource specify a scope: + + - Account: + + - Filters on campaigns or ad groups are not specified. + - All products from the linked Google Merchant Center accounts are + returned. + - Metrics and some fields (see the per-field documentation) are + aggregated across all Shopping and Performance Max campaigns + that include a product. + + - Campaign: + + - An equality filter on ``campaign`` is specified. Supported + campaign types are Shopping, Performance Max, Demand Gen, Video, + App. + - Only products that are included by the specified campaign are + returned. + - Metrics and some fields (see the per-field documentation) are + restricted to the specified campaign. + - Only the following metrics are supported for Demand Gen, Video, + App campaigns: impressions, clicks, ctr. + + - Ad group: + + - An equality filter on ``ad_group`` and ``campaign`` is + specified. Supported campaign types are Shopping, Demand Gen, + Video, App. + - Only products that are included by the specified campaign are + returned. + - Metrics and some fields (see the per-field documentation) are + restricted to the specified ad group. + - Only the following metrics are supported for Demand Gen, Video, + App campaigns: impressions, clicks, ctr. + + Note that segmentation by date segments is not permitted and will + return UNSUPPORTED_DATE_SEGMENTATION error. On the other hand, + filtering on date segments is allowed. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the shopping product. + Shopping product resource names have the form: + + ``customers/{customer_id}/shoppingProducts/{merchant_center_id}~{channel}~{language_code}~{feed_label}~{item_id}`` + merchant_center_id (int): + Output only. The id of the merchant that owns + the product. + channel (google.ads.googleads.v24.enums.types.ProductChannelEnum.ProductChannel): + Output only. The product channel describing + the locality of the product. + language_code (str): + Output only. The language code as provided by + the merchant, in BCP 47 format. + feed_label (str): + Output only. The product feed label as + provided by the merchant. + item_id (str): + Output only. The item id of the product as + provided by the merchant. + multi_client_account_id (int): + Output only. The id of the Multi Client + Account of the merchant, if present. + + This field is a member of `oneof`_ ``_multi_client_account_id``. + title (str): + Output only. The title of the product as + provided by the merchant. + + This field is a member of `oneof`_ ``_title``. + brand (str): + Output only. The brand of the product as + provided by the merchant. + + This field is a member of `oneof`_ ``_brand``. + product_image_uri (str): + Output only. The URI of the product image as + provided by the merchant. + + This field is a member of `oneof`_ ``_product_image_uri``. + price_micros (int): + Output only. The price of the product in micros as provided + by the merchant, in the currency specified in + ``currency_code`` (e.g. $2.97 is reported as 2970000). + + This field is a member of `oneof`_ ``_price_micros``. + currency_code (str): + Output only. The currency code as provided by + the merchant, in ISO 4217 format. + + This field is a member of `oneof`_ ``_currency_code``. + channel_exclusivity (google.ads.googleads.v24.enums.types.ProductChannelExclusivityEnum.ProductChannelExclusivity): + Output only. The channel exclusivity of the + product as provided by the merchant. + + This field is a member of `oneof`_ ``_channel_exclusivity``. + condition (google.ads.googleads.v24.enums.types.ProductConditionEnum.ProductCondition): + Output only. The condition of the product as + provided by the merchant. + + This field is a member of `oneof`_ ``_condition``. + availability (google.ads.googleads.v24.enums.types.ProductAvailabilityEnum.ProductAvailability): + Output only. The availability of the product + as provided by the merchant. + + This field is a member of `oneof`_ ``_availability``. + target_countries (MutableSequence[str]): + Output only. Upper-case two-letter ISO 3166-1 + code of the regions where the product is + intended to be shown in ads. + custom_attribute0 (str): + Output only. The custom attribute 0 of the + product as provided by the merchant. + + This field is a member of `oneof`_ ``_custom_attribute0``. + custom_attribute1 (str): + Output only. The custom attribute 1 of the + product as provided by the merchant. + + This field is a member of `oneof`_ ``_custom_attribute1``. + custom_attribute2 (str): + Output only. The custom attribute 2 of the + product as provided by the merchant. + + This field is a member of `oneof`_ ``_custom_attribute2``. + custom_attribute3 (str): + Output only. The custom attribute 3 of the + product as provided by the merchant. + + This field is a member of `oneof`_ ``_custom_attribute3``. + custom_attribute4 (str): + Output only. The custom attribute 4 of the + product as provided by the merchant. + + This field is a member of `oneof`_ ``_custom_attribute4``. + category_level1 (str): + Output only. The category level 1 of the + product. + + This field is a member of `oneof`_ ``_category_level1``. + category_level2 (str): + Output only. The category level 2 of the + product. + + This field is a member of `oneof`_ ``_category_level2``. + category_level3 (str): + Output only. The category level 3 of the + product. + + This field is a member of `oneof`_ ``_category_level3``. + category_level4 (str): + Output only. The category level 4 of the + product. + + This field is a member of `oneof`_ ``_category_level4``. + category_level5 (str): + Output only. The category level 5 of the + product. + + This field is a member of `oneof`_ ``_category_level5``. + product_type_level1 (str): + Output only. The product type level 1 as + provided by the merchant. + + This field is a member of `oneof`_ ``_product_type_level1``. + product_type_level2 (str): + Output only. The product type level 2 as + provided by the merchant. + + This field is a member of `oneof`_ ``_product_type_level2``. + product_type_level3 (str): + Output only. The product type level 3 as + provided by the merchant. + + This field is a member of `oneof`_ ``_product_type_level3``. + product_type_level4 (str): + Output only. The product type level 4 as + provided by the merchant. + + This field is a member of `oneof`_ ``_product_type_level4``. + product_type_level5 (str): + Output only. The product type level 5 as + provided by the merchant. + + This field is a member of `oneof`_ ``_product_type_level5``. + effective_max_cpc_micros (int): + Output only. The effective maximum + cost-per-click (effective max. CPC) of the + product. This field is available only if the + query specifies the campaign or ad group scope, + and if the campaign uses manual bidding. The + value is the highest bid set for the product in + product groups across all enabled ad groups. It + represents the most you're willing to pay for a + click on the product. This field can take up to + 24 hours to update. + + This field is a member of `oneof`_ ``_effective_max_cpc_micros``. + status (google.ads.googleads.v24.enums.types.ProductStatusEnum.ProductStatus): + Output only. The status that indicates + whether the product can show in ads. The value + of this field is restricted to the scope + specified in the query, see the documentation of + the resource. + This field can take up to 24 hours to update. + This field is not supported for App campaigns. + issues (MutableSequence[google.ads.googleads.v24.resources.types.ShoppingProduct.ProductIssue]): + Output only. The list of issues affecting + whether the product can show in ads. The value + of this field is restricted to the scope + specified in the query, see the documentation of + the resource. This field can take up to 24 hours + to update. This field is not supported for App + campaigns. + campaign (str): + Output only. A campaign that includes the product. This + field is selectable only in the campaign scope, which + requires an equality filter on ``campaign``. + + This field is a member of `oneof`_ ``_campaign``. + ad_group (str): + Output only. An ad group of a campaign that includes the + product. This field is selectable only in the ad group + scope, which requires an equality filter on ``campaign`` and + ``ad_group``. + + This field is a member of `oneof`_ ``_ad_group``. + """ + + class ProductIssue(proto.Message): + r"""An issue affecting whether a product can show in ads. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + error_code (str): + Output only. The error code that identifies + the issue. + ads_severity (google.ads.googleads.v24.enums.types.ProductIssueSeverityEnum.ProductIssueSeverity): + Output only. The severity of the issue in + Google Ads. + attribute_name (str): + Output only. The name of the product's + attribute, if any, that triggered the issue. + + This field is a member of `oneof`_ ``_attribute_name``. + description (str): + Output only. The short description of the + issue in English. + detail (str): + Output only. The detailed description of the + issue in English. + documentation (str): + Output only. The URL of the Help Center + article for the issue. + affected_regions (MutableSequence[str]): + Output only. List of upper-case two-letter + ISO 3166-1 codes of the regions affected by the + issue. If empty, all regions are affected. + """ + + error_code: str = proto.Field( + proto.STRING, + number=1, + ) + ads_severity: ( + product_issue_severity.ProductIssueSeverityEnum.ProductIssueSeverity + ) = proto.Field( + proto.ENUM, + number=2, + enum=product_issue_severity.ProductIssueSeverityEnum.ProductIssueSeverity, + ) + attribute_name: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + description: str = proto.Field( + proto.STRING, + number=4, + ) + detail: str = proto.Field( + proto.STRING, + number=5, + ) + documentation: str = proto.Field( + proto.STRING, + number=6, + ) + affected_regions: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=7, + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + merchant_center_id: int = proto.Field( + proto.INT64, + number=2, + ) + channel: product_channel.ProductChannelEnum.ProductChannel = proto.Field( + proto.ENUM, + number=3, + enum=product_channel.ProductChannelEnum.ProductChannel, + ) + language_code: str = proto.Field( + proto.STRING, + number=4, + ) + feed_label: str = proto.Field( + proto.STRING, + number=5, + ) + item_id: str = proto.Field( + proto.STRING, + number=6, + ) + multi_client_account_id: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + title: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + brand: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + product_image_uri: str = proto.Field( + proto.STRING, + number=36, + optional=True, + ) + price_micros: int = proto.Field( + proto.INT64, + number=10, + optional=True, + ) + currency_code: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + channel_exclusivity: ( + product_channel_exclusivity.ProductChannelExclusivityEnum.ProductChannelExclusivity + ) = proto.Field( + proto.ENUM, + number=12, + optional=True, + enum=product_channel_exclusivity.ProductChannelExclusivityEnum.ProductChannelExclusivity, + ) + condition: product_condition.ProductConditionEnum.ProductCondition = ( + proto.Field( + proto.ENUM, + number=13, + optional=True, + enum=product_condition.ProductConditionEnum.ProductCondition, + ) + ) + availability: ( + product_availability.ProductAvailabilityEnum.ProductAvailability + ) = proto.Field( + proto.ENUM, + number=14, + optional=True, + enum=product_availability.ProductAvailabilityEnum.ProductAvailability, + ) + target_countries: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=15, + ) + custom_attribute0: str = proto.Field( + proto.STRING, + number=16, + optional=True, + ) + custom_attribute1: str = proto.Field( + proto.STRING, + number=17, + optional=True, + ) + custom_attribute2: str = proto.Field( + proto.STRING, + number=18, + optional=True, + ) + custom_attribute3: str = proto.Field( + proto.STRING, + number=19, + optional=True, + ) + custom_attribute4: str = proto.Field( + proto.STRING, + number=20, + optional=True, + ) + category_level1: str = proto.Field( + proto.STRING, + number=21, + optional=True, + ) + category_level2: str = proto.Field( + proto.STRING, + number=22, + optional=True, + ) + category_level3: str = proto.Field( + proto.STRING, + number=23, + optional=True, + ) + category_level4: str = proto.Field( + proto.STRING, + number=24, + optional=True, + ) + category_level5: str = proto.Field( + proto.STRING, + number=25, + optional=True, + ) + product_type_level1: str = proto.Field( + proto.STRING, + number=26, + optional=True, + ) + product_type_level2: str = proto.Field( + proto.STRING, + number=27, + optional=True, + ) + product_type_level3: str = proto.Field( + proto.STRING, + number=28, + optional=True, + ) + product_type_level4: str = proto.Field( + proto.STRING, + number=29, + optional=True, + ) + product_type_level5: str = proto.Field( + proto.STRING, + number=30, + optional=True, + ) + effective_max_cpc_micros: int = proto.Field( + proto.INT64, + number=31, + optional=True, + ) + status: product_status.ProductStatusEnum.ProductStatus = proto.Field( + proto.ENUM, + number=32, + enum=product_status.ProductStatusEnum.ProductStatus, + ) + issues: MutableSequence[ProductIssue] = proto.RepeatedField( + proto.MESSAGE, + number=33, + message=ProductIssue, + ) + campaign: str = proto.Field( + proto.STRING, + number=34, + optional=True, + ) + ad_group: str = proto.Field( + proto.STRING, + number=35, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/smart_campaign_search_term_view.py b/google/ads/googleads/v24/resources/types/smart_campaign_search_term_view.py new file mode 100644 index 000000000..76d614aec --- /dev/null +++ b/google/ads/googleads/v24/resources/types/smart_campaign_search_term_view.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "SmartCampaignSearchTermView", + }, +) + + +class SmartCampaignSearchTermView(proto.Message): + r"""A Smart campaign search term view. + + Attributes: + resource_name (str): + Output only. The resource name of the Smart campaign search + term view. Smart campaign search term view resource names + have the form: + + ``customers/{customer_id}/smartCampaignSearchTermViews/{campaign_id}~{URL-base64_search_term}`` + search_term (str): + Output only. The search term. + campaign (str): + Output only. The Smart campaign the search + term served in. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + search_term: str = proto.Field( + proto.STRING, + number=2, + ) + campaign: str = proto.Field( + proto.STRING, + number=3, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/smart_campaign_setting.py b/google/ads/googleads/v24/resources/types/smart_campaign_setting.py new file mode 100644 index 000000000..6564886ec --- /dev/null +++ b/google/ads/googleads/v24/resources/types/smart_campaign_setting.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "SmartCampaignSetting", + }, +) + + +class SmartCampaignSetting(proto.Message): + r"""Settings for configuring Smart campaigns. + + 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: + resource_name (str): + Immutable. The resource name of the Smart campaign setting. + Smart campaign setting resource names have the form: + + ``customers/{customer_id}/smartCampaignSettings/{campaign_id}`` + campaign (str): + Output only. The campaign to which these + settings apply. + phone_number (google.ads.googleads.v24.resources.types.SmartCampaignSetting.PhoneNumber): + Phone number and country code. + advertising_language_code (str): + The language code to advertise in from the set of [supported + language codes] + (https://developers.google.com/google-ads/api/reference/data/codes-formats#languages). + final_url (str): + The user-provided landing page URL for this + Campaign. + + This field is a member of `oneof`_ ``landing_page``. + ad_optimized_business_profile_setting (google.ads.googleads.v24.resources.types.SmartCampaignSetting.AdOptimizedBusinessProfileSetting): + Settings for configuring a business profile + optimized for ads as this campaign's landing + page. This campaign must be linked to a + business profile to use this option. For more + information on this feature, consult + https://support.google.com/google-ads/answer/9827068. + + This field is a member of `oneof`_ ``landing_page``. + business_name (str): + The name of the business. + + This field is a member of `oneof`_ ``business_setting``. + business_profile_location (str): + The resource name of a Business Profile location. Business + Profile location resource names can be fetched through the + Business Profile API and adhere to the following format: + ``locations/{locationId}``. + + See the [Business Profile API] + (https://developers.google.com/my-business/reference/businessinformation/rest/v1/accounts.locations) + for additional details. + + This field is a member of `oneof`_ ``business_setting``. + """ + + class PhoneNumber(proto.Message): + r"""Phone number and country code in smart campaign settings. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + phone_number (str): + Phone number of the smart campaign. + + This field is a member of `oneof`_ ``_phone_number``. + country_code (str): + Upper-case, two-letter country code as + defined by ISO-3166. + + This field is a member of `oneof`_ ``_country_code``. + """ + + phone_number: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + country_code: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + class AdOptimizedBusinessProfileSetting(proto.Message): + r"""Settings for configuring a business profile optimized for ads + as this campaign's landing page. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + include_lead_form (bool): + Enabling a lead form on your business profile + enables prospective customers to contact your + business by filling out a simple form, and + you'll receive their information through email. + + This field is a member of `oneof`_ ``_include_lead_form``. + """ + + include_lead_form: bool = proto.Field( + proto.BOOL, + number=1, + optional=True, + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=2, + ) + phone_number: PhoneNumber = proto.Field( + proto.MESSAGE, + number=3, + message=PhoneNumber, + ) + advertising_language_code: str = proto.Field( + proto.STRING, + number=7, + ) + final_url: str = proto.Field( + proto.STRING, + number=8, + oneof="landing_page", + ) + ad_optimized_business_profile_setting: AdOptimizedBusinessProfileSetting = ( + proto.Field( + proto.MESSAGE, + number=9, + oneof="landing_page", + message=AdOptimizedBusinessProfileSetting, + ) + ) + business_name: str = proto.Field( + proto.STRING, + number=5, + oneof="business_setting", + ) + business_profile_location: str = proto.Field( + proto.STRING, + number=10, + oneof="business_setting", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/targeting_expansion_view.py b/google/ads/googleads/v24/resources/types/targeting_expansion_view.py new file mode 100644 index 000000000..0071dc9e5 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/targeting_expansion_view.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "TargetingExpansionView", + }, +) + + +class TargetingExpansionView(proto.Message): + r"""A targeting expansion view with metrics. + Returns metrics for automated expansion over manual targeting. + + Attributes: + resource_name (str): + Output only. The resource name of the targeting expansion + view. Targeting expansion view resource names have the form: + + ``customers/{customer_id}/targetingExpansionViews/{campaign_id}~{targeting_expansion_type}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/third_party_app_analytics_link.py b/google/ads/googleads/v24/resources/types/third_party_app_analytics_link.py new file mode 100644 index 000000000..ebb5956d2 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/third_party_app_analytics_link.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "ThirdPartyAppAnalyticsLink", + }, +) + + +class ThirdPartyAppAnalyticsLink(proto.Message): + r"""A data sharing connection, allowing the import of third party + app analytics into a Google Ads Customer. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Immutable. The resource name of the third party app + analytics link. Third party app analytics link resource + names have the form: + + ``customers/{customer_id}/thirdPartyAppAnalyticsLinks/{account_link_id}`` + shareable_link_id (str): + Output only. The shareable link ID that + should be provided to the third party when + setting up app analytics. This is able to be + regenerated using regenerate method in the + ThirdPartyAppAnalyticsLinkService. + + This field is a member of `oneof`_ ``_shareable_link_id``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + shareable_link_id: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/topic_constant.py b/google/ads/googleads/v24/resources/types/topic_constant.py new file mode 100644 index 000000000..9cdccd032 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/topic_constant.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "TopicConstant", + }, +) + + +class TopicConstant(proto.Message): + r"""Use topics to target or exclude placements in the Google + Display Network based on the category into which the placement + falls (for example, "Pets & Animals/Pets/Dogs"). + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the topic constant. topic + constant resource names have the form: + + ``topicConstants/{topic_id}`` + id (int): + Output only. The ID of the topic. + + This field is a member of `oneof`_ ``_id``. + topic_constant_parent (str): + Output only. Resource name of parent of the + topic constant. + + This field is a member of `oneof`_ ``_topic_constant_parent``. + path (MutableSequence[str]): + Output only. The category to target or + exclude. Each subsequent element in the array + describes a more specific sub-category. For + example, {"Pets & Animals", "Pets", "Dogs"} + represents the "Pets & Animals/Pets/Dogs" + category. List of available topic categories at + https://developers.google.com/google-ads/api/reference/data/verticals + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + topic_constant_parent: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + path: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=7, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/topic_view.py b/google/ads/googleads/v24/resources/types/topic_view.py new file mode 100644 index 000000000..b692b94e3 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/topic_view.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "TopicView", + }, +) + + +class TopicView(proto.Message): + r"""A topic view. + + Attributes: + resource_name (str): + Output only. The resource name of the topic view. Topic view + resource names have the form: + + ``customers/{customer_id}/topicViews/{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/travel_activity_group_view.py b/google/ads/googleads/v24/resources/types/travel_activity_group_view.py new file mode 100644 index 000000000..36e6264e4 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/travel_activity_group_view.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "TravelActivityGroupView", + }, +) + + +class TravelActivityGroupView(proto.Message): + r"""A travel activity group view. + + Attributes: + resource_name (str): + Output only. The resource name of the travel activity group + view. Travel Activity Group view resource names have the + form: + + ``customers/{customer_id}/travelActivityGroupViews/{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/travel_activity_performance_view.py b/google/ads/googleads/v24/resources/types/travel_activity_performance_view.py new file mode 100644 index 000000000..04cffba54 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/travel_activity_performance_view.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "TravelActivityPerformanceView", + }, +) + + +class TravelActivityPerformanceView(proto.Message): + r"""A travel activity performance view. + + Attributes: + resource_name (str): + Output only. The resource name of the travel activity + performance view. Travel Activity performance view resource + names have the form: + + ``customers/{customer_id}/travelActivityPerformanceView`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/user_interest.py b/google/ads/googleads/v24/resources/types/user_interest.py new file mode 100644 index 000000000..e699cd3f7 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/user_interest.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import ( + criterion_category_availability, +) +from google.ads.googleads.v24.enums.types import user_interest_taxonomy_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "UserInterest", + }, +) + + +class UserInterest(proto.Message): + r"""A user interest: a particular interest-based vertical to be + targeted. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the user interest. User + interest resource names have the form: + + ``customers/{customer_id}/userInterests/{user_interest_id}`` + taxonomy_type (google.ads.googleads.v24.enums.types.UserInterestTaxonomyTypeEnum.UserInterestTaxonomyType): + Output only. Taxonomy type of the user + interest. + user_interest_id (int): + Output only. The ID of the user interest. + + This field is a member of `oneof`_ ``_user_interest_id``. + name (str): + Output only. The name of the user interest. + + This field is a member of `oneof`_ ``_name``. + user_interest_parent (str): + Output only. The parent of the user interest. + + This field is a member of `oneof`_ ``_user_interest_parent``. + launched_to_all (bool): + Output only. True if the user interest is + launched to all channels and locales. + + This field is a member of `oneof`_ ``_launched_to_all``. + availabilities (MutableSequence[google.ads.googleads.v24.common.types.CriterionCategoryAvailability]): + Output only. Availability information of the + user interest. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + taxonomy_type: ( + user_interest_taxonomy_type.UserInterestTaxonomyTypeEnum.UserInterestTaxonomyType + ) = proto.Field( + proto.ENUM, + number=2, + enum=user_interest_taxonomy_type.UserInterestTaxonomyTypeEnum.UserInterestTaxonomyType, + ) + user_interest_id: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + user_interest_parent: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + launched_to_all: bool = proto.Field( + proto.BOOL, + number=11, + optional=True, + ) + availabilities: MutableSequence[ + criterion_category_availability.CriterionCategoryAvailability + ] = proto.RepeatedField( + proto.MESSAGE, + number=7, + message=criterion_category_availability.CriterionCategoryAvailability, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/user_list.py b/google/ads/googleads/v24/resources/types/user_list.py new file mode 100644 index 000000000..92824c7f7 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/user_list.py @@ -0,0 +1,357 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import user_lists +from google.ads.googleads.v24.enums.types import ( + access_reason as gage_access_reason, +) +from google.ads.googleads.v24.enums.types import user_list_access_status +from google.ads.googleads.v24.enums.types import user_list_closing_reason +from google.ads.googleads.v24.enums.types import user_list_membership_status +from google.ads.googleads.v24.enums.types import user_list_size_range +from google.ads.googleads.v24.enums.types import user_list_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "UserList", + }, +) + + +class UserList(proto.Message): + r"""A user list. This is a list of users a customer may target. The + unique key of a user list consists of the following fields: ``id``. + Note that the ``name`` must also be unique for user lists owned by a + given customer, except in some cases where ``access_reason`` is set + to ``SHARED``. Violating the unique name constraint produces error: + ``UserListError.INVALID_NAME``. + + 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: + resource_name (str): + Immutable. The resource name of the user list. User list + resource names have the form: + + ``customers/{customer_id}/userLists/{user_list_id}`` + id (int): + Output only. Id of the user list. + + This field is a member of `oneof`_ ``_id``. + read_only (bool): + Output only. An option that indicates if a + user may edit a list. Depends on the list + ownership and list type. For example, external + remarketing user lists are not editable. + + This field is read-only. + + This field is a member of `oneof`_ ``_read_only``. + name (str): + Name of this user list. Unique per user list, except in some + cases where a user list of the same name has + ``access_reason`` set to ``SHARED``. + + This field is a member of `oneof`_ ``_name``. + description (str): + Description of this user list. + + This field is a member of `oneof`_ ``_description``. + membership_status (google.ads.googleads.v24.enums.types.UserListMembershipStatusEnum.UserListMembershipStatus): + Membership status of this user list. + Indicates whether a user list is open or active. + Only open user lists can accumulate more users + and can be targeted to. + integration_code (str): + An ID from external system. It is used by + user list sellers to correlate IDs on their + systems. + + This field is a member of `oneof`_ ``_integration_code``. + membership_life_span (int): + Number of days a user's cookie stays on your list since its + most recent addition to the list. This field must be between + 0 and 540 inclusive. + + This field is ignored for ``logical_user_list`` and + ``rule_based_user_list`` types. Membership to lists of these + types depends on the rules defined by the lists. + + This field is a member of `oneof`_ ``_membership_life_span``. + size_for_display (int): + Output only. Estimated number of users in + this user list, on the Google Display Network. + This value is null if the number of users has + not yet been determined. + + This field is read-only. + + This field is a member of `oneof`_ ``_size_for_display``. + size_range_for_display (google.ads.googleads.v24.enums.types.UserListSizeRangeEnum.UserListSizeRange): + Output only. Size range in terms of number of + users of the UserList, on the Google Display + Network. + + This field is read-only. + size_for_search (int): + Output only. Estimated number of users in + this user list in the google.com domain. These + are the users available for targeting in Search + campaigns. This value is null if the number of + users has not yet been determined. + + This field is read-only. + + This field is a member of `oneof`_ ``_size_for_search``. + size_range_for_search (google.ads.googleads.v24.enums.types.UserListSizeRangeEnum.UserListSizeRange): + Output only. Size range in terms of number of + users of the UserList, for Search ads. + + This field is read-only. + type_ (google.ads.googleads.v24.enums.types.UserListTypeEnum.UserListType): + Output only. Type of this list. + + This field is read-only. + closing_reason (google.ads.googleads.v24.enums.types.UserListClosingReasonEnum.UserListClosingReason): + Indicating the reason why this user list + membership status is closed. It is only + populated on lists that were automatically + closed due to inactivity, and will be cleared + once the list membership status becomes open. + access_reason (google.ads.googleads.v24.enums.types.AccessReasonEnum.AccessReason): + Output only. Indicates the reason this + account has been granted access to the list. The + reason can be SHARED, OWNED, LICENSED or + SUBSCRIBED. + + This field is read-only. + account_user_list_status (google.ads.googleads.v24.enums.types.UserListAccessStatusEnum.UserListAccessStatus): + Indicates if this share is still enabled. + When a UserList is shared with the user this + field is set to ENABLED. Later the userList + owner can decide to revoke the share and make it + DISABLED. + The default value of this field is set to + ENABLED. + eligible_for_search (bool): + Indicates if this user list is eligible for + Google Search Network. + + This field is a member of `oneof`_ ``_eligible_for_search``. + eligible_for_display (bool): + Output only. Indicates this user list is + eligible for Google Display Network. + + This field is read-only. + + This field is a member of `oneof`_ ``_eligible_for_display``. + match_rate_percentage (int): + Output only. Indicates match rate for Customer Match lists. + The range of this field is [0-100]. This will be null for + other list types or when it's not possible to calculate the + match rate. + + This field is read-only. + + This field is a member of `oneof`_ ``_match_rate_percentage``. + crm_based_user_list (google.ads.googleads.v24.common.types.CrmBasedUserListInfo): + User list of CRM users provided by the + advertiser. + + This field is a member of `oneof`_ ``user_list``. + similar_user_list (google.ads.googleads.v24.common.types.SimilarUserListInfo): + Output only. User list which are similar to + users from another UserList. These lists are + readonly and automatically created by google. + + This field is a member of `oneof`_ ``user_list``. + rule_based_user_list (google.ads.googleads.v24.common.types.RuleBasedUserListInfo): + User list generated by a rule. + + This field is a member of `oneof`_ ``user_list``. + logical_user_list (google.ads.googleads.v24.common.types.LogicalUserListInfo): + User list that is a custom combination of + user lists and user interests. + + This field is a member of `oneof`_ ``user_list``. + basic_user_list (google.ads.googleads.v24.common.types.BasicUserListInfo): + User list targeting as a collection of + conversion or remarketing actions. + + This field is a member of `oneof`_ ``user_list``. + lookalike_user_list (google.ads.googleads.v24.common.types.LookalikeUserListInfo): + Immutable. Lookalike User List. + + This field is a member of `oneof`_ ``user_list``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=25, + optional=True, + ) + read_only: bool = proto.Field( + proto.BOOL, + number=26, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=27, + optional=True, + ) + description: str = proto.Field( + proto.STRING, + number=28, + optional=True, + ) + membership_status: ( + user_list_membership_status.UserListMembershipStatusEnum.UserListMembershipStatus + ) = proto.Field( + proto.ENUM, + number=6, + enum=user_list_membership_status.UserListMembershipStatusEnum.UserListMembershipStatus, + ) + integration_code: str = proto.Field( + proto.STRING, + number=29, + optional=True, + ) + membership_life_span: int = proto.Field( + proto.INT64, + number=30, + optional=True, + ) + size_for_display: int = proto.Field( + proto.INT64, + number=31, + optional=True, + ) + size_range_for_display: ( + user_list_size_range.UserListSizeRangeEnum.UserListSizeRange + ) = proto.Field( + proto.ENUM, + number=10, + enum=user_list_size_range.UserListSizeRangeEnum.UserListSizeRange, + ) + size_for_search: int = proto.Field( + proto.INT64, + number=32, + optional=True, + ) + size_range_for_search: ( + user_list_size_range.UserListSizeRangeEnum.UserListSizeRange + ) = proto.Field( + proto.ENUM, + number=12, + enum=user_list_size_range.UserListSizeRangeEnum.UserListSizeRange, + ) + type_: user_list_type.UserListTypeEnum.UserListType = proto.Field( + proto.ENUM, + number=13, + enum=user_list_type.UserListTypeEnum.UserListType, + ) + closing_reason: ( + user_list_closing_reason.UserListClosingReasonEnum.UserListClosingReason + ) = proto.Field( + proto.ENUM, + number=14, + enum=user_list_closing_reason.UserListClosingReasonEnum.UserListClosingReason, + ) + access_reason: gage_access_reason.AccessReasonEnum.AccessReason = ( + proto.Field( + proto.ENUM, + number=15, + enum=gage_access_reason.AccessReasonEnum.AccessReason, + ) + ) + account_user_list_status: ( + user_list_access_status.UserListAccessStatusEnum.UserListAccessStatus + ) = proto.Field( + proto.ENUM, + number=16, + enum=user_list_access_status.UserListAccessStatusEnum.UserListAccessStatus, + ) + eligible_for_search: bool = proto.Field( + proto.BOOL, + number=33, + optional=True, + ) + eligible_for_display: bool = proto.Field( + proto.BOOL, + number=34, + optional=True, + ) + match_rate_percentage: int = proto.Field( + proto.INT32, + number=24, + optional=True, + ) + crm_based_user_list: user_lists.CrmBasedUserListInfo = proto.Field( + proto.MESSAGE, + number=19, + oneof="user_list", + message=user_lists.CrmBasedUserListInfo, + ) + similar_user_list: user_lists.SimilarUserListInfo = proto.Field( + proto.MESSAGE, + number=20, + oneof="user_list", + message=user_lists.SimilarUserListInfo, + ) + rule_based_user_list: user_lists.RuleBasedUserListInfo = proto.Field( + proto.MESSAGE, + number=21, + oneof="user_list", + message=user_lists.RuleBasedUserListInfo, + ) + logical_user_list: user_lists.LogicalUserListInfo = proto.Field( + proto.MESSAGE, + number=22, + oneof="user_list", + message=user_lists.LogicalUserListInfo, + ) + basic_user_list: user_lists.BasicUserListInfo = proto.Field( + proto.MESSAGE, + number=23, + oneof="user_list", + message=user_lists.BasicUserListInfo, + ) + lookalike_user_list: user_lists.LookalikeUserListInfo = proto.Field( + proto.MESSAGE, + number=36, + oneof="user_list", + message=user_lists.LookalikeUserListInfo, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/user_list_customer_type.py b/google/ads/googleads/v24/resources/types/user_list_customer_type.py new file mode 100644 index 000000000..71e476138 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/user_list_customer_type.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + user_list_customer_type_category, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "UserListCustomerType", + }, +) + + +class UserListCustomerType(proto.Message): + r"""A user list customer type + + Attributes: + resource_name (str): + Immutable. The resource name of the user list customer type + User list customer type resource names have the form: + ``customers/{customer_id}/userListCustomerTypes/{user_list_id}~{customer_type_category}`` + user_list (str): + Immutable. The resource name for the user + list this user list customer type is associated + with + customer_type_category (google.ads.googleads.v24.enums.types.UserListCustomerTypeCategoryEnum.UserListCustomerTypeCategory): + Immutable. The user list customer type + category + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + user_list: str = proto.Field( + proto.STRING, + number=2, + ) + customer_type_category: ( + user_list_customer_type_category.UserListCustomerTypeCategoryEnum.UserListCustomerTypeCategory + ) = proto.Field( + proto.ENUM, + number=3, + enum=user_list_customer_type_category.UserListCustomerTypeCategoryEnum.UserListCustomerTypeCategory, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/user_location_view.py b/google/ads/googleads/v24/resources/types/user_location_view.py new file mode 100644 index 000000000..b5d3c1a42 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/user_location_view.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "UserLocationView", + }, +) + + +class UserLocationView(proto.Message): + r"""A user location view. + + User Location View includes all metrics aggregated at the + country level, one row per country. It reports metrics at the + actual physical location of the user by targeted or not targeted + location. If other segment fields are used, you may get more + than one row per country. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the user location view. + UserLocation view resource names have the form: + + ``customers/{customer_id}/userLocationViews/{country_criterion_id}~{targeting_location}`` + country_criterion_id (int): + Output only. Criterion Id for the country. + + This field is a member of `oneof`_ ``_country_criterion_id``. + targeting_location (bool): + Output only. Indicates whether location was + targeted or not. + + This field is a member of `oneof`_ ``_targeting_location``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + country_criterion_id: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + targeting_location: bool = proto.Field( + proto.BOOL, + number=5, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/video.py b/google/ads/googleads/v24/resources/types/video.py new file mode 100644 index 000000000..95e289dd8 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/video.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "Video", + }, +) + + +class Video(proto.Message): + r"""A video. + + If the video has any enhancements, the stats on all of them will + be aggregated and displayed on this video resource. To get stats + for a specific enhancement, use the VideoEnhancement resource + instead. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Output only. The resource name of the video. Video resource + names have the form: + + ``customers/{customer_id}/videos/{video_id}`` + id (str): + Output only. The ID of the video. + + This field is a member of `oneof`_ ``_id``. + channel_id (str): + Output only. The owner channel id of the + video. + + This field is a member of `oneof`_ ``_channel_id``. + duration_millis (int): + Output only. The duration of the video in + milliseconds. + + This field is a member of `oneof`_ ``_duration_millis``. + title (str): + Output only. The title of the video. + + This field is a member of `oneof`_ ``_title``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + channel_id: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + duration_millis: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + title: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/video_enhancement.py b/google/ads/googleads/v24/resources/types/video_enhancement.py new file mode 100644 index 000000000..db223ea40 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/video_enhancement.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import video_enhancement_source + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "VideoEnhancement", + }, +) + + +class VideoEnhancement(proto.Message): + r"""Represents a video that can include both advertiser uploaded videos + or enhancements generated from the advertiser uploaded videos. Only + publicly available videos are returned. + + Each row in this resource represents either the video uploaded by + the advertiser or each specific variation of it. In contrast, the + ``Video`` resource represents only the advertiser-provided video and + would aggregate metrics across all its variations (including + enhancements). {-- next tag to use: 5 --} + + Attributes: + resource_name (str): + Output only. The resource name of the video enhancement. + Video enhancement resource names have the form: + + ``customers/{customer_id}/videoEnhancements/{video_id}`` + duration_millis (int): + Output only. Duration of this video, in + milliseconds. + source (google.ads.googleads.v24.enums.types.VideoEnhancementSourceEnum.VideoEnhancementSource): + Output only. The source of the video (e.g. + advertiser or enhanced by Google Ads). + title (str): + Output only. Title of this video. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + duration_millis: int = proto.Field( + proto.INT64, + number=2, + ) + source: ( + video_enhancement_source.VideoEnhancementSourceEnum.VideoEnhancementSource + ) = proto.Field( + proto.ENUM, + number=3, + enum=video_enhancement_source.VideoEnhancementSourceEnum.VideoEnhancementSource, + ) + title: str = proto.Field( + proto.STRING, + number=4, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/webpage_view.py b/google/ads/googleads/v24/resources/types/webpage_view.py new file mode 100644 index 000000000..de00725cc --- /dev/null +++ b/google/ads/googleads/v24/resources/types/webpage_view.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "WebpageView", + }, +) + + +class WebpageView(proto.Message): + r"""A webpage view. + + Attributes: + resource_name (str): + Output only. The resource name of the webpage view. Webpage + view resource names have the form: + + ``customers/{customer_id}/webpageViews/{ad_group_id}~{criterion_id}`` + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/resources/types/youtube_video_upload.py b/google/ads/googleads/v24/resources/types/youtube_video_upload.py new file mode 100644 index 000000000..39ce10ca9 --- /dev/null +++ b/google/ads/googleads/v24/resources/types/youtube_video_upload.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import youtube_video_privacy +from google.ads.googleads.v24.enums.types import youtube_video_upload_state + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.resources", + marshal="google.ads.googleads.v24", + manifest={ + "YouTubeVideoUpload", + }, +) + + +class YouTubeVideoUpload(proto.Message): + r"""Represents a video upload to YouTube using the Google Ads + API. + + Attributes: + resource_name (str): + Immutable. Resource name of the YouTube video + upload. + video_upload_id (int): + Output only. The unique ID of the YouTube + video upload. + channel_id (str): + Immutable. The destination YouTube channel ID + for the video upload. + Only mutable on YouTube video upload creation. + If omitted, the video will be uploaded to the + Google-managed YouTube channel associated with + the Ads account. + video_id (str): + Output only. The YouTube video ID of the + uploaded video. + state (google.ads.googleads.v24.enums.types.YouTubeVideoUploadStateEnum.YouTubeVideoUploadState): + Output only. The current state of the YouTube + video upload. + video_title (str): + Input only. Immutable. The title of the + video. + Only mutable on YouTube video upload creation. + Immutable after creation. + video_description (str): + Input only. Immutable. The description of the + video. + Only mutable on YouTube video upload creation. + Immutable after creation. + video_privacy (google.ads.googleads.v24.enums.types.YouTubeVideoPrivacyEnum.YouTubeVideoPrivacy): + The privacy state of the video. + + Only mutable for videos uploaded to the + advertiser owned (brand) YouTube channel. For + videos uploaded to the Google-managed channels + only UNLISTED privacy is allowed. Defaults to + UNLISTED privacy if not specified. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + video_upload_id: int = proto.Field( + proto.INT64, + number=2, + ) + channel_id: str = proto.Field( + proto.STRING, + number=3, + ) + video_id: str = proto.Field( + proto.STRING, + number=4, + ) + state: ( + youtube_video_upload_state.YouTubeVideoUploadStateEnum.YouTubeVideoUploadState + ) = proto.Field( + proto.ENUM, + number=5, + enum=youtube_video_upload_state.YouTubeVideoUploadStateEnum.YouTubeVideoUploadState, + ) + video_title: str = proto.Field( + proto.STRING, + number=6, + ) + video_description: str = proto.Field( + proto.STRING, + number=7, + ) + video_privacy: ( + youtube_video_privacy.YouTubeVideoPrivacyEnum.YouTubeVideoPrivacy + ) = proto.Field( + proto.ENUM, + number=8, + enum=youtube_video_privacy.YouTubeVideoPrivacyEnum.YouTubeVideoPrivacy, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/__init__.py b/google/ads/googleads/v24/services/__init__.py new file mode 100644 index 000000000..fa7b5fea7 --- /dev/null +++ b/google/ads/googleads/v24/services/__init__.py @@ -0,0 +1,1486 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .types.account_budget_proposal_service import ( + AccountBudgetProposalOperation, + MutateAccountBudgetProposalRequest, + MutateAccountBudgetProposalResponse, + MutateAccountBudgetProposalResult, +) +from .types.account_link_service import ( + AccountLinkOperation, + CreateAccountLinkRequest, + CreateAccountLinkResponse, + MutateAccountLinkRequest, + MutateAccountLinkResponse, + MutateAccountLinkResult, +) +from .types.ad_group_ad_label_service import ( + AdGroupAdLabelOperation, + MutateAdGroupAdLabelResult, + MutateAdGroupAdLabelsRequest, + MutateAdGroupAdLabelsResponse, +) +from .types.ad_group_ad_service import ( + AdGroupAdOperation, + AssetsWithFieldType, + MutateAdGroupAdResult, + MutateAdGroupAdsRequest, + MutateAdGroupAdsResponse, + RemoveAutomaticallyCreatedAssetsRequest, +) +from .types.ad_group_asset_service import ( + AdGroupAssetOperation, + MutateAdGroupAssetResult, + MutateAdGroupAssetsRequest, + MutateAdGroupAssetsResponse, +) +from .types.ad_group_asset_set_service import ( + AdGroupAssetSetOperation, + MutateAdGroupAssetSetResult, + MutateAdGroupAssetSetsRequest, + MutateAdGroupAssetSetsResponse, +) +from .types.ad_group_bid_modifier_service import ( + AdGroupBidModifierOperation, + MutateAdGroupBidModifierResult, + MutateAdGroupBidModifiersRequest, + MutateAdGroupBidModifiersResponse, +) +from .types.ad_group_criterion_customizer_service import ( + AdGroupCriterionCustomizerOperation, + MutateAdGroupCriterionCustomizerResult, + MutateAdGroupCriterionCustomizersRequest, + MutateAdGroupCriterionCustomizersResponse, +) +from .types.ad_group_criterion_label_service import ( + AdGroupCriterionLabelOperation, + MutateAdGroupCriterionLabelResult, + MutateAdGroupCriterionLabelsRequest, + MutateAdGroupCriterionLabelsResponse, +) +from .types.ad_group_criterion_service import ( + AdGroupCriterionOperation, + MutateAdGroupCriteriaRequest, + MutateAdGroupCriteriaResponse, + MutateAdGroupCriterionResult, +) +from .types.ad_group_customizer_service import ( + AdGroupCustomizerOperation, + MutateAdGroupCustomizerResult, + MutateAdGroupCustomizersRequest, + MutateAdGroupCustomizersResponse, +) +from .types.ad_group_label_service import ( + AdGroupLabelOperation, + MutateAdGroupLabelResult, + MutateAdGroupLabelsRequest, + MutateAdGroupLabelsResponse, +) +from .types.ad_group_service import ( + AdGroupOperation, + MutateAdGroupResult, + MutateAdGroupsRequest, + MutateAdGroupsResponse, +) +from .types.ad_parameter_service import ( + AdParameterOperation, + MutateAdParameterResult, + MutateAdParametersRequest, + MutateAdParametersResponse, +) +from .types.ad_service import ( + AdOperation, + MutateAdResult, + MutateAdsRequest, + MutateAdsResponse, +) +from .types.asset_generation_service import ( + AssetGenerationExistingContext, + FinalUrlImageGenerationInput, + FreeformImageGenerationInput, + GeneratedImage, + GeneratedText, + GenerateImagesRequest, + GenerateImagesResponse, + GenerateTextRequest, + GenerateTextResponse, + ProductRecontextGenerationImageInput, + SourceImage, +) +from .types.asset_group_asset_service import ( + AssetGroupAssetOperation, + MutateAssetGroupAssetResult, + MutateAssetGroupAssetsRequest, + MutateAssetGroupAssetsResponse, +) +from .types.asset_group_listing_group_filter_service import ( + AssetGroupListingGroupFilterOperation, + MutateAssetGroupListingGroupFilterResult, + MutateAssetGroupListingGroupFiltersRequest, + MutateAssetGroupListingGroupFiltersResponse, +) +from .types.asset_group_service import ( + AssetGroupOperation, + MutateAssetGroupResult, + MutateAssetGroupsRequest, + MutateAssetGroupsResponse, +) +from .types.asset_group_signal_service import ( + AssetGroupSignalOperation, + MutateAssetGroupSignalResult, + MutateAssetGroupSignalsRequest, + MutateAssetGroupSignalsResponse, +) +from .types.asset_service import ( + AssetOperation, + MutateAssetResult, + MutateAssetsRequest, + MutateAssetsResponse, +) +from .types.asset_set_asset_service import ( + AssetSetAssetOperation, + MutateAssetSetAssetResult, + MutateAssetSetAssetsRequest, + MutateAssetSetAssetsResponse, +) +from .types.asset_set_service import ( + AssetSetOperation, + MutateAssetSetResult, + MutateAssetSetsRequest, + MutateAssetSetsResponse, +) +from .types.audience_insights_service import ( + AudienceCompositionAttribute, + AudienceCompositionAttributeCluster, + AudienceCompositionMetrics, + AudienceCompositionSection, + AudienceInsightsDimensions, + AudienceOverlapItem, + DimensionOverlapResult, + GenerateAudienceCompositionInsightsRequest, + GenerateAudienceCompositionInsightsResponse, + GenerateAudienceDefinitionRequest, + GenerateAudienceDefinitionResponse, + GenerateAudienceOverlapInsightsRequest, + GenerateAudienceOverlapInsightsResponse, + GenerateInsightsFinderReportRequest, + GenerateInsightsFinderReportResponse, + GenerateSuggestedTargetingInsightsRequest, + GenerateSuggestedTargetingInsightsResponse, + GenerateTargetingSuggestionMetricsRequest, + GenerateTargetingSuggestionMetricsResponse, + InsightsAudience, + InsightsAudienceDefinition, + InsightsAudienceDescription, + ListAudienceInsightsAttributesRequest, + ListAudienceInsightsAttributesResponse, + ListInsightsEligibleDatesRequest, + ListInsightsEligibleDatesResponse, + TargetingSuggestionMetrics, +) +from .types.audience_service import ( + AudienceOperation, + MutateAudienceResult, + MutateAudiencesRequest, + MutateAudiencesResponse, +) +from .types.automatically_created_asset_removal_service import ( + RemoveCampaignAutomaticallyCreatedAssetOperation, + RemoveCampaignAutomaticallyCreatedAssetRequest, + RemoveCampaignAutomaticallyCreatedAssetResponse, +) +from .types.batch_job_service import ( + AddBatchJobOperationsRequest, + AddBatchJobOperationsResponse, + BatchJobOperation, + BatchJobResult, + ListBatchJobResultsRequest, + ListBatchJobResultsResponse, + MutateBatchJobRequest, + MutateBatchJobResponse, + MutateBatchJobResult, + RunBatchJobRequest, +) +from .types.benchmarks_service import ( + BenchmarksLocation, + BenchmarksProductMetadata, + BenchmarksSource, + BenchmarksSourceMetadata, + BreakdownDefinition, + BreakdownKey, + BreakdownMetrics, + GenerateBenchmarksMetricsRequest, + GenerateBenchmarksMetricsResponse, + IndustryVerticalInfo, + ListBenchmarksAvailableDatesRequest, + ListBenchmarksAvailableDatesResponse, + ListBenchmarksLocationsRequest, + ListBenchmarksLocationsResponse, + ListBenchmarksProductsRequest, + ListBenchmarksProductsResponse, + ListBenchmarksSourcesRequest, + ListBenchmarksSourcesResponse, + Metrics, + ProductFilter, + RateMetrics, +) +from .types.bidding_data_exclusion_service import ( + BiddingDataExclusionOperation, + MutateBiddingDataExclusionsRequest, + MutateBiddingDataExclusionsResponse, + MutateBiddingDataExclusionsResult, +) +from .types.bidding_seasonality_adjustment_service import ( + BiddingSeasonalityAdjustmentOperation, + MutateBiddingSeasonalityAdjustmentsRequest, + MutateBiddingSeasonalityAdjustmentsResponse, + MutateBiddingSeasonalityAdjustmentsResult, +) +from .types.bidding_strategy_service import ( + BiddingStrategyOperation, + MutateBiddingStrategiesRequest, + MutateBiddingStrategiesResponse, + MutateBiddingStrategyResult, +) +from .types.billing_setup_service import ( + BillingSetupOperation, + MutateBillingSetupRequest, + MutateBillingSetupResponse, + MutateBillingSetupResult, +) +from .types.brand_suggestion_service import ( + BrandSuggestion, + SuggestBrandsRequest, + SuggestBrandsResponse, +) +from .types.campaign_asset_service import ( + CampaignAssetOperation, + MutateCampaignAssetResult, + MutateCampaignAssetsRequest, + MutateCampaignAssetsResponse, +) +from .types.campaign_asset_set_service import ( + CampaignAssetSetOperation, + MutateCampaignAssetSetResult, + MutateCampaignAssetSetsRequest, + MutateCampaignAssetSetsResponse, +) +from .types.campaign_bid_modifier_service import ( + CampaignBidModifierOperation, + MutateCampaignBidModifierResult, + MutateCampaignBidModifiersRequest, + MutateCampaignBidModifiersResponse, +) +from .types.campaign_budget_service import ( + CampaignBudgetOperation, + MutateCampaignBudgetResult, + MutateCampaignBudgetsRequest, + MutateCampaignBudgetsResponse, +) +from .types.campaign_conversion_goal_service import ( + CampaignConversionGoalOperation, + MutateCampaignConversionGoalResult, + MutateCampaignConversionGoalsRequest, + MutateCampaignConversionGoalsResponse, +) +from .types.campaign_criterion_service import ( + CampaignCriterionOperation, + MutateCampaignCriteriaRequest, + MutateCampaignCriteriaResponse, + MutateCampaignCriterionResult, +) +from .types.campaign_customizer_service import ( + CampaignCustomizerOperation, + MutateCampaignCustomizerResult, + MutateCampaignCustomizersRequest, + MutateCampaignCustomizersResponse, +) +from .types.campaign_draft_service import ( + CampaignDraftOperation, + ListCampaignDraftAsyncErrorsRequest, + ListCampaignDraftAsyncErrorsResponse, + MutateCampaignDraftResult, + MutateCampaignDraftsRequest, + MutateCampaignDraftsResponse, + PromoteCampaignDraftRequest, +) +from .types.campaign_goal_config_service import ( + CampaignGoalConfigOperation, + MutateCampaignGoalConfigResult, + MutateCampaignGoalConfigsRequest, + MutateCampaignGoalConfigsResponse, +) +from .types.campaign_group_service import ( + CampaignGroupOperation, + MutateCampaignGroupResult, + MutateCampaignGroupsRequest, + MutateCampaignGroupsResponse, +) +from .types.campaign_label_service import ( + CampaignLabelOperation, + MutateCampaignLabelResult, + MutateCampaignLabelsRequest, + MutateCampaignLabelsResponse, +) +from .types.campaign_lifecycle_goal_service import ( + CampaignLifecycleGoalOperation, + ConfigureCampaignLifecycleGoalsRequest, + ConfigureCampaignLifecycleGoalsResponse, + ConfigureCampaignLifecycleGoalsResult, +) +from .types.campaign_service import ( + BrandCampaignAssets, + CampaignOperation, + EnablementResult, + EnableOperation, + EnablePMaxBrandGuidelinesRequest, + EnablePMaxBrandGuidelinesResponse, + MutateCampaignResult, + MutateCampaignsRequest, + MutateCampaignsResponse, +) +from .types.campaign_shared_set_service import ( + CampaignSharedSetOperation, + MutateCampaignSharedSetResult, + MutateCampaignSharedSetsRequest, + MutateCampaignSharedSetsResponse, +) +from .types.content_creator_insights_service import ( + GenerateCreatorInsightsRequest, + GenerateCreatorInsightsResponse, + GenerateTrendingInsightsRequest, + GenerateTrendingInsightsResponse, + LanguageDistribution, + SearchAudience, + SearchTopics, + TrendInsight, + TrendInsightDataPoint, + TrendInsightMetrics, + YouTubeChannelInsights, + YouTubeCreatorInsights, + YouTubeMetrics, +) +from .types.conversion_action_service import ( + ConversionActionOperation, + MutateConversionActionResult, + MutateConversionActionsRequest, + MutateConversionActionsResponse, +) +from .types.conversion_adjustment_upload_service import ( + ConversionAdjustment, + ConversionAdjustmentResult, + GclidDateTimePair, + RestatementValue, + UploadConversionAdjustmentsRequest, + UploadConversionAdjustmentsResponse, +) +from .types.conversion_custom_variable_service import ( + ConversionCustomVariableOperation, + MutateConversionCustomVariableResult, + MutateConversionCustomVariablesRequest, + MutateConversionCustomVariablesResponse, +) +from .types.conversion_goal_campaign_config_service import ( + ConversionGoalCampaignConfigOperation, + MutateConversionGoalCampaignConfigResult, + MutateConversionGoalCampaignConfigsRequest, + MutateConversionGoalCampaignConfigsResponse, +) +from .types.conversion_upload_service import ( + CallConversion, + CallConversionResult, + CartData, + ClickConversion, + ClickConversionResult, + CustomVariable, + ExternalAttributionData, + SessionAttributeKeyValuePair, + SessionAttributesKeyValuePairs, + UploadCallConversionsRequest, + UploadCallConversionsResponse, + UploadClickConversionsRequest, + UploadClickConversionsResponse, +) +from .types.conversion_value_rule_service import ( + ConversionValueRuleOperation, + MutateConversionValueRuleResult, + MutateConversionValueRulesRequest, + MutateConversionValueRulesResponse, +) +from .types.conversion_value_rule_set_service import ( + ConversionValueRuleSetOperation, + MutateConversionValueRuleSetResult, + MutateConversionValueRuleSetsRequest, + MutateConversionValueRuleSetsResponse, +) +from .types.custom_audience_service import ( + CustomAudienceOperation, + MutateCustomAudienceResult, + MutateCustomAudiencesRequest, + MutateCustomAudiencesResponse, +) +from .types.custom_conversion_goal_service import ( + CustomConversionGoalOperation, + MutateCustomConversionGoalResult, + MutateCustomConversionGoalsRequest, + MutateCustomConversionGoalsResponse, +) +from .types.custom_interest_service import ( + CustomInterestOperation, + MutateCustomInterestResult, + MutateCustomInterestsRequest, + MutateCustomInterestsResponse, +) +from .types.customer_asset_service import ( + CustomerAssetOperation, + MutateCustomerAssetResult, + MutateCustomerAssetsRequest, + MutateCustomerAssetsResponse, +) +from .types.customer_asset_set_service import ( + CustomerAssetSetOperation, + MutateCustomerAssetSetResult, + MutateCustomerAssetSetsRequest, + MutateCustomerAssetSetsResponse, +) +from .types.customer_client_link_service import ( + CustomerClientLinkOperation, + MutateCustomerClientLinkRequest, + MutateCustomerClientLinkResponse, + MutateCustomerClientLinkResult, +) +from .types.customer_conversion_goal_service import ( + CustomerConversionGoalOperation, + MutateCustomerConversionGoalResult, + MutateCustomerConversionGoalsRequest, + MutateCustomerConversionGoalsResponse, +) +from .types.customer_customizer_service import ( + CustomerCustomizerOperation, + MutateCustomerCustomizerResult, + MutateCustomerCustomizersRequest, + MutateCustomerCustomizersResponse, +) +from .types.customer_label_service import ( + CustomerLabelOperation, + MutateCustomerLabelResult, + MutateCustomerLabelsRequest, + MutateCustomerLabelsResponse, +) +from .types.customer_lifecycle_goal_service import ( + ConfigureCustomerLifecycleGoalsRequest, + ConfigureCustomerLifecycleGoalsResponse, + ConfigureCustomerLifecycleGoalsResult, + CustomerLifecycleGoalOperation, +) +from .types.customer_manager_link_service import ( + CustomerManagerLinkOperation, + MoveManagerLinkRequest, + MoveManagerLinkResponse, + MutateCustomerManagerLinkRequest, + MutateCustomerManagerLinkResponse, + MutateCustomerManagerLinkResult, +) +from .types.customer_negative_criterion_service import ( + CustomerNegativeCriterionOperation, + MutateCustomerNegativeCriteriaRequest, + MutateCustomerNegativeCriteriaResponse, + MutateCustomerNegativeCriteriaResult, +) +from .types.customer_service import ( + CreateCustomerClientRequest, + CreateCustomerClientResponse, + CustomerOperation, + ListAccessibleCustomersRequest, + ListAccessibleCustomersResponse, + MutateCustomerRequest, + MutateCustomerResponse, + MutateCustomerResult, +) +from .types.customer_sk_ad_network_conversion_value_schema_service import ( + CustomerSkAdNetworkConversionValueSchemaOperation, + MutateCustomerSkAdNetworkConversionValueSchemaRequest, + MutateCustomerSkAdNetworkConversionValueSchemaResponse, + MutateCustomerSkAdNetworkConversionValueSchemaResult, +) +from .types.customer_user_access_invitation_service import ( + CustomerUserAccessInvitationOperation, + MutateCustomerUserAccessInvitationRequest, + MutateCustomerUserAccessInvitationResponse, + MutateCustomerUserAccessInvitationResult, +) +from .types.customer_user_access_service import ( + CustomerUserAccessOperation, + MutateCustomerUserAccessRequest, + MutateCustomerUserAccessResponse, + MutateCustomerUserAccessResult, +) +from .types.customizer_attribute_service import ( + CustomizerAttributeOperation, + MutateCustomizerAttributeResult, + MutateCustomizerAttributesRequest, + MutateCustomizerAttributesResponse, +) +from .types.data_link_service import ( + CreateDataLinkRequest, + CreateDataLinkResponse, + RemoveDataLinkRequest, + RemoveDataLinkResponse, + UpdateDataLinkRequest, + UpdateDataLinkResponse, +) +from .types.experiment_arm_service import ( + ExperimentArmOperation, + MutateExperimentArmResult, + MutateExperimentArmsRequest, + MutateExperimentArmsResponse, +) +from .types.experiment_service import ( + CampaignBudgetMapping, + EndExperimentRequest, + ExperimentOperation, + GraduateExperimentRequest, + ListExperimentAsyncErrorsRequest, + ListExperimentAsyncErrorsResponse, + MutateExperimentResult, + MutateExperimentsRequest, + MutateExperimentsResponse, + PromoteExperimentMetadata, + PromoteExperimentRequest, + ScheduleExperimentMetadata, + ScheduleExperimentRequest, +) +from .types.geo_target_constant_service import ( + GeoTargetConstantSuggestion, + SuggestGeoTargetConstantsRequest, + SuggestGeoTargetConstantsResponse, +) +from .types.goal_service import ( + GoalOperation, + MutateGoalResult, + MutateGoalsRequest, + MutateGoalsResponse, +) +from .types.google_ads_field_service import ( + GetGoogleAdsFieldRequest, + SearchGoogleAdsFieldsRequest, + SearchGoogleAdsFieldsResponse, +) +from .types.google_ads_service import ( + GoogleAdsRow, + MetricAttributes, + MutateGoogleAdsRequest, + MutateGoogleAdsResponse, + MutateOperation, + MutateOperationResponse, + SearchGoogleAdsRequest, + SearchGoogleAdsResponse, + SearchGoogleAdsStreamRequest, + SearchGoogleAdsStreamResponse, + SearchSettings, +) +from .types.identity_verification_service import ( + GetIdentityVerificationRequest, + GetIdentityVerificationResponse, + IdentityVerification, + IdentityVerificationProgress, + IdentityVerificationRequirement, + StartIdentityVerificationRequest, +) +from .types.incentive_service import ( + ApplyIncentiveRequest, + ApplyIncentiveResponse, + CyoIncentives, + FetchIncentiveRequest, + FetchIncentiveResponse, + Incentive, + IncentiveOffer, +) +from .types.invoice_service import ( + ListInvoicesRequest, + ListInvoicesResponse, +) +from .types.keyword_plan_ad_group_keyword_service import ( + KeywordPlanAdGroupKeywordOperation, + MutateKeywordPlanAdGroupKeywordResult, + MutateKeywordPlanAdGroupKeywordsRequest, + MutateKeywordPlanAdGroupKeywordsResponse, +) +from .types.keyword_plan_ad_group_service import ( + KeywordPlanAdGroupOperation, + MutateKeywordPlanAdGroupResult, + MutateKeywordPlanAdGroupsRequest, + MutateKeywordPlanAdGroupsResponse, +) +from .types.keyword_plan_campaign_keyword_service import ( + KeywordPlanCampaignKeywordOperation, + MutateKeywordPlanCampaignKeywordResult, + MutateKeywordPlanCampaignKeywordsRequest, + MutateKeywordPlanCampaignKeywordsResponse, +) +from .types.keyword_plan_campaign_service import ( + KeywordPlanCampaignOperation, + MutateKeywordPlanCampaignResult, + MutateKeywordPlanCampaignsRequest, + MutateKeywordPlanCampaignsResponse, +) +from .types.keyword_plan_idea_service import ( + AdGroupKeywordSuggestion, + CampaignToForecast, + ForecastAdGroup, + GenerateAdGroupThemesRequest, + GenerateAdGroupThemesResponse, + GenerateKeywordForecastMetricsRequest, + GenerateKeywordForecastMetricsResponse, + GenerateKeywordHistoricalMetricsRequest, + GenerateKeywordHistoricalMetricsResponse, + GenerateKeywordHistoricalMetricsResult, + GenerateKeywordIdeaResponse, + GenerateKeywordIdeaResult, + GenerateKeywordIdeasRequest, + KeywordAndUrlSeed, + KeywordForecastMetrics, + KeywordSeed, + ManualCpcBiddingStrategy, + MaximizeClicksBiddingStrategy, + MaximizeConversionsBiddingStrategy, + SiteSeed, + UnusableAdGroup, + UrlSeed, +) +from .types.keyword_plan_service import ( + KeywordPlanOperation, + MutateKeywordPlansRequest, + MutateKeywordPlansResponse, + MutateKeywordPlansResult, +) +from .types.keyword_theme_constant_service import ( + SuggestKeywordThemeConstantsRequest, + SuggestKeywordThemeConstantsResponse, +) +from .types.label_service import ( + LabelOperation, + MutateLabelResult, + MutateLabelsRequest, + MutateLabelsResponse, +) +from .types.local_services_lead_service import ( + AppendLeadConversationRequest, + AppendLeadConversationResponse, + Conversation, + ConversationOrError, + ProvideLeadFeedbackRequest, + ProvideLeadFeedbackResponse, + SurveyDissatisfied, + SurveySatisfied, +) +from .types.offline_user_data_job_service import ( + AddOfflineUserDataJobOperationsRequest, + AddOfflineUserDataJobOperationsResponse, + CreateOfflineUserDataJobRequest, + CreateOfflineUserDataJobResponse, + OfflineUserDataJobOperation, + RunOfflineUserDataJobRequest, +) +from .types.payments_account_service import ( + ListPaymentsAccountsRequest, + ListPaymentsAccountsResponse, +) +from .types.product_link_invitation_service import ( + CreateProductLinkInvitationRequest, + CreateProductLinkInvitationResponse, + RemoveProductLinkInvitationRequest, + RemoveProductLinkInvitationResponse, + UpdateProductLinkInvitationRequest, + UpdateProductLinkInvitationResponse, +) +from .types.product_link_service import ( + CreateProductLinkRequest, + CreateProductLinkResponse, + RemoveProductLinkRequest, + RemoveProductLinkResponse, +) +from .types.reach_plan_service import ( + AdvancedProductTargeting, + AudienceTargeting, + CampaignDuration, + ConversionRateSuggestion, + EffectiveFrequencyBreakdown, + EffectiveFrequencyLimit, + Forecast, + ForecastMetricOptions, + FrequencyCap, + GenerateConversionRatesRequest, + GenerateConversionRatesResponse, + GenerateReachForecastRequest, + GenerateReachForecastResponse, + ListPlannableLocationsRequest, + ListPlannableLocationsResponse, + ListPlannableProductsRequest, + ListPlannableProductsResponse, + ListPlannableUserInterestsRequest, + ListPlannableUserInterestsResponse, + ListPlannableUserListsRequest, + ListPlannableUserListsResponse, + OnTargetAudienceMetrics, + PlannableLocation, + PlannableTargeting, + PlannableUserInterest, + PlannableUserList, + PlannableUserListMetadata, + PlannedProduct, + PlannedProductForecast, + PlannedProductReachForecast, + ProductCoreAttributes, + ProductMetadata, + ReachCurve, + ReachForecast, + SurfaceTargeting, + SurfaceTargetingCombinations, + TargetFrequencySettings, + Targeting, + YouTubeSelectLineUp, + YouTubeSelectLineUpTargeting, + YouTubeSelectSettings, +) +from .types.recommendation_service import ( + ApplyRecommendationOperation, + ApplyRecommendationRequest, + ApplyRecommendationResponse, + ApplyRecommendationResult, + DismissRecommendationRequest, + DismissRecommendationResponse, + GenerateRecommendationsRequest, + GenerateRecommendationsResponse, +) +from .types.recommendation_subscription_service import ( + MutateRecommendationSubscriptionRequest, + MutateRecommendationSubscriptionResponse, + MutateRecommendationSubscriptionResult, + RecommendationSubscriptionOperation, +) +from .types.remarketing_action_service import ( + MutateRemarketingActionResult, + MutateRemarketingActionsRequest, + MutateRemarketingActionsResponse, + RemarketingActionOperation, +) +from .types.reservation_service import ( + BookCampaignsRequest, + BookCampaignsResponse, + QuoteCampaignsRequest, + QuoteCampaignsResponse, +) +from .types.shareable_preview_service import ( + GenerateShareablePreviewsRequest, + GenerateShareablePreviewsResponse, +) +from .types.shared_criterion_service import ( + MutateSharedCriteriaRequest, + MutateSharedCriteriaResponse, + MutateSharedCriterionResult, + SharedCriterionOperation, +) +from .types.shared_set_service import ( + MutateSharedSetResult, + MutateSharedSetsRequest, + MutateSharedSetsResponse, + SharedSetOperation, +) +from .types.smart_campaign_setting_service import ( + GetSmartCampaignStatusRequest, + GetSmartCampaignStatusResponse, + MutateSmartCampaignSettingResult, + MutateSmartCampaignSettingsRequest, + MutateSmartCampaignSettingsResponse, + SmartCampaignEligibleDetails, + SmartCampaignEndedDetails, + SmartCampaignNotEligibleDetails, + SmartCampaignPausedDetails, + SmartCampaignRemovedDetails, + SmartCampaignSettingOperation, +) +from .types.smart_campaign_suggest_service import ( + SmartCampaignSuggestionInfo, + SuggestKeywordThemesRequest, + SuggestKeywordThemesResponse, + SuggestSmartCampaignAdRequest, + SuggestSmartCampaignAdResponse, + SuggestSmartCampaignBudgetOptionsRequest, + SuggestSmartCampaignBudgetOptionsResponse, +) +from .types.third_party_app_analytics_link_service import ( + RegenerateShareableLinkIdRequest, + RegenerateShareableLinkIdResponse, +) +from .types.travel_asset_suggestion_service import ( + HotelAssetSuggestion, + HotelImageAsset, + HotelTextAsset, + SuggestTravelAssetsRequest, + SuggestTravelAssetsResponse, +) +from .types.user_data_service import ( + UploadUserDataRequest, + UploadUserDataResponse, + UserDataOperation, +) +from .types.user_list_customer_type_service import ( + MutateUserListCustomerTypeResult, + MutateUserListCustomerTypesRequest, + MutateUserListCustomerTypesResponse, + UserListCustomerTypeOperation, +) +from .types.user_list_service import ( + MutateUserListResult, + MutateUserListsRequest, + MutateUserListsResponse, + UserListOperation, +) +from .types.youtube_video_upload_service import ( + CreateYouTubeVideoUploadRequest, + CreateYouTubeVideoUploadResponse, + RemoveYouTubeVideoUploadRequest, + RemoveYouTubeVideoUploadResponse, + UpdateYouTubeVideoUploadRequest, + UpdateYouTubeVideoUploadResponse, +) + +__all__ = ( + "AccountBudgetProposalOperation", + "MutateAccountBudgetProposalRequest", + "MutateAccountBudgetProposalResponse", + "MutateAccountBudgetProposalResult", + "AccountLinkOperation", + "CreateAccountLinkRequest", + "CreateAccountLinkResponse", + "MutateAccountLinkRequest", + "MutateAccountLinkResponse", + "MutateAccountLinkResult", + "AdGroupAdLabelOperation", + "MutateAdGroupAdLabelResult", + "MutateAdGroupAdLabelsRequest", + "MutateAdGroupAdLabelsResponse", + "AdGroupAdOperation", + "AssetsWithFieldType", + "MutateAdGroupAdResult", + "MutateAdGroupAdsRequest", + "MutateAdGroupAdsResponse", + "RemoveAutomaticallyCreatedAssetsRequest", + "AdGroupAssetOperation", + "MutateAdGroupAssetResult", + "MutateAdGroupAssetsRequest", + "MutateAdGroupAssetsResponse", + "AdGroupAssetSetOperation", + "MutateAdGroupAssetSetResult", + "MutateAdGroupAssetSetsRequest", + "MutateAdGroupAssetSetsResponse", + "AdGroupBidModifierOperation", + "MutateAdGroupBidModifierResult", + "MutateAdGroupBidModifiersRequest", + "MutateAdGroupBidModifiersResponse", + "AdGroupCriterionCustomizerOperation", + "MutateAdGroupCriterionCustomizerResult", + "MutateAdGroupCriterionCustomizersRequest", + "MutateAdGroupCriterionCustomizersResponse", + "AdGroupCriterionLabelOperation", + "MutateAdGroupCriterionLabelResult", + "MutateAdGroupCriterionLabelsRequest", + "MutateAdGroupCriterionLabelsResponse", + "AdGroupCriterionOperation", + "MutateAdGroupCriteriaRequest", + "MutateAdGroupCriteriaResponse", + "MutateAdGroupCriterionResult", + "AdGroupCustomizerOperation", + "MutateAdGroupCustomizerResult", + "MutateAdGroupCustomizersRequest", + "MutateAdGroupCustomizersResponse", + "AdGroupLabelOperation", + "MutateAdGroupLabelResult", + "MutateAdGroupLabelsRequest", + "MutateAdGroupLabelsResponse", + "AdGroupOperation", + "MutateAdGroupResult", + "MutateAdGroupsRequest", + "MutateAdGroupsResponse", + "AdParameterOperation", + "MutateAdParameterResult", + "MutateAdParametersRequest", + "MutateAdParametersResponse", + "AdOperation", + "MutateAdResult", + "MutateAdsRequest", + "MutateAdsResponse", + "AssetGenerationExistingContext", + "FinalUrlImageGenerationInput", + "FreeformImageGenerationInput", + "GeneratedImage", + "GeneratedText", + "GenerateImagesRequest", + "GenerateImagesResponse", + "GenerateTextRequest", + "GenerateTextResponse", + "ProductRecontextGenerationImageInput", + "SourceImage", + "AssetGroupAssetOperation", + "MutateAssetGroupAssetResult", + "MutateAssetGroupAssetsRequest", + "MutateAssetGroupAssetsResponse", + "AssetGroupListingGroupFilterOperation", + "MutateAssetGroupListingGroupFilterResult", + "MutateAssetGroupListingGroupFiltersRequest", + "MutateAssetGroupListingGroupFiltersResponse", + "AssetGroupOperation", + "MutateAssetGroupResult", + "MutateAssetGroupsRequest", + "MutateAssetGroupsResponse", + "AssetGroupSignalOperation", + "MutateAssetGroupSignalResult", + "MutateAssetGroupSignalsRequest", + "MutateAssetGroupSignalsResponse", + "AssetOperation", + "MutateAssetResult", + "MutateAssetsRequest", + "MutateAssetsResponse", + "AssetSetAssetOperation", + "MutateAssetSetAssetResult", + "MutateAssetSetAssetsRequest", + "MutateAssetSetAssetsResponse", + "AssetSetOperation", + "MutateAssetSetResult", + "MutateAssetSetsRequest", + "MutateAssetSetsResponse", + "AudienceCompositionAttribute", + "AudienceCompositionAttributeCluster", + "AudienceCompositionMetrics", + "AudienceCompositionSection", + "AudienceInsightsDimensions", + "AudienceOverlapItem", + "DimensionOverlapResult", + "GenerateAudienceCompositionInsightsRequest", + "GenerateAudienceCompositionInsightsResponse", + "GenerateAudienceDefinitionRequest", + "GenerateAudienceDefinitionResponse", + "GenerateAudienceOverlapInsightsRequest", + "GenerateAudienceOverlapInsightsResponse", + "GenerateInsightsFinderReportRequest", + "GenerateInsightsFinderReportResponse", + "GenerateSuggestedTargetingInsightsRequest", + "GenerateSuggestedTargetingInsightsResponse", + "GenerateTargetingSuggestionMetricsRequest", + "GenerateTargetingSuggestionMetricsResponse", + "InsightsAudience", + "InsightsAudienceDefinition", + "InsightsAudienceDescription", + "ListAudienceInsightsAttributesRequest", + "ListAudienceInsightsAttributesResponse", + "ListInsightsEligibleDatesRequest", + "ListInsightsEligibleDatesResponse", + "TargetingSuggestionMetrics", + "AudienceOperation", + "MutateAudienceResult", + "MutateAudiencesRequest", + "MutateAudiencesResponse", + "RemoveCampaignAutomaticallyCreatedAssetOperation", + "RemoveCampaignAutomaticallyCreatedAssetRequest", + "RemoveCampaignAutomaticallyCreatedAssetResponse", + "AddBatchJobOperationsRequest", + "AddBatchJobOperationsResponse", + "BatchJobOperation", + "BatchJobResult", + "ListBatchJobResultsRequest", + "ListBatchJobResultsResponse", + "MutateBatchJobRequest", + "MutateBatchJobResponse", + "MutateBatchJobResult", + "RunBatchJobRequest", + "BenchmarksLocation", + "BenchmarksProductMetadata", + "BenchmarksSource", + "BenchmarksSourceMetadata", + "BreakdownDefinition", + "BreakdownKey", + "BreakdownMetrics", + "GenerateBenchmarksMetricsRequest", + "GenerateBenchmarksMetricsResponse", + "IndustryVerticalInfo", + "ListBenchmarksAvailableDatesRequest", + "ListBenchmarksAvailableDatesResponse", + "ListBenchmarksLocationsRequest", + "ListBenchmarksLocationsResponse", + "ListBenchmarksProductsRequest", + "ListBenchmarksProductsResponse", + "ListBenchmarksSourcesRequest", + "ListBenchmarksSourcesResponse", + "Metrics", + "ProductFilter", + "RateMetrics", + "BiddingDataExclusionOperation", + "MutateBiddingDataExclusionsRequest", + "MutateBiddingDataExclusionsResponse", + "MutateBiddingDataExclusionsResult", + "BiddingSeasonalityAdjustmentOperation", + "MutateBiddingSeasonalityAdjustmentsRequest", + "MutateBiddingSeasonalityAdjustmentsResponse", + "MutateBiddingSeasonalityAdjustmentsResult", + "BiddingStrategyOperation", + "MutateBiddingStrategiesRequest", + "MutateBiddingStrategiesResponse", + "MutateBiddingStrategyResult", + "BillingSetupOperation", + "MutateBillingSetupRequest", + "MutateBillingSetupResponse", + "MutateBillingSetupResult", + "BrandSuggestion", + "SuggestBrandsRequest", + "SuggestBrandsResponse", + "CampaignAssetOperation", + "MutateCampaignAssetResult", + "MutateCampaignAssetsRequest", + "MutateCampaignAssetsResponse", + "CampaignAssetSetOperation", + "MutateCampaignAssetSetResult", + "MutateCampaignAssetSetsRequest", + "MutateCampaignAssetSetsResponse", + "CampaignBidModifierOperation", + "MutateCampaignBidModifierResult", + "MutateCampaignBidModifiersRequest", + "MutateCampaignBidModifiersResponse", + "CampaignBudgetOperation", + "MutateCampaignBudgetResult", + "MutateCampaignBudgetsRequest", + "MutateCampaignBudgetsResponse", + "CampaignConversionGoalOperation", + "MutateCampaignConversionGoalResult", + "MutateCampaignConversionGoalsRequest", + "MutateCampaignConversionGoalsResponse", + "CampaignCriterionOperation", + "MutateCampaignCriteriaRequest", + "MutateCampaignCriteriaResponse", + "MutateCampaignCriterionResult", + "CampaignCustomizerOperation", + "MutateCampaignCustomizerResult", + "MutateCampaignCustomizersRequest", + "MutateCampaignCustomizersResponse", + "CampaignDraftOperation", + "ListCampaignDraftAsyncErrorsRequest", + "ListCampaignDraftAsyncErrorsResponse", + "MutateCampaignDraftResult", + "MutateCampaignDraftsRequest", + "MutateCampaignDraftsResponse", + "PromoteCampaignDraftRequest", + "CampaignGoalConfigOperation", + "MutateCampaignGoalConfigResult", + "MutateCampaignGoalConfigsRequest", + "MutateCampaignGoalConfigsResponse", + "CampaignGroupOperation", + "MutateCampaignGroupResult", + "MutateCampaignGroupsRequest", + "MutateCampaignGroupsResponse", + "CampaignLabelOperation", + "MutateCampaignLabelResult", + "MutateCampaignLabelsRequest", + "MutateCampaignLabelsResponse", + "CampaignLifecycleGoalOperation", + "ConfigureCampaignLifecycleGoalsRequest", + "ConfigureCampaignLifecycleGoalsResponse", + "ConfigureCampaignLifecycleGoalsResult", + "BrandCampaignAssets", + "CampaignOperation", + "EnablementResult", + "EnableOperation", + "EnablePMaxBrandGuidelinesRequest", + "EnablePMaxBrandGuidelinesResponse", + "MutateCampaignResult", + "MutateCampaignsRequest", + "MutateCampaignsResponse", + "CampaignSharedSetOperation", + "MutateCampaignSharedSetResult", + "MutateCampaignSharedSetsRequest", + "MutateCampaignSharedSetsResponse", + "GenerateCreatorInsightsRequest", + "GenerateCreatorInsightsResponse", + "GenerateTrendingInsightsRequest", + "GenerateTrendingInsightsResponse", + "LanguageDistribution", + "SearchAudience", + "SearchTopics", + "TrendInsight", + "TrendInsightDataPoint", + "TrendInsightMetrics", + "YouTubeChannelInsights", + "YouTubeCreatorInsights", + "YouTubeMetrics", + "ConversionActionOperation", + "MutateConversionActionResult", + "MutateConversionActionsRequest", + "MutateConversionActionsResponse", + "ConversionAdjustment", + "ConversionAdjustmentResult", + "GclidDateTimePair", + "RestatementValue", + "UploadConversionAdjustmentsRequest", + "UploadConversionAdjustmentsResponse", + "ConversionCustomVariableOperation", + "MutateConversionCustomVariableResult", + "MutateConversionCustomVariablesRequest", + "MutateConversionCustomVariablesResponse", + "ConversionGoalCampaignConfigOperation", + "MutateConversionGoalCampaignConfigResult", + "MutateConversionGoalCampaignConfigsRequest", + "MutateConversionGoalCampaignConfigsResponse", + "CallConversion", + "CallConversionResult", + "CartData", + "ClickConversion", + "ClickConversionResult", + "CustomVariable", + "ExternalAttributionData", + "SessionAttributeKeyValuePair", + "SessionAttributesKeyValuePairs", + "UploadCallConversionsRequest", + "UploadCallConversionsResponse", + "UploadClickConversionsRequest", + "UploadClickConversionsResponse", + "ConversionValueRuleOperation", + "MutateConversionValueRuleResult", + "MutateConversionValueRulesRequest", + "MutateConversionValueRulesResponse", + "ConversionValueRuleSetOperation", + "MutateConversionValueRuleSetResult", + "MutateConversionValueRuleSetsRequest", + "MutateConversionValueRuleSetsResponse", + "CustomAudienceOperation", + "MutateCustomAudienceResult", + "MutateCustomAudiencesRequest", + "MutateCustomAudiencesResponse", + "CustomConversionGoalOperation", + "MutateCustomConversionGoalResult", + "MutateCustomConversionGoalsRequest", + "MutateCustomConversionGoalsResponse", + "CustomInterestOperation", + "MutateCustomInterestResult", + "MutateCustomInterestsRequest", + "MutateCustomInterestsResponse", + "CustomerAssetOperation", + "MutateCustomerAssetResult", + "MutateCustomerAssetsRequest", + "MutateCustomerAssetsResponse", + "CustomerAssetSetOperation", + "MutateCustomerAssetSetResult", + "MutateCustomerAssetSetsRequest", + "MutateCustomerAssetSetsResponse", + "CustomerClientLinkOperation", + "MutateCustomerClientLinkRequest", + "MutateCustomerClientLinkResponse", + "MutateCustomerClientLinkResult", + "CustomerConversionGoalOperation", + "MutateCustomerConversionGoalResult", + "MutateCustomerConversionGoalsRequest", + "MutateCustomerConversionGoalsResponse", + "CustomerCustomizerOperation", + "MutateCustomerCustomizerResult", + "MutateCustomerCustomizersRequest", + "MutateCustomerCustomizersResponse", + "CustomerLabelOperation", + "MutateCustomerLabelResult", + "MutateCustomerLabelsRequest", + "MutateCustomerLabelsResponse", + "ConfigureCustomerLifecycleGoalsRequest", + "ConfigureCustomerLifecycleGoalsResponse", + "ConfigureCustomerLifecycleGoalsResult", + "CustomerLifecycleGoalOperation", + "CustomerManagerLinkOperation", + "MoveManagerLinkRequest", + "MoveManagerLinkResponse", + "MutateCustomerManagerLinkRequest", + "MutateCustomerManagerLinkResponse", + "MutateCustomerManagerLinkResult", + "CustomerNegativeCriterionOperation", + "MutateCustomerNegativeCriteriaRequest", + "MutateCustomerNegativeCriteriaResponse", + "MutateCustomerNegativeCriteriaResult", + "CreateCustomerClientRequest", + "CreateCustomerClientResponse", + "CustomerOperation", + "ListAccessibleCustomersRequest", + "ListAccessibleCustomersResponse", + "MutateCustomerRequest", + "MutateCustomerResponse", + "MutateCustomerResult", + "CustomerSkAdNetworkConversionValueSchemaOperation", + "MutateCustomerSkAdNetworkConversionValueSchemaRequest", + "MutateCustomerSkAdNetworkConversionValueSchemaResponse", + "MutateCustomerSkAdNetworkConversionValueSchemaResult", + "CustomerUserAccessInvitationOperation", + "MutateCustomerUserAccessInvitationRequest", + "MutateCustomerUserAccessInvitationResponse", + "MutateCustomerUserAccessInvitationResult", + "CustomerUserAccessOperation", + "MutateCustomerUserAccessRequest", + "MutateCustomerUserAccessResponse", + "MutateCustomerUserAccessResult", + "CustomizerAttributeOperation", + "MutateCustomizerAttributeResult", + "MutateCustomizerAttributesRequest", + "MutateCustomizerAttributesResponse", + "CreateDataLinkRequest", + "CreateDataLinkResponse", + "RemoveDataLinkRequest", + "RemoveDataLinkResponse", + "UpdateDataLinkRequest", + "UpdateDataLinkResponse", + "ExperimentArmOperation", + "MutateExperimentArmResult", + "MutateExperimentArmsRequest", + "MutateExperimentArmsResponse", + "CampaignBudgetMapping", + "EndExperimentRequest", + "ExperimentOperation", + "GraduateExperimentRequest", + "ListExperimentAsyncErrorsRequest", + "ListExperimentAsyncErrorsResponse", + "MutateExperimentResult", + "MutateExperimentsRequest", + "MutateExperimentsResponse", + "PromoteExperimentMetadata", + "PromoteExperimentRequest", + "ScheduleExperimentMetadata", + "ScheduleExperimentRequest", + "GeoTargetConstantSuggestion", + "SuggestGeoTargetConstantsRequest", + "SuggestGeoTargetConstantsResponse", + "GoalOperation", + "MutateGoalResult", + "MutateGoalsRequest", + "MutateGoalsResponse", + "GetGoogleAdsFieldRequest", + "SearchGoogleAdsFieldsRequest", + "SearchGoogleAdsFieldsResponse", + "GoogleAdsRow", + "MetricAttributes", + "MutateGoogleAdsRequest", + "MutateGoogleAdsResponse", + "MutateOperation", + "MutateOperationResponse", + "SearchGoogleAdsRequest", + "SearchGoogleAdsResponse", + "SearchGoogleAdsStreamRequest", + "SearchGoogleAdsStreamResponse", + "SearchSettings", + "GetIdentityVerificationRequest", + "GetIdentityVerificationResponse", + "IdentityVerification", + "IdentityVerificationProgress", + "IdentityVerificationRequirement", + "StartIdentityVerificationRequest", + "ApplyIncentiveRequest", + "ApplyIncentiveResponse", + "CyoIncentives", + "FetchIncentiveRequest", + "FetchIncentiveResponse", + "Incentive", + "IncentiveOffer", + "ListInvoicesRequest", + "ListInvoicesResponse", + "KeywordPlanAdGroupKeywordOperation", + "MutateKeywordPlanAdGroupKeywordResult", + "MutateKeywordPlanAdGroupKeywordsRequest", + "MutateKeywordPlanAdGroupKeywordsResponse", + "KeywordPlanAdGroupOperation", + "MutateKeywordPlanAdGroupResult", + "MutateKeywordPlanAdGroupsRequest", + "MutateKeywordPlanAdGroupsResponse", + "KeywordPlanCampaignKeywordOperation", + "MutateKeywordPlanCampaignKeywordResult", + "MutateKeywordPlanCampaignKeywordsRequest", + "MutateKeywordPlanCampaignKeywordsResponse", + "KeywordPlanCampaignOperation", + "MutateKeywordPlanCampaignResult", + "MutateKeywordPlanCampaignsRequest", + "MutateKeywordPlanCampaignsResponse", + "AdGroupKeywordSuggestion", + "CampaignToForecast", + "ForecastAdGroup", + "GenerateAdGroupThemesRequest", + "GenerateAdGroupThemesResponse", + "GenerateKeywordForecastMetricsRequest", + "GenerateKeywordForecastMetricsResponse", + "GenerateKeywordHistoricalMetricsRequest", + "GenerateKeywordHistoricalMetricsResponse", + "GenerateKeywordHistoricalMetricsResult", + "GenerateKeywordIdeaResponse", + "GenerateKeywordIdeaResult", + "GenerateKeywordIdeasRequest", + "KeywordAndUrlSeed", + "KeywordForecastMetrics", + "KeywordSeed", + "ManualCpcBiddingStrategy", + "MaximizeClicksBiddingStrategy", + "MaximizeConversionsBiddingStrategy", + "SiteSeed", + "UnusableAdGroup", + "UrlSeed", + "KeywordPlanOperation", + "MutateKeywordPlansRequest", + "MutateKeywordPlansResponse", + "MutateKeywordPlansResult", + "SuggestKeywordThemeConstantsRequest", + "SuggestKeywordThemeConstantsResponse", + "LabelOperation", + "MutateLabelResult", + "MutateLabelsRequest", + "MutateLabelsResponse", + "AppendLeadConversationRequest", + "AppendLeadConversationResponse", + "Conversation", + "ConversationOrError", + "ProvideLeadFeedbackRequest", + "ProvideLeadFeedbackResponse", + "SurveyDissatisfied", + "SurveySatisfied", + "AddOfflineUserDataJobOperationsRequest", + "AddOfflineUserDataJobOperationsResponse", + "CreateOfflineUserDataJobRequest", + "CreateOfflineUserDataJobResponse", + "OfflineUserDataJobOperation", + "RunOfflineUserDataJobRequest", + "ListPaymentsAccountsRequest", + "ListPaymentsAccountsResponse", + "CreateProductLinkInvitationRequest", + "CreateProductLinkInvitationResponse", + "RemoveProductLinkInvitationRequest", + "RemoveProductLinkInvitationResponse", + "UpdateProductLinkInvitationRequest", + "UpdateProductLinkInvitationResponse", + "CreateProductLinkRequest", + "CreateProductLinkResponse", + "RemoveProductLinkRequest", + "RemoveProductLinkResponse", + "AdvancedProductTargeting", + "AudienceTargeting", + "CampaignDuration", + "ConversionRateSuggestion", + "EffectiveFrequencyBreakdown", + "EffectiveFrequencyLimit", + "Forecast", + "ForecastMetricOptions", + "FrequencyCap", + "GenerateConversionRatesRequest", + "GenerateConversionRatesResponse", + "GenerateReachForecastRequest", + "GenerateReachForecastResponse", + "ListPlannableLocationsRequest", + "ListPlannableLocationsResponse", + "ListPlannableProductsRequest", + "ListPlannableProductsResponse", + "ListPlannableUserInterestsRequest", + "ListPlannableUserInterestsResponse", + "ListPlannableUserListsRequest", + "ListPlannableUserListsResponse", + "OnTargetAudienceMetrics", + "PlannableLocation", + "PlannableTargeting", + "PlannableUserInterest", + "PlannableUserList", + "PlannableUserListMetadata", + "PlannedProduct", + "PlannedProductForecast", + "PlannedProductReachForecast", + "ProductCoreAttributes", + "ProductMetadata", + "ReachCurve", + "ReachForecast", + "SurfaceTargeting", + "SurfaceTargetingCombinations", + "TargetFrequencySettings", + "Targeting", + "YouTubeSelectLineUp", + "YouTubeSelectLineUpTargeting", + "YouTubeSelectSettings", + "ApplyRecommendationOperation", + "ApplyRecommendationRequest", + "ApplyRecommendationResponse", + "ApplyRecommendationResult", + "DismissRecommendationRequest", + "DismissRecommendationResponse", + "GenerateRecommendationsRequest", + "GenerateRecommendationsResponse", + "MutateRecommendationSubscriptionRequest", + "MutateRecommendationSubscriptionResponse", + "MutateRecommendationSubscriptionResult", + "RecommendationSubscriptionOperation", + "MutateRemarketingActionResult", + "MutateRemarketingActionsRequest", + "MutateRemarketingActionsResponse", + "RemarketingActionOperation", + "BookCampaignsRequest", + "BookCampaignsResponse", + "QuoteCampaignsRequest", + "QuoteCampaignsResponse", + "GenerateShareablePreviewsRequest", + "GenerateShareablePreviewsResponse", + "MutateSharedCriteriaRequest", + "MutateSharedCriteriaResponse", + "MutateSharedCriterionResult", + "SharedCriterionOperation", + "MutateSharedSetResult", + "MutateSharedSetsRequest", + "MutateSharedSetsResponse", + "SharedSetOperation", + "GetSmartCampaignStatusRequest", + "GetSmartCampaignStatusResponse", + "MutateSmartCampaignSettingResult", + "MutateSmartCampaignSettingsRequest", + "MutateSmartCampaignSettingsResponse", + "SmartCampaignEligibleDetails", + "SmartCampaignEndedDetails", + "SmartCampaignNotEligibleDetails", + "SmartCampaignPausedDetails", + "SmartCampaignRemovedDetails", + "SmartCampaignSettingOperation", + "SmartCampaignSuggestionInfo", + "SuggestKeywordThemesRequest", + "SuggestKeywordThemesResponse", + "SuggestSmartCampaignAdRequest", + "SuggestSmartCampaignAdResponse", + "SuggestSmartCampaignBudgetOptionsRequest", + "SuggestSmartCampaignBudgetOptionsResponse", + "RegenerateShareableLinkIdRequest", + "RegenerateShareableLinkIdResponse", + "HotelAssetSuggestion", + "HotelImageAsset", + "HotelTextAsset", + "SuggestTravelAssetsRequest", + "SuggestTravelAssetsResponse", + "UploadUserDataRequest", + "UploadUserDataResponse", + "UserDataOperation", + "MutateUserListCustomerTypeResult", + "MutateUserListCustomerTypesRequest", + "MutateUserListCustomerTypesResponse", + "UserListCustomerTypeOperation", + "MutateUserListResult", + "MutateUserListsRequest", + "MutateUserListsResponse", + "UserListOperation", + "CreateYouTubeVideoUploadRequest", + "CreateYouTubeVideoUploadResponse", + "RemoveYouTubeVideoUploadRequest", + "RemoveYouTubeVideoUploadResponse", + "UpdateYouTubeVideoUploadRequest", + "UpdateYouTubeVideoUploadResponse", +) diff --git a/google/ads/googleads/v24/services/services/__init__.py b/google/ads/googleads/v24/services/services/__init__.py new file mode 100644 index 000000000..cbf94b283 --- /dev/null +++ b/google/ads/googleads/v24/services/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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. +# diff --git a/google/ads/googleads/v24/services/services/account_budget_proposal_service/__init__.py b/google/ads/googleads/v24/services/services/account_budget_proposal_service/__init__.py new file mode 100644 index 000000000..758b5ae3e --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_budget_proposal_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AccountBudgetProposalServiceClient +from .async_client import AccountBudgetProposalServiceAsyncClient + +__all__ = ( + "AccountBudgetProposalServiceClient", + "AccountBudgetProposalServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/account_budget_proposal_service/async_client.py b/google/ads/googleads/v24/services/services/account_budget_proposal_service/async_client.py new file mode 100644 index 000000000..7a4fab053 --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_budget_proposal_service/async_client.py @@ -0,0 +1,458 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + account_budget_proposal_service, +) +from .transports.base import ( + AccountBudgetProposalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import AccountBudgetProposalServiceClient + +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 AccountBudgetProposalServiceAsyncClient: + """A service for managing account-level budgets through + proposals. + A proposal is a request to create a new budget or make changes + to an existing one. + + Mutates: + + The CREATE operation creates a new proposal. + UPDATE operations aren't supported. + The REMOVE operation cancels a pending proposal. + """ + + _client: AccountBudgetProposalServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AccountBudgetProposalServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + AccountBudgetProposalServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + AccountBudgetProposalServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AccountBudgetProposalServiceClient._DEFAULT_UNIVERSE + + account_budget_path = staticmethod( + AccountBudgetProposalServiceClient.account_budget_path + ) + parse_account_budget_path = staticmethod( + AccountBudgetProposalServiceClient.parse_account_budget_path + ) + account_budget_proposal_path = staticmethod( + AccountBudgetProposalServiceClient.account_budget_proposal_path + ) + parse_account_budget_proposal_path = staticmethod( + AccountBudgetProposalServiceClient.parse_account_budget_proposal_path + ) + billing_setup_path = staticmethod( + AccountBudgetProposalServiceClient.billing_setup_path + ) + parse_billing_setup_path = staticmethod( + AccountBudgetProposalServiceClient.parse_billing_setup_path + ) + common_billing_account_path = staticmethod( + AccountBudgetProposalServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AccountBudgetProposalServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AccountBudgetProposalServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AccountBudgetProposalServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AccountBudgetProposalServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AccountBudgetProposalServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AccountBudgetProposalServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AccountBudgetProposalServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AccountBudgetProposalServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AccountBudgetProposalServiceClient.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: + AccountBudgetProposalServiceAsyncClient: The constructed client. + """ + return AccountBudgetProposalServiceClient.from_service_account_info.__func__(AccountBudgetProposalServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AccountBudgetProposalServiceAsyncClient: The constructed client. + """ + return AccountBudgetProposalServiceClient.from_service_account_file.__func__(AccountBudgetProposalServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AccountBudgetProposalServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AccountBudgetProposalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AccountBudgetProposalServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AccountBudgetProposalServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AccountBudgetProposalServiceTransport, + Callable[..., AccountBudgetProposalServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the account budget proposal 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,AccountBudgetProposalServiceTransport,Callable[..., AccountBudgetProposalServiceTransport]]]): + 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 AccountBudgetProposalServiceTransport 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 = AccountBudgetProposalServiceClient( + 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.ads.googleads.v24.services.AccountBudgetProposalServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AccountBudgetProposalService", + "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.ads.googleads.v24.services.AccountBudgetProposalService", + "credentialsType": None, + } + ), + ) + + async def mutate_account_budget_proposal( + self, + request: Optional[ + Union[ + account_budget_proposal_service.MutateAccountBudgetProposalRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[ + account_budget_proposal_service.AccountBudgetProposalOperation + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> account_budget_proposal_service.MutateAccountBudgetProposalResponse: + r"""Creates, updates, or removes account budget proposals. Operation + statuses are returned. + + List of thrown errors: `AccountBudgetProposalError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `DatabaseError <>`__ `DateError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + `StringLengthError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAccountBudgetProposalRequest, dict]]): + The request object. Request message for + [AccountBudgetProposalService.MutateAccountBudgetProposal][google.ads.googleads.v24.services.AccountBudgetProposalService.MutateAccountBudgetProposal]. + customer_id (:class:`str`): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (:class:`google.ads.googleads.v24.services.types.AccountBudgetProposalOperation`): + Required. The operation to perform on + an individual account-level budget + proposal. + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateAccountBudgetProposalResponse: + Response message for account-level + budget mutate operations. + + """ + # 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 = [customer_id, operation] + 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, + account_budget_proposal_service.MutateAccountBudgetProposalRequest, + ): + request = account_budget_proposal_service.MutateAccountBudgetProposalRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_account_budget_proposal + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AccountBudgetProposalServiceAsyncClient": + 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__ = ("AccountBudgetProposalServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/account_budget_proposal_service/client.py b/google/ads/googleads/v24/services/services/account_budget_proposal_service/client.py new file mode 100644 index 000000000..a4abbb0c0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_budget_proposal_service/client.py @@ -0,0 +1,965 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + account_budget_proposal_service, +) +from .transports.base import ( + AccountBudgetProposalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AccountBudgetProposalServiceGrpcTransport +from .transports.grpc_asyncio import ( + AccountBudgetProposalServiceGrpcAsyncIOTransport, +) + + +class AccountBudgetProposalServiceClientMeta(type): + """Metaclass for the AccountBudgetProposalService 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[AccountBudgetProposalServiceTransport]] + _transport_registry["grpc"] = AccountBudgetProposalServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AccountBudgetProposalServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AccountBudgetProposalServiceTransport]: + """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 AccountBudgetProposalServiceClient( + metaclass=AccountBudgetProposalServiceClientMeta +): + """A service for managing account-level budgets through + proposals. + A proposal is a request to create a new budget or make changes + to an existing one. + + Mutates: + + The CREATE operation creates a new proposal. + UPDATE operations aren't supported. + The REMOVE operation cancels a pending proposal. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AccountBudgetProposalServiceClient: 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: + AccountBudgetProposalServiceClient: 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) -> AccountBudgetProposalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AccountBudgetProposalServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def account_budget_path( + customer_id: str, + account_budget_id: str, + ) -> str: + """Returns a fully-qualified account_budget string.""" + return ( + "customers/{customer_id}/accountBudgets/{account_budget_id}".format( + customer_id=customer_id, + account_budget_id=account_budget_id, + ) + ) + + @staticmethod + def parse_account_budget_path(path: str) -> Dict[str, str]: + """Parses a account_budget path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/accountBudgets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def account_budget_proposal_path( + customer_id: str, + account_budget_proposal_id: str, + ) -> str: + """Returns a fully-qualified account_budget_proposal string.""" + return "customers/{customer_id}/accountBudgetProposals/{account_budget_proposal_id}".format( + customer_id=customer_id, + account_budget_proposal_id=account_budget_proposal_id, + ) + + @staticmethod + def parse_account_budget_proposal_path(path: str) -> Dict[str, str]: + """Parses a account_budget_proposal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/accountBudgetProposals/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def billing_setup_path( + customer_id: str, + billing_setup_id: str, + ) -> str: + """Returns a fully-qualified billing_setup string.""" + return ( + "customers/{customer_id}/billingSetups/{billing_setup_id}".format( + customer_id=customer_id, + billing_setup_id=billing_setup_id, + ) + ) + + @staticmethod + def parse_billing_setup_path(path: str) -> Dict[str, str]: + """Parses a billing_setup path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/billingSetups/(?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 = ( + AccountBudgetProposalServiceClient._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 = ( + AccountBudgetProposalServiceClient._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 + ): + """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 = ( + AccountBudgetProposalServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + AccountBudgetProposalServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = AccountBudgetProposalServiceClient._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 = AccountBudgetProposalServiceClient._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): + """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, + AccountBudgetProposalServiceTransport, + Callable[..., AccountBudgetProposalServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the account budget proposal 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,AccountBudgetProposalServiceTransport,Callable[..., AccountBudgetProposalServiceTransport]]]): + 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 AccountBudgetProposalServiceTransport 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, + ) = AccountBudgetProposalServiceClient._read_environment_variables() + self._client_cert_source = ( + AccountBudgetProposalServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + AccountBudgetProposalServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AccountBudgetProposalServiceTransport + ) + if transport_provided: + # transport is a AccountBudgetProposalServiceTransport 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( + AccountBudgetProposalServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AccountBudgetProposalServiceClient._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[AccountBudgetProposalServiceTransport], + Callable[..., AccountBudgetProposalServiceTransport], + ] = ( + AccountBudgetProposalServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AccountBudgetProposalServiceTransport], + 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.ads.googleads.v24.services.AccountBudgetProposalServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AccountBudgetProposalService", + "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.ads.googleads.v24.services.AccountBudgetProposalService", + "credentialsType": None, + } + ), + ) + + def mutate_account_budget_proposal( + self, + request: Optional[ + Union[ + account_budget_proposal_service.MutateAccountBudgetProposalRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[ + account_budget_proposal_service.AccountBudgetProposalOperation + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> account_budget_proposal_service.MutateAccountBudgetProposalResponse: + r"""Creates, updates, or removes account budget proposals. Operation + statuses are returned. + + List of thrown errors: `AccountBudgetProposalError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `DatabaseError <>`__ `DateError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAccountBudgetProposalRequest, dict]): + The request object. Request message for + [AccountBudgetProposalService.MutateAccountBudgetProposal][google.ads.googleads.v24.services.AccountBudgetProposalService.MutateAccountBudgetProposal]. + customer_id (str): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (google.ads.googleads.v24.services.types.AccountBudgetProposalOperation): + Required. The operation to perform on + an individual account-level budget + proposal. + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateAccountBudgetProposalResponse: + Response message for account-level + budget mutate operations. + + """ + # 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 = [customer_id, operation] + 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, + account_budget_proposal_service.MutateAccountBudgetProposalRequest, + ): + request = account_budget_proposal_service.MutateAccountBudgetProposalRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_account_budget_proposal + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AccountBudgetProposalServiceClient": + 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() + + +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__ = ("AccountBudgetProposalServiceClient",) diff --git a/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/README.rst b/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/README.rst new file mode 100644 index 000000000..926f4a38e --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AccountBudgetProposalServiceTransport` is the ABC for all transports. +- public child `AccountBudgetProposalServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AccountBudgetProposalServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAccountBudgetProposalServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AccountBudgetProposalServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/__init__.py b/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/__init__.py new file mode 100644 index 000000000..18652bd7a --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AccountBudgetProposalServiceTransport +from .grpc import AccountBudgetProposalServiceGrpcTransport +from .grpc_asyncio import AccountBudgetProposalServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AccountBudgetProposalServiceTransport]] +_transport_registry["grpc"] = AccountBudgetProposalServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + AccountBudgetProposalServiceGrpcAsyncIOTransport +) + +__all__ = ( + "AccountBudgetProposalServiceTransport", + "AccountBudgetProposalServiceGrpcTransport", + "AccountBudgetProposalServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/base.py b/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/base.py new file mode 100644 index 000000000..8f6da85df --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + account_budget_proposal_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 AccountBudgetProposalServiceTransport(abc.ABC): + """Abstract transport class for AccountBudgetProposalService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_account_budget_proposal: gapic_v1.method.wrap_method( + self.mutate_account_budget_proposal, + 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 mutate_account_budget_proposal( + self, + ) -> Callable[ + [account_budget_proposal_service.MutateAccountBudgetProposalRequest], + Union[ + account_budget_proposal_service.MutateAccountBudgetProposalResponse, + Awaitable[ + account_budget_proposal_service.MutateAccountBudgetProposalResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AccountBudgetProposalServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/grpc.py b/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/grpc.py new file mode 100644 index 000000000..953771036 --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/grpc.py @@ -0,0 +1,404 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + account_budget_proposal_service, +) +from .base import AccountBudgetProposalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AccountBudgetProposalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AccountBudgetProposalService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AccountBudgetProposalServiceGrpcTransport( + AccountBudgetProposalServiceTransport +): + """gRPC backend transport for AccountBudgetProposalService. + + A service for managing account-level budgets through + proposals. + A proposal is a request to create a new budget or make changes + to an existing one. + + Mutates: + + The CREATE operation creates a new proposal. + UPDATE operations aren't supported. + The REMOVE operation cancels a pending proposal. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_account_budget_proposal( + self, + ) -> Callable[ + [account_budget_proposal_service.MutateAccountBudgetProposalRequest], + account_budget_proposal_service.MutateAccountBudgetProposalResponse, + ]: + r"""Return a callable for the mutate account budget proposal method over gRPC. + + Creates, updates, or removes account budget proposals. Operation + statuses are returned. + + List of thrown errors: `AccountBudgetProposalError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `DatabaseError <>`__ `DateError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + `StringLengthError <>`__ + + Returns: + Callable[[~.MutateAccountBudgetProposalRequest], + ~.MutateAccountBudgetProposalResponse]: + 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 "mutate_account_budget_proposal" not in self._stubs: + self._stubs["mutate_account_budget_proposal"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AccountBudgetProposalService/MutateAccountBudgetProposal", + request_serializer=account_budget_proposal_service.MutateAccountBudgetProposalRequest.serialize, + response_deserializer=account_budget_proposal_service.MutateAccountBudgetProposalResponse.deserialize, + ) + ) + return self._stubs["mutate_account_budget_proposal"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AccountBudgetProposalServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..e164bc03a --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_budget_proposal_service/transports/grpc_asyncio.py @@ -0,0 +1,427 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + account_budget_proposal_service, +) +from .base import AccountBudgetProposalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AccountBudgetProposalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AccountBudgetProposalService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AccountBudgetProposalServiceGrpcAsyncIOTransport( + AccountBudgetProposalServiceTransport +): + """gRPC AsyncIO backend transport for AccountBudgetProposalService. + + A service for managing account-level budgets through + proposals. + A proposal is a request to create a new budget or make changes + to an existing one. + + Mutates: + + The CREATE operation creates a new proposal. + UPDATE operations aren't supported. + The REMOVE operation cancels a pending proposal. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_account_budget_proposal( + self, + ) -> Callable[ + [account_budget_proposal_service.MutateAccountBudgetProposalRequest], + Awaitable[ + account_budget_proposal_service.MutateAccountBudgetProposalResponse + ], + ]: + r"""Return a callable for the mutate account budget proposal method over gRPC. + + Creates, updates, or removes account budget proposals. Operation + statuses are returned. + + List of thrown errors: `AccountBudgetProposalError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `DatabaseError <>`__ `DateError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + `StringLengthError <>`__ + + Returns: + Callable[[~.MutateAccountBudgetProposalRequest], + Awaitable[~.MutateAccountBudgetProposalResponse]]: + 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 "mutate_account_budget_proposal" not in self._stubs: + self._stubs["mutate_account_budget_proposal"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AccountBudgetProposalService/MutateAccountBudgetProposal", + request_serializer=account_budget_proposal_service.MutateAccountBudgetProposalRequest.serialize, + response_deserializer=account_budget_proposal_service.MutateAccountBudgetProposalResponse.deserialize, + ) + ) + return self._stubs["mutate_account_budget_proposal"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_account_budget_proposal: self._wrap_method( + self.mutate_account_budget_proposal, + 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" + + +__all__ = ("AccountBudgetProposalServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/account_link_service/__init__.py b/google/ads/googleads/v24/services/services/account_link_service/__init__.py new file mode 100644 index 000000000..cfb948fb6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_link_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AccountLinkServiceClient +from .async_client import AccountLinkServiceAsyncClient + +__all__ = ( + "AccountLinkServiceClient", + "AccountLinkServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/account_link_service/async_client.py b/google/ads/googleads/v24/services/services/account_link_service/async_client.py new file mode 100644 index 000000000..f8239d42f --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_link_service/async_client.py @@ -0,0 +1,532 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.resources.types import ( + account_link as gagr_account_link, +) +from google.ads.googleads.v24.services.types import account_link_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AccountLinkServiceTransport, DEFAULT_CLIENT_INFO +from .client import AccountLinkServiceClient + +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 AccountLinkServiceAsyncClient: + """This service allows management of links between Google Ads + accounts and other accounts. + """ + + _client: AccountLinkServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AccountLinkServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AccountLinkServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AccountLinkServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AccountLinkServiceClient._DEFAULT_UNIVERSE + + account_link_path = staticmethod(AccountLinkServiceClient.account_link_path) + parse_account_link_path = staticmethod( + AccountLinkServiceClient.parse_account_link_path + ) + common_billing_account_path = staticmethod( + AccountLinkServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AccountLinkServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AccountLinkServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AccountLinkServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AccountLinkServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AccountLinkServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AccountLinkServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AccountLinkServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AccountLinkServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AccountLinkServiceClient.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: + AccountLinkServiceAsyncClient: The constructed client. + """ + return AccountLinkServiceClient.from_service_account_info.__func__(AccountLinkServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AccountLinkServiceAsyncClient: The constructed client. + """ + return AccountLinkServiceClient.from_service_account_file.__func__(AccountLinkServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AccountLinkServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AccountLinkServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AccountLinkServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AccountLinkServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AccountLinkServiceTransport, + Callable[..., AccountLinkServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the account link 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,AccountLinkServiceTransport,Callable[..., AccountLinkServiceTransport]]]): + 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 AccountLinkServiceTransport 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 = AccountLinkServiceClient( + 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.ads.googleads.v24.services.AccountLinkServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AccountLinkService", + "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.ads.googleads.v24.services.AccountLinkService", + "credentialsType": None, + } + ), + ) + + async def create_account_link( + self, + request: Optional[ + Union[account_link_service.CreateAccountLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + account_link: Optional[gagr_account_link.AccountLink] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> account_link_service.CreateAccountLinkResponse: + r"""Creates an account link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + `ThirdPartyAppAnalyticsLinkError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.CreateAccountLinkRequest, dict]]): + The request object. Request message for + [AccountLinkService.CreateAccountLink][google.ads.googleads.v24.services.AccountLinkService.CreateAccountLink]. + customer_id (:class:`str`): + Required. The ID of the customer for + which the account link is created. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + account_link (:class:`google.ads.googleads.v24.resources.types.AccountLink`): + Required. The account link to be + created. + + This corresponds to the ``account_link`` 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.ads.googleads.v24.services.types.CreateAccountLinkResponse: + Response message for + [AccountLinkService.CreateAccountLink][google.ads.googleads.v24.services.AccountLinkService.CreateAccountLink]. + + """ + # 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 = [customer_id, account_link] + 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, account_link_service.CreateAccountLinkRequest + ): + request = account_link_service.CreateAccountLinkRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if account_link is not None: + request.account_link = account_link + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.create_account_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 mutate_account_link( + self, + request: Optional[ + Union[account_link_service.MutateAccountLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[account_link_service.AccountLinkOperation] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> account_link_service.MutateAccountLinkResponse: + r"""Creates or removes an account link. From V5, create is not + supported through AccountLinkService.MutateAccountLink. Use + AccountLinkService.CreateAccountLink instead. + + List of thrown errors: `AccountLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAccountLinkRequest, dict]]): + The request object. Request message for + [AccountLinkService.MutateAccountLink][google.ads.googleads.v24.services.AccountLinkService.MutateAccountLink]. + customer_id (:class:`str`): + Required. The ID of the customer + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (:class:`google.ads.googleads.v24.services.types.AccountLinkOperation`): + Required. The operation to perform on + the link. + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateAccountLinkResponse: + Response message for account link + mutate. + + """ + # 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 = [customer_id, operation] + 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, account_link_service.MutateAccountLinkRequest + ): + request = account_link_service.MutateAccountLinkRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_account_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AccountLinkServiceAsyncClient": + 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__ = ("AccountLinkServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/account_link_service/client.py b/google/ads/googleads/v24/services/services/account_link_service/client.py new file mode 100644 index 000000000..9c5c2222e --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_link_service/client.py @@ -0,0 +1,987 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.resources.types import ( + account_link as gagr_account_link, +) +from google.ads.googleads.v24.services.types import account_link_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AccountLinkServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import AccountLinkServiceGrpcTransport +from .transports.grpc_asyncio import AccountLinkServiceGrpcAsyncIOTransport + + +class AccountLinkServiceClientMeta(type): + """Metaclass for the AccountLinkService 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[AccountLinkServiceTransport]] + _transport_registry["grpc"] = AccountLinkServiceGrpcTransport + _transport_registry["grpc_asyncio"] = AccountLinkServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AccountLinkServiceTransport]: + """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 AccountLinkServiceClient(metaclass=AccountLinkServiceClientMeta): + """This service allows management of links between Google Ads + accounts and other accounts. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AccountLinkServiceClient: 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: + AccountLinkServiceClient: 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) -> AccountLinkServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AccountLinkServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def account_link_path( + customer_id: str, + account_link_id: str, + ) -> str: + """Returns a fully-qualified account_link string.""" + return "customers/{customer_id}/accountLinks/{account_link_id}".format( + customer_id=customer_id, + account_link_id=account_link_id, + ) + + @staticmethod + def parse_account_link_path(path: str) -> Dict[str, str]: + """Parses a account_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/accountLinks/(?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 = AccountLinkServiceClient._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 = AccountLinkServiceClient._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 + ): + """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 = AccountLinkServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AccountLinkServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AccountLinkServiceClient._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 = AccountLinkServiceClient._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): + """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, + AccountLinkServiceTransport, + Callable[..., AccountLinkServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the account link 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,AccountLinkServiceTransport,Callable[..., AccountLinkServiceTransport]]]): + 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 AccountLinkServiceTransport 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, + ) = AccountLinkServiceClient._read_environment_variables() + self._client_cert_source = ( + AccountLinkServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = AccountLinkServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AccountLinkServiceTransport) + if transport_provided: + # transport is a AccountLinkServiceTransport 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(AccountLinkServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AccountLinkServiceClient._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[AccountLinkServiceTransport], + Callable[..., AccountLinkServiceTransport], + ] = ( + AccountLinkServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., AccountLinkServiceTransport], 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.ads.googleads.v24.services.AccountLinkServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AccountLinkService", + "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.ads.googleads.v24.services.AccountLinkService", + "credentialsType": None, + } + ), + ) + + def create_account_link( + self, + request: Optional[ + Union[account_link_service.CreateAccountLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + account_link: Optional[gagr_account_link.AccountLink] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> account_link_service.CreateAccountLinkResponse: + r"""Creates an account link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + `ThirdPartyAppAnalyticsLinkError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.CreateAccountLinkRequest, dict]): + The request object. Request message for + [AccountLinkService.CreateAccountLink][google.ads.googleads.v24.services.AccountLinkService.CreateAccountLink]. + customer_id (str): + Required. The ID of the customer for + which the account link is created. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + account_link (google.ads.googleads.v24.resources.types.AccountLink): + Required. The account link to be + created. + + This corresponds to the ``account_link`` 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.ads.googleads.v24.services.types.CreateAccountLinkResponse: + Response message for + [AccountLinkService.CreateAccountLink][google.ads.googleads.v24.services.AccountLinkService.CreateAccountLink]. + + """ + # 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 = [customer_id, account_link] + 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, account_link_service.CreateAccountLinkRequest + ): + request = account_link_service.CreateAccountLinkRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if account_link is not None: + request.account_link = account_link + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.create_account_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 mutate_account_link( + self, + request: Optional[ + Union[account_link_service.MutateAccountLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[account_link_service.AccountLinkOperation] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> account_link_service.MutateAccountLinkResponse: + r"""Creates or removes an account link. From V5, create is not + supported through AccountLinkService.MutateAccountLink. Use + AccountLinkService.CreateAccountLink instead. + + List of thrown errors: `AccountLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAccountLinkRequest, dict]): + The request object. Request message for + [AccountLinkService.MutateAccountLink][google.ads.googleads.v24.services.AccountLinkService.MutateAccountLink]. + customer_id (str): + Required. The ID of the customer + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (google.ads.googleads.v24.services.types.AccountLinkOperation): + Required. The operation to perform on + the link. + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateAccountLinkResponse: + Response message for account link + mutate. + + """ + # 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 = [customer_id, operation] + 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, account_link_service.MutateAccountLinkRequest + ): + request = account_link_service.MutateAccountLinkRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_account_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AccountLinkServiceClient": + 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() + + +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__ = ("AccountLinkServiceClient",) diff --git a/google/ads/googleads/v24/services/services/account_link_service/transports/README.rst b/google/ads/googleads/v24/services/services/account_link_service/transports/README.rst new file mode 100644 index 000000000..9d512545f --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_link_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AccountLinkServiceTransport` is the ABC for all transports. +- public child `AccountLinkServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AccountLinkServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAccountLinkServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AccountLinkServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/account_link_service/transports/__init__.py b/google/ads/googleads/v24/services/services/account_link_service/transports/__init__.py new file mode 100644 index 000000000..0e0427054 --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_link_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AccountLinkServiceTransport +from .grpc import AccountLinkServiceGrpcTransport +from .grpc_asyncio import AccountLinkServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AccountLinkServiceTransport]] +_transport_registry["grpc"] = AccountLinkServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AccountLinkServiceGrpcAsyncIOTransport + +__all__ = ( + "AccountLinkServiceTransport", + "AccountLinkServiceGrpcTransport", + "AccountLinkServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/account_link_service/transports/base.py b/google/ads/googleads/v24/services/services/account_link_service/transports/base.py new file mode 100644 index 000000000..b06a1d7fe --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_link_service/transports/base.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import account_link_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 AccountLinkServiceTransport(abc.ABC): + """Abstract transport class for AccountLinkService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.create_account_link: gapic_v1.method.wrap_method( + self.create_account_link, + default_timeout=None, + client_info=client_info, + ), + self.mutate_account_link: gapic_v1.method.wrap_method( + self.mutate_account_link, + 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 create_account_link( + self, + ) -> Callable[ + [account_link_service.CreateAccountLinkRequest], + Union[ + account_link_service.CreateAccountLinkResponse, + Awaitable[account_link_service.CreateAccountLinkResponse], + ], + ]: + raise NotImplementedError() + + @property + def mutate_account_link( + self, + ) -> Callable[ + [account_link_service.MutateAccountLinkRequest], + Union[ + account_link_service.MutateAccountLinkResponse, + Awaitable[account_link_service.MutateAccountLinkResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AccountLinkServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/account_link_service/transports/grpc.py b/google/ads/googleads/v24/services/services/account_link_service/transports/grpc.py new file mode 100644 index 000000000..fe710a02d --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_link_service/transports/grpc.py @@ -0,0 +1,428 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import account_link_service +from .base import AccountLinkServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AccountLinkService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AccountLinkService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AccountLinkServiceGrpcTransport(AccountLinkServiceTransport): + """gRPC backend transport for AccountLinkService. + + This service allows management of links between Google Ads + accounts and other accounts. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 create_account_link( + self, + ) -> Callable[ + [account_link_service.CreateAccountLinkRequest], + account_link_service.CreateAccountLinkResponse, + ]: + r"""Return a callable for the create account link method over gRPC. + + Creates an account link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + `ThirdPartyAppAnalyticsLinkError <>`__ + + Returns: + Callable[[~.CreateAccountLinkRequest], + ~.CreateAccountLinkResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_account_link" not in self._stubs: + self._stubs["create_account_link"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AccountLinkService/CreateAccountLink", + request_serializer=account_link_service.CreateAccountLinkRequest.serialize, + response_deserializer=account_link_service.CreateAccountLinkResponse.deserialize, + ) + ) + return self._stubs["create_account_link"] + + @property + def mutate_account_link( + self, + ) -> Callable[ + [account_link_service.MutateAccountLinkRequest], + account_link_service.MutateAccountLinkResponse, + ]: + r"""Return a callable for the mutate account link method over gRPC. + + Creates or removes an account link. From V5, create is not + supported through AccountLinkService.MutateAccountLink. Use + AccountLinkService.CreateAccountLink instead. + + List of thrown errors: `AccountLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateAccountLinkRequest], + ~.MutateAccountLinkResponse]: + 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 "mutate_account_link" not in self._stubs: + self._stubs["mutate_account_link"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AccountLinkService/MutateAccountLink", + request_serializer=account_link_service.MutateAccountLinkRequest.serialize, + response_deserializer=account_link_service.MutateAccountLinkResponse.deserialize, + ) + ) + return self._stubs["mutate_account_link"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AccountLinkServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/account_link_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/account_link_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..731d43043 --- /dev/null +++ b/google/ads/googleads/v24/services/services/account_link_service/transports/grpc_asyncio.py @@ -0,0 +1,454 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import account_link_service +from .base import AccountLinkServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AccountLinkService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AccountLinkService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AccountLinkServiceGrpcAsyncIOTransport(AccountLinkServiceTransport): + """gRPC AsyncIO backend transport for AccountLinkService. + + This service allows management of links between Google Ads + accounts and other accounts. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 create_account_link( + self, + ) -> Callable[ + [account_link_service.CreateAccountLinkRequest], + Awaitable[account_link_service.CreateAccountLinkResponse], + ]: + r"""Return a callable for the create account link method over gRPC. + + Creates an account link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + `ThirdPartyAppAnalyticsLinkError <>`__ + + Returns: + Callable[[~.CreateAccountLinkRequest], + Awaitable[~.CreateAccountLinkResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_account_link" not in self._stubs: + self._stubs["create_account_link"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AccountLinkService/CreateAccountLink", + request_serializer=account_link_service.CreateAccountLinkRequest.serialize, + response_deserializer=account_link_service.CreateAccountLinkResponse.deserialize, + ) + ) + return self._stubs["create_account_link"] + + @property + def mutate_account_link( + self, + ) -> Callable[ + [account_link_service.MutateAccountLinkRequest], + Awaitable[account_link_service.MutateAccountLinkResponse], + ]: + r"""Return a callable for the mutate account link method over gRPC. + + Creates or removes an account link. From V5, create is not + supported through AccountLinkService.MutateAccountLink. Use + AccountLinkService.CreateAccountLink instead. + + List of thrown errors: `AccountLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateAccountLinkRequest], + Awaitable[~.MutateAccountLinkResponse]]: + 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 "mutate_account_link" not in self._stubs: + self._stubs["mutate_account_link"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AccountLinkService/MutateAccountLink", + request_serializer=account_link_service.MutateAccountLinkRequest.serialize, + response_deserializer=account_link_service.MutateAccountLinkResponse.deserialize, + ) + ) + return self._stubs["mutate_account_link"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.create_account_link: self._wrap_method( + self.create_account_link, + default_timeout=None, + client_info=client_info, + ), + self.mutate_account_link: self._wrap_method( + self.mutate_account_link, + 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" + + +__all__ = ("AccountLinkServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_label_service/__init__.py b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/__init__.py new file mode 100644 index 000000000..265eaa120 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AdGroupAdLabelServiceClient +from .async_client import AdGroupAdLabelServiceAsyncClient + +__all__ = ( + "AdGroupAdLabelServiceClient", + "AdGroupAdLabelServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_label_service/async_client.py b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/async_client.py new file mode 100644 index 000000000..3522404e5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/async_client.py @@ -0,0 +1,436 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ad_group_ad_label_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdGroupAdLabelServiceTransport, DEFAULT_CLIENT_INFO +from .client import AdGroupAdLabelServiceClient + +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 AdGroupAdLabelServiceAsyncClient: + """Service to manage labels on ad group ads.""" + + _client: AdGroupAdLabelServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AdGroupAdLabelServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AdGroupAdLabelServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AdGroupAdLabelServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AdGroupAdLabelServiceClient._DEFAULT_UNIVERSE + + ad_group_ad_path = staticmethod( + AdGroupAdLabelServiceClient.ad_group_ad_path + ) + parse_ad_group_ad_path = staticmethod( + AdGroupAdLabelServiceClient.parse_ad_group_ad_path + ) + ad_group_ad_label_path = staticmethod( + AdGroupAdLabelServiceClient.ad_group_ad_label_path + ) + parse_ad_group_ad_label_path = staticmethod( + AdGroupAdLabelServiceClient.parse_ad_group_ad_label_path + ) + label_path = staticmethod(AdGroupAdLabelServiceClient.label_path) + parse_label_path = staticmethod( + AdGroupAdLabelServiceClient.parse_label_path + ) + common_billing_account_path = staticmethod( + AdGroupAdLabelServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AdGroupAdLabelServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AdGroupAdLabelServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AdGroupAdLabelServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AdGroupAdLabelServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AdGroupAdLabelServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AdGroupAdLabelServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AdGroupAdLabelServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AdGroupAdLabelServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AdGroupAdLabelServiceClient.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: + AdGroupAdLabelServiceAsyncClient: The constructed client. + """ + return AdGroupAdLabelServiceClient.from_service_account_info.__func__(AdGroupAdLabelServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AdGroupAdLabelServiceAsyncClient: The constructed client. + """ + return AdGroupAdLabelServiceClient.from_service_account_file.__func__(AdGroupAdLabelServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AdGroupAdLabelServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AdGroupAdLabelServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupAdLabelServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AdGroupAdLabelServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AdGroupAdLabelServiceTransport, + Callable[..., AdGroupAdLabelServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group ad label 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,AdGroupAdLabelServiceTransport,Callable[..., AdGroupAdLabelServiceTransport]]]): + 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 AdGroupAdLabelServiceTransport 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 = AdGroupAdLabelServiceClient( + 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.ads.googleads.v24.services.AdGroupAdLabelServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupAdLabelService", + "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.ads.googleads.v24.services.AdGroupAdLabelService", + "credentialsType": None, + } + ), + ) + + async def mutate_ad_group_ad_labels( + self, + request: Optional[ + Union[ad_group_ad_label_service.MutateAdGroupAdLabelsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_group_ad_label_service.AdGroupAdLabelOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_ad_label_service.MutateAdGroupAdLabelsResponse: + r"""Creates and removes ad group ad labels. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAdGroupAdLabelsRequest, dict]]): + The request object. Request message for + [AdGroupAdLabelService.MutateAdGroupAdLabels][google.ads.googleads.v24.services.AdGroupAdLabelService.MutateAdGroupAdLabels]. + customer_id (:class:`str`): + Required. ID of the customer whose ad + group ad labels are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AdGroupAdLabelOperation]`): + Required. The list of operations to + perform on ad group ad labels. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupAdLabelsResponse: + Response message for an ad group ad + labels mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_ad_label_service.MutateAdGroupAdLabelsRequest + ): + request = ad_group_ad_label_service.MutateAdGroupAdLabelsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_ad_group_ad_labels + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AdGroupAdLabelServiceAsyncClient": + 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__ = ("AdGroupAdLabelServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_label_service/client.py b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/client.py new file mode 100644 index 000000000..664e6356b --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/client.py @@ -0,0 +1,949 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ad_group_ad_label_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdGroupAdLabelServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import AdGroupAdLabelServiceGrpcTransport +from .transports.grpc_asyncio import AdGroupAdLabelServiceGrpcAsyncIOTransport + + +class AdGroupAdLabelServiceClientMeta(type): + """Metaclass for the AdGroupAdLabelService 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[AdGroupAdLabelServiceTransport]] + _transport_registry["grpc"] = AdGroupAdLabelServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AdGroupAdLabelServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdGroupAdLabelServiceTransport]: + """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 AdGroupAdLabelServiceClient(metaclass=AdGroupAdLabelServiceClientMeta): + """Service to manage labels on ad group ads.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AdGroupAdLabelServiceClient: 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: + AdGroupAdLabelServiceClient: 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) -> AdGroupAdLabelServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupAdLabelServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_group_ad_path( + customer_id: str, + ad_group_id: str, + ad_id: str, + ) -> str: + """Returns a fully-qualified ad_group_ad string.""" + return ( + "customers/{customer_id}/adGroupAds/{ad_group_id}~{ad_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ad_id=ad_id, + ) + ) + + @staticmethod + def parse_ad_group_ad_path(path: str) -> Dict[str, str]: + """Parses a ad_group_ad path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAds/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_ad_label_path( + customer_id: str, + ad_group_id: str, + ad_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified ad_group_ad_label string.""" + return "customers/{customer_id}/adGroupAdLabels/{ad_group_id}~{ad_id}~{label_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ad_id=ad_id, + label_id=label_id, + ) + + @staticmethod + def parse_ad_group_ad_label_path(path: str) -> Dict[str, str]: + """Parses a ad_group_ad_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAdLabels/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def label_path( + customer_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified label string.""" + return "customers/{customer_id}/labels/{label_id}".format( + customer_id=customer_id, + label_id=label_id, + ) + + @staticmethod + def parse_label_path(path: str) -> Dict[str, str]: + """Parses a label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/labels/(?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 = ( + AdGroupAdLabelServiceClient._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 = ( + AdGroupAdLabelServiceClient._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 + ): + """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 = AdGroupAdLabelServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AdGroupAdLabelServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AdGroupAdLabelServiceClient._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 = AdGroupAdLabelServiceClient._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): + """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, + AdGroupAdLabelServiceTransport, + Callable[..., AdGroupAdLabelServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group ad label 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,AdGroupAdLabelServiceTransport,Callable[..., AdGroupAdLabelServiceTransport]]]): + 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 AdGroupAdLabelServiceTransport 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, + ) = AdGroupAdLabelServiceClient._read_environment_variables() + self._client_cert_source = ( + AdGroupAdLabelServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + AdGroupAdLabelServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AdGroupAdLabelServiceTransport + ) + if transport_provided: + # transport is a AdGroupAdLabelServiceTransport 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(AdGroupAdLabelServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AdGroupAdLabelServiceClient._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[AdGroupAdLabelServiceTransport], + Callable[..., AdGroupAdLabelServiceTransport], + ] = ( + AdGroupAdLabelServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AdGroupAdLabelServiceTransport], 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.ads.googleads.v24.services.AdGroupAdLabelServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupAdLabelService", + "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.ads.googleads.v24.services.AdGroupAdLabelService", + "credentialsType": None, + } + ), + ) + + def mutate_ad_group_ad_labels( + self, + request: Optional[ + Union[ad_group_ad_label_service.MutateAdGroupAdLabelsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_group_ad_label_service.AdGroupAdLabelOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_ad_label_service.MutateAdGroupAdLabelsResponse: + r"""Creates and removes ad group ad labels. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAdGroupAdLabelsRequest, dict]): + The request object. Request message for + [AdGroupAdLabelService.MutateAdGroupAdLabels][google.ads.googleads.v24.services.AdGroupAdLabelService.MutateAdGroupAdLabels]. + customer_id (str): + Required. ID of the customer whose ad + group ad labels are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupAdLabelOperation]): + Required. The list of operations to + perform on ad group ad labels. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupAdLabelsResponse: + Response message for an ad group ad + labels mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_ad_label_service.MutateAdGroupAdLabelsRequest + ): + request = ad_group_ad_label_service.MutateAdGroupAdLabelsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_ad_group_ad_labels + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AdGroupAdLabelServiceClient": + 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() + + +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__ = ("AdGroupAdLabelServiceClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/README.rst b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/README.rst new file mode 100644 index 000000000..d5f9403de --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AdGroupAdLabelServiceTransport` is the ABC for all transports. +- public child `AdGroupAdLabelServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AdGroupAdLabelServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAdGroupAdLabelServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AdGroupAdLabelServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/__init__.py b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/__init__.py new file mode 100644 index 000000000..c5e23ca13 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AdGroupAdLabelServiceTransport +from .grpc import AdGroupAdLabelServiceGrpcTransport +from .grpc_asyncio import AdGroupAdLabelServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupAdLabelServiceTransport]] +_transport_registry["grpc"] = AdGroupAdLabelServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AdGroupAdLabelServiceGrpcAsyncIOTransport + +__all__ = ( + "AdGroupAdLabelServiceTransport", + "AdGroupAdLabelServiceGrpcTransport", + "AdGroupAdLabelServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/base.py b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/base.py new file mode 100644 index 000000000..dc3cfd39c --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ad_group_ad_label_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 AdGroupAdLabelServiceTransport(abc.ABC): + """Abstract transport class for AdGroupAdLabelService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ad_group_ad_labels: gapic_v1.method.wrap_method( + self.mutate_ad_group_ad_labels, + 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 mutate_ad_group_ad_labels( + self, + ) -> Callable[ + [ad_group_ad_label_service.MutateAdGroupAdLabelsRequest], + Union[ + ad_group_ad_label_service.MutateAdGroupAdLabelsResponse, + Awaitable[ad_group_ad_label_service.MutateAdGroupAdLabelsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AdGroupAdLabelServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/grpc.py b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/grpc.py new file mode 100644 index 000000000..f195d2920 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/grpc.py @@ -0,0 +1,390 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_ad_label_service +from .base import AdGroupAdLabelServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupAdLabelService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupAdLabelService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupAdLabelServiceGrpcTransport(AdGroupAdLabelServiceTransport): + """gRPC backend transport for AdGroupAdLabelService. + + Service to manage labels on ad group ads. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_ad_group_ad_labels( + self, + ) -> Callable[ + [ad_group_ad_label_service.MutateAdGroupAdLabelsRequest], + ad_group_ad_label_service.MutateAdGroupAdLabelsResponse, + ]: + r"""Return a callable for the mutate ad group ad labels method over gRPC. + + Creates and removes ad group ad labels. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateAdGroupAdLabelsRequest], + ~.MutateAdGroupAdLabelsResponse]: + 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 "mutate_ad_group_ad_labels" not in self._stubs: + self._stubs["mutate_ad_group_ad_labels"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupAdLabelService/MutateAdGroupAdLabels", + request_serializer=ad_group_ad_label_service.MutateAdGroupAdLabelsRequest.serialize, + response_deserializer=ad_group_ad_label_service.MutateAdGroupAdLabelsResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_ad_labels"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AdGroupAdLabelServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..64f54c895 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_label_service/transports/grpc_asyncio.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_ad_label_service +from .base import AdGroupAdLabelServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupAdLabelService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupAdLabelService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupAdLabelServiceGrpcAsyncIOTransport(AdGroupAdLabelServiceTransport): + """gRPC AsyncIO backend transport for AdGroupAdLabelService. + + Service to manage labels on ad group ads. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_ad_group_ad_labels( + self, + ) -> Callable[ + [ad_group_ad_label_service.MutateAdGroupAdLabelsRequest], + Awaitable[ad_group_ad_label_service.MutateAdGroupAdLabelsResponse], + ]: + r"""Return a callable for the mutate ad group ad labels method over gRPC. + + Creates and removes ad group ad labels. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateAdGroupAdLabelsRequest], + Awaitable[~.MutateAdGroupAdLabelsResponse]]: + 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 "mutate_ad_group_ad_labels" not in self._stubs: + self._stubs["mutate_ad_group_ad_labels"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupAdLabelService/MutateAdGroupAdLabels", + request_serializer=ad_group_ad_label_service.MutateAdGroupAdLabelsRequest.serialize, + response_deserializer=ad_group_ad_label_service.MutateAdGroupAdLabelsResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_ad_labels"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_ad_group_ad_labels: self._wrap_method( + self.mutate_ad_group_ad_labels, + 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" + + +__all__ = ("AdGroupAdLabelServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_service/__init__.py b/google/ads/googleads/v24/services/services/ad_group_ad_service/__init__.py new file mode 100644 index 000000000..710c5a37a --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AdGroupAdServiceClient +from .async_client import AdGroupAdServiceAsyncClient + +__all__ = ( + "AdGroupAdServiceClient", + "AdGroupAdServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_service/async_client.py b/google/ads/googleads/v24/services/services/ad_group_ad_service/async_client.py new file mode 100644 index 000000000..4cc2623c6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_service/async_client.py @@ -0,0 +1,554 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ad_group_ad_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdGroupAdServiceTransport, DEFAULT_CLIENT_INFO +from .client import AdGroupAdServiceClient + +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 AdGroupAdServiceAsyncClient: + """Service to manage ads in an ad group.""" + + _client: AdGroupAdServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AdGroupAdServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AdGroupAdServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AdGroupAdServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AdGroupAdServiceClient._DEFAULT_UNIVERSE + + ad_path = staticmethod(AdGroupAdServiceClient.ad_path) + parse_ad_path = staticmethod(AdGroupAdServiceClient.parse_ad_path) + ad_group_path = staticmethod(AdGroupAdServiceClient.ad_group_path) + parse_ad_group_path = staticmethod( + AdGroupAdServiceClient.parse_ad_group_path + ) + ad_group_ad_path = staticmethod(AdGroupAdServiceClient.ad_group_ad_path) + parse_ad_group_ad_path = staticmethod( + AdGroupAdServiceClient.parse_ad_group_ad_path + ) + ad_group_ad_label_path = staticmethod( + AdGroupAdServiceClient.ad_group_ad_label_path + ) + parse_ad_group_ad_label_path = staticmethod( + AdGroupAdServiceClient.parse_ad_group_ad_label_path + ) + asset_path = staticmethod(AdGroupAdServiceClient.asset_path) + parse_asset_path = staticmethod(AdGroupAdServiceClient.parse_asset_path) + common_billing_account_path = staticmethod( + AdGroupAdServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AdGroupAdServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(AdGroupAdServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + AdGroupAdServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AdGroupAdServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AdGroupAdServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AdGroupAdServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AdGroupAdServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AdGroupAdServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AdGroupAdServiceClient.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: + AdGroupAdServiceAsyncClient: The constructed client. + """ + return AdGroupAdServiceClient.from_service_account_info.__func__(AdGroupAdServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AdGroupAdServiceAsyncClient: The constructed client. + """ + return AdGroupAdServiceClient.from_service_account_file.__func__(AdGroupAdServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AdGroupAdServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AdGroupAdServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupAdServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AdGroupAdServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AdGroupAdServiceTransport, + Callable[..., AdGroupAdServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group ad 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,AdGroupAdServiceTransport,Callable[..., AdGroupAdServiceTransport]]]): + 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 AdGroupAdServiceTransport 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 = AdGroupAdServiceClient( + 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.ads.googleads.v24.services.AdGroupAdServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupAdService", + "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.ads.googleads.v24.services.AdGroupAdService", + "credentialsType": None, + } + ), + ) + + async def mutate_ad_group_ads( + self, + request: Optional[ + Union[ad_group_ad_service.MutateAdGroupAdsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_group_ad_service.AdGroupAdOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_ad_service.MutateAdGroupAdsResponse: + r"""Creates, updates, or removes ads. Operation statuses are + returned. + + List of thrown errors: `AdCustomizerError <>`__ `AdError <>`__ + `AdGroupAdError <>`__ `AdSharingError <>`__ `AdxError <>`__ + `AssetError <>`__ `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CollectionSizeError <>`__ `ContextError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FeedAttributeReferenceError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `FunctionError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `IdError <>`__ + `ImageError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MediaBundleError <>`__ `MediaFileError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `PolicyFindingError <>`__ + `PolicyValidationParameterError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ `UrlFieldError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAdGroupAdsRequest, dict]]): + The request object. Request message for + [AdGroupAdService.MutateAdGroupAds][google.ads.googleads.v24.services.AdGroupAdService.MutateAdGroupAds]. + customer_id (:class:`str`): + Required. The ID of the customer + whose ads are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AdGroupAdOperation]`): + Required. The list of operations to + perform on individual ads. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupAdsResponse: + Response message for an ad group ad + mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_ad_service.MutateAdGroupAdsRequest): + request = ad_group_ad_service.MutateAdGroupAdsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_ad_group_ads + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 remove_automatically_created_assets( + self, + request: Optional[ + Union[ + ad_group_ad_service.RemoveAutomaticallyCreatedAssetsRequest, + dict, + ] + ] = None, + *, + ad_group_ad: Optional[str] = None, + assets_with_field_type: Optional[ + MutableSequence[ad_group_ad_service.AssetsWithFieldType] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Remove automatically created assets from an ad. + + List of thrown errors: `AdError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ + `AutomaticallyCreatedAssetRemovalError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.RemoveAutomaticallyCreatedAssetsRequest, dict]]): + The request object. Request message for + [AdGroupAdService.RemoveAutomaticallyCreatedAssets][google.ads.googleads.v24.services.AdGroupAdService.RemoveAutomaticallyCreatedAssets]. + ad_group_ad (:class:`str`): + Required. The resource name of the + AdGroupAd from which to remove + automatically created assets. + + This corresponds to the ``ad_group_ad`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + assets_with_field_type (:class:`MutableSequence[google.ads.googleads.v24.services.types.AssetsWithFieldType]`): + Required. List of assets with field + type to be removed from the AdGroupAd. + + This corresponds to the ``assets_with_field_type`` 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 = [ad_group_ad, assets_with_field_type] + 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, ad_group_ad_service.RemoveAutomaticallyCreatedAssetsRequest + ): + request = ( + ad_group_ad_service.RemoveAutomaticallyCreatedAssetsRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if ad_group_ad is not None: + request.ad_group_ad = ad_group_ad + if assets_with_field_type: + request.assets_with_field_type.extend(assets_with_field_type) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.remove_automatically_created_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("ad_group_ad", request.ad_group_ad),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + async def __aenter__(self) -> "AdGroupAdServiceAsyncClient": + 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__ = ("AdGroupAdServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_service/client.py b/google/ads/googleads/v24/services/services/ad_group_ad_service/client.py new file mode 100644 index 000000000..fa7664f44 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_service/client.py @@ -0,0 +1,1093 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ad_group_ad_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdGroupAdServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import AdGroupAdServiceGrpcTransport +from .transports.grpc_asyncio import AdGroupAdServiceGrpcAsyncIOTransport + + +class AdGroupAdServiceClientMeta(type): + """Metaclass for the AdGroupAdService 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[AdGroupAdServiceTransport]] + _transport_registry["grpc"] = AdGroupAdServiceGrpcTransport + _transport_registry["grpc_asyncio"] = AdGroupAdServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdGroupAdServiceTransport]: + """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 AdGroupAdServiceClient(metaclass=AdGroupAdServiceClientMeta): + """Service to manage ads in an ad group.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AdGroupAdServiceClient: 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: + AdGroupAdServiceClient: 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) -> AdGroupAdServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupAdServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_path( + customer_id: str, + ad_id: str, + ) -> str: + """Returns a fully-qualified ad string.""" + return "customers/{customer_id}/ads/{ad_id}".format( + customer_id=customer_id, + ad_id=ad_id, + ) + + @staticmethod + def parse_ad_path(path: str) -> Dict[str, str]: + """Parses a ad path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/ads/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_path( + customer_id: str, + ad_group_id: str, + ) -> str: + """Returns a fully-qualified ad_group string.""" + return "customers/{customer_id}/adGroups/{ad_group_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ) + + @staticmethod + def parse_ad_group_path(path: str) -> Dict[str, str]: + """Parses a ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_ad_path( + customer_id: str, + ad_group_id: str, + ad_id: str, + ) -> str: + """Returns a fully-qualified ad_group_ad string.""" + return ( + "customers/{customer_id}/adGroupAds/{ad_group_id}~{ad_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ad_id=ad_id, + ) + ) + + @staticmethod + def parse_ad_group_ad_path(path: str) -> Dict[str, str]: + """Parses a ad_group_ad path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAds/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_ad_label_path( + customer_id: str, + ad_group_id: str, + ad_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified ad_group_ad_label string.""" + return "customers/{customer_id}/adGroupAdLabels/{ad_group_id}~{ad_id}~{label_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ad_id=ad_id, + label_id=label_id, + ) + + @staticmethod + def parse_ad_group_ad_label_path(path: str) -> Dict[str, str]: + """Parses a ad_group_ad_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAdLabels/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_path( + customer_id: str, + asset_id: str, + ) -> str: + """Returns a fully-qualified asset string.""" + return "customers/{customer_id}/assets/{asset_id}".format( + customer_id=customer_id, + asset_id=asset_id, + ) + + @staticmethod + def parse_asset_path(path: str) -> Dict[str, str]: + """Parses a asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assets/(?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 = AdGroupAdServiceClient._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 = AdGroupAdServiceClient._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 + ): + """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 = AdGroupAdServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AdGroupAdServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AdGroupAdServiceClient._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 = AdGroupAdServiceClient._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): + """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, + AdGroupAdServiceTransport, + Callable[..., AdGroupAdServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group ad 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,AdGroupAdServiceTransport,Callable[..., AdGroupAdServiceTransport]]]): + 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 AdGroupAdServiceTransport 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, + ) = AdGroupAdServiceClient._read_environment_variables() + self._client_cert_source = ( + AdGroupAdServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = AdGroupAdServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AdGroupAdServiceTransport) + if transport_provided: + # transport is a AdGroupAdServiceTransport 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(AdGroupAdServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AdGroupAdServiceClient._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[AdGroupAdServiceTransport], + Callable[..., AdGroupAdServiceTransport], + ] = ( + AdGroupAdServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., AdGroupAdServiceTransport], 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.ads.googleads.v24.services.AdGroupAdServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupAdService", + "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.ads.googleads.v24.services.AdGroupAdService", + "credentialsType": None, + } + ), + ) + + def mutate_ad_group_ads( + self, + request: Optional[ + Union[ad_group_ad_service.MutateAdGroupAdsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_group_ad_service.AdGroupAdOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_ad_service.MutateAdGroupAdsResponse: + r"""Creates, updates, or removes ads. Operation statuses are + returned. + + List of thrown errors: `AdCustomizerError <>`__ `AdError <>`__ + `AdGroupAdError <>`__ `AdSharingError <>`__ `AdxError <>`__ + `AssetError <>`__ `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CollectionSizeError <>`__ `ContextError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FeedAttributeReferenceError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `FunctionError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `IdError <>`__ + `ImageError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MediaBundleError <>`__ `MediaFileError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `PolicyFindingError <>`__ + `PolicyValidationParameterError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ `UrlFieldError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAdGroupAdsRequest, dict]): + The request object. Request message for + [AdGroupAdService.MutateAdGroupAds][google.ads.googleads.v24.services.AdGroupAdService.MutateAdGroupAds]. + customer_id (str): + Required. The ID of the customer + whose ads are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupAdOperation]): + Required. The list of operations to + perform on individual ads. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupAdsResponse: + Response message for an ad group ad + mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_ad_service.MutateAdGroupAdsRequest): + request = ad_group_ad_service.MutateAdGroupAdsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_ad_group_ads + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 remove_automatically_created_assets( + self, + request: Optional[ + Union[ + ad_group_ad_service.RemoveAutomaticallyCreatedAssetsRequest, + dict, + ] + ] = None, + *, + ad_group_ad: Optional[str] = None, + assets_with_field_type: Optional[ + MutableSequence[ad_group_ad_service.AssetsWithFieldType] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Remove automatically created assets from an ad. + + List of thrown errors: `AdError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ + `AutomaticallyCreatedAssetRemovalError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.RemoveAutomaticallyCreatedAssetsRequest, dict]): + The request object. Request message for + [AdGroupAdService.RemoveAutomaticallyCreatedAssets][google.ads.googleads.v24.services.AdGroupAdService.RemoveAutomaticallyCreatedAssets]. + ad_group_ad (str): + Required. The resource name of the + AdGroupAd from which to remove + automatically created assets. + + This corresponds to the ``ad_group_ad`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + assets_with_field_type (MutableSequence[google.ads.googleads.v24.services.types.AssetsWithFieldType]): + Required. List of assets with field + type to be removed from the AdGroupAd. + + This corresponds to the ``assets_with_field_type`` 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`. + """ + # 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 = [ad_group_ad, assets_with_field_type] + 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, ad_group_ad_service.RemoveAutomaticallyCreatedAssetsRequest + ): + request = ( + ad_group_ad_service.RemoveAutomaticallyCreatedAssetsRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if ad_group_ad is not None: + request.ad_group_ad = ad_group_ad + if assets_with_field_type is not None: + request.assets_with_field_type = assets_with_field_type + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.remove_automatically_created_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("ad_group_ad", request.ad_group_ad),) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + def __enter__(self) -> "AdGroupAdServiceClient": + 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() + + +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__ = ("AdGroupAdServiceClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/README.rst b/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/README.rst new file mode 100644 index 000000000..57df60193 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AdGroupAdServiceTransport` is the ABC for all transports. +- public child `AdGroupAdServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AdGroupAdServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAdGroupAdServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AdGroupAdServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/__init__.py b/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/__init__.py new file mode 100644 index 000000000..865006e3f --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AdGroupAdServiceTransport +from .grpc import AdGroupAdServiceGrpcTransport +from .grpc_asyncio import AdGroupAdServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupAdServiceTransport]] +_transport_registry["grpc"] = AdGroupAdServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AdGroupAdServiceGrpcAsyncIOTransport + +__all__ = ( + "AdGroupAdServiceTransport", + "AdGroupAdServiceGrpcTransport", + "AdGroupAdServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/base.py b/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/base.py new file mode 100644 index 000000000..d907e9909 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/base.py @@ -0,0 +1,188 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ad_group_ad_service +from google.protobuf import empty_pb2 # type: ignore + +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 AdGroupAdServiceTransport(abc.ABC): + """Abstract transport class for AdGroupAdService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ad_group_ads: gapic_v1.method.wrap_method( + self.mutate_ad_group_ads, + default_timeout=None, + client_info=client_info, + ), + self.remove_automatically_created_assets: gapic_v1.method.wrap_method( + self.remove_automatically_created_assets, + 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 mutate_ad_group_ads( + self, + ) -> Callable[ + [ad_group_ad_service.MutateAdGroupAdsRequest], + Union[ + ad_group_ad_service.MutateAdGroupAdsResponse, + Awaitable[ad_group_ad_service.MutateAdGroupAdsResponse], + ], + ]: + raise NotImplementedError() + + @property + def remove_automatically_created_assets( + self, + ) -> Callable[ + [ad_group_ad_service.RemoveAutomaticallyCreatedAssetsRequest], + Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AdGroupAdServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/grpc.py b/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/grpc.py new file mode 100644 index 000000000..2cd8f4098 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/grpc.py @@ -0,0 +1,443 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_ad_service +from google.protobuf import empty_pb2 # type: ignore +from .base import AdGroupAdServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupAdService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupAdService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupAdServiceGrpcTransport(AdGroupAdServiceTransport): + """gRPC backend transport for AdGroupAdService. + + Service to manage ads in an ad group. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_ad_group_ads( + self, + ) -> Callable[ + [ad_group_ad_service.MutateAdGroupAdsRequest], + ad_group_ad_service.MutateAdGroupAdsResponse, + ]: + r"""Return a callable for the mutate ad group ads method over gRPC. + + Creates, updates, or removes ads. Operation statuses are + returned. + + List of thrown errors: `AdCustomizerError <>`__ `AdError <>`__ + `AdGroupAdError <>`__ `AdSharingError <>`__ `AdxError <>`__ + `AssetError <>`__ `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CollectionSizeError <>`__ `ContextError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FeedAttributeReferenceError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `FunctionError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `IdError <>`__ + `ImageError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MediaBundleError <>`__ `MediaFileError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `PolicyFindingError <>`__ + `PolicyValidationParameterError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateAdGroupAdsRequest], + ~.MutateAdGroupAdsResponse]: + 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 "mutate_ad_group_ads" not in self._stubs: + self._stubs["mutate_ad_group_ads"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupAdService/MutateAdGroupAds", + request_serializer=ad_group_ad_service.MutateAdGroupAdsRequest.serialize, + response_deserializer=ad_group_ad_service.MutateAdGroupAdsResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_ads"] + + @property + def remove_automatically_created_assets( + self, + ) -> Callable[ + [ad_group_ad_service.RemoveAutomaticallyCreatedAssetsRequest], + empty_pb2.Empty, + ]: + r"""Return a callable for the remove automatically created + assets method over gRPC. + + Remove automatically created assets from an ad. + + List of thrown errors: `AdError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ + `AutomaticallyCreatedAssetRemovalError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.RemoveAutomaticallyCreatedAssetsRequest], + ~.Empty]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "remove_automatically_created_assets" not in self._stubs: + self._stubs["remove_automatically_created_assets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupAdService/RemoveAutomaticallyCreatedAssets", + request_serializer=ad_group_ad_service.RemoveAutomaticallyCreatedAssetsRequest.serialize, + response_deserializer=empty_pb2.Empty.FromString, + ) + ) + return self._stubs["remove_automatically_created_assets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AdGroupAdServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..028c1f9fc --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_ad_service/transports/grpc_asyncio.py @@ -0,0 +1,469 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_ad_service +from google.protobuf import empty_pb2 # type: ignore +from .base import AdGroupAdServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupAdService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupAdService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupAdServiceGrpcAsyncIOTransport(AdGroupAdServiceTransport): + """gRPC AsyncIO backend transport for AdGroupAdService. + + Service to manage ads in an ad group. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_ad_group_ads( + self, + ) -> Callable[ + [ad_group_ad_service.MutateAdGroupAdsRequest], + Awaitable[ad_group_ad_service.MutateAdGroupAdsResponse], + ]: + r"""Return a callable for the mutate ad group ads method over gRPC. + + Creates, updates, or removes ads. Operation statuses are + returned. + + List of thrown errors: `AdCustomizerError <>`__ `AdError <>`__ + `AdGroupAdError <>`__ `AdSharingError <>`__ `AdxError <>`__ + `AssetError <>`__ `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CollectionSizeError <>`__ `ContextError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FeedAttributeReferenceError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `FunctionError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `IdError <>`__ + `ImageError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MediaBundleError <>`__ `MediaFileError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `PolicyFindingError <>`__ + `PolicyValidationParameterError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateAdGroupAdsRequest], + Awaitable[~.MutateAdGroupAdsResponse]]: + 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 "mutate_ad_group_ads" not in self._stubs: + self._stubs["mutate_ad_group_ads"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupAdService/MutateAdGroupAds", + request_serializer=ad_group_ad_service.MutateAdGroupAdsRequest.serialize, + response_deserializer=ad_group_ad_service.MutateAdGroupAdsResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_ads"] + + @property + def remove_automatically_created_assets( + self, + ) -> Callable[ + [ad_group_ad_service.RemoveAutomaticallyCreatedAssetsRequest], + Awaitable[empty_pb2.Empty], + ]: + r"""Return a callable for the remove automatically created + assets method over gRPC. + + Remove automatically created assets from an ad. + + List of thrown errors: `AdError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ + `AutomaticallyCreatedAssetRemovalError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.RemoveAutomaticallyCreatedAssetsRequest], + Awaitable[~.Empty]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "remove_automatically_created_assets" not in self._stubs: + self._stubs["remove_automatically_created_assets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupAdService/RemoveAutomaticallyCreatedAssets", + request_serializer=ad_group_ad_service.RemoveAutomaticallyCreatedAssetsRequest.serialize, + response_deserializer=empty_pb2.Empty.FromString, + ) + ) + return self._stubs["remove_automatically_created_assets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_ad_group_ads: self._wrap_method( + self.mutate_ad_group_ads, + default_timeout=None, + client_info=client_info, + ), + self.remove_automatically_created_assets: self._wrap_method( + self.remove_automatically_created_assets, + 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" + + +__all__ = ("AdGroupAdServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_service/__init__.py b/google/ads/googleads/v24/services/services/ad_group_asset_service/__init__.py new file mode 100644 index 000000000..4c01c9244 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AdGroupAssetServiceClient +from .async_client import AdGroupAssetServiceAsyncClient + +__all__ = ( + "AdGroupAssetServiceClient", + "AdGroupAssetServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_service/async_client.py b/google/ads/googleads/v24/services/services/ad_group_asset_service/async_client.py new file mode 100644 index 000000000..c11597df3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_service/async_client.py @@ -0,0 +1,431 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ad_group_asset_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdGroupAssetServiceTransport, DEFAULT_CLIENT_INFO +from .client import AdGroupAssetServiceClient + +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 AdGroupAssetServiceAsyncClient: + """Service to manage ad group assets.""" + + _client: AdGroupAssetServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AdGroupAssetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AdGroupAssetServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AdGroupAssetServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AdGroupAssetServiceClient._DEFAULT_UNIVERSE + + ad_group_path = staticmethod(AdGroupAssetServiceClient.ad_group_path) + parse_ad_group_path = staticmethod( + AdGroupAssetServiceClient.parse_ad_group_path + ) + ad_group_asset_path = staticmethod( + AdGroupAssetServiceClient.ad_group_asset_path + ) + parse_ad_group_asset_path = staticmethod( + AdGroupAssetServiceClient.parse_ad_group_asset_path + ) + asset_path = staticmethod(AdGroupAssetServiceClient.asset_path) + parse_asset_path = staticmethod(AdGroupAssetServiceClient.parse_asset_path) + common_billing_account_path = staticmethod( + AdGroupAssetServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AdGroupAssetServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AdGroupAssetServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AdGroupAssetServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AdGroupAssetServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AdGroupAssetServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AdGroupAssetServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AdGroupAssetServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AdGroupAssetServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AdGroupAssetServiceClient.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: + AdGroupAssetServiceAsyncClient: The constructed client. + """ + return AdGroupAssetServiceClient.from_service_account_info.__func__(AdGroupAssetServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AdGroupAssetServiceAsyncClient: The constructed client. + """ + return AdGroupAssetServiceClient.from_service_account_file.__func__(AdGroupAssetServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AdGroupAssetServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AdGroupAssetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupAssetServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AdGroupAssetServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AdGroupAssetServiceTransport, + Callable[..., AdGroupAssetServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group asset 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,AdGroupAssetServiceTransport,Callable[..., AdGroupAssetServiceTransport]]]): + 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 AdGroupAssetServiceTransport 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 = AdGroupAssetServiceClient( + 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.ads.googleads.v24.services.AdGroupAssetServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupAssetService", + "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.ads.googleads.v24.services.AdGroupAssetService", + "credentialsType": None, + } + ), + ) + + async def mutate_ad_group_assets( + self, + request: Optional[ + Union[ad_group_asset_service.MutateAdGroupAssetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_group_asset_service.AdGroupAssetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_asset_service.MutateAdGroupAssetsResponse: + r"""Creates, updates, or removes ad group assets. Operation statuses + are returned. + + List of thrown errors: `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ + `NotAllowlistedError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAdGroupAssetsRequest, dict]]): + The request object. Request message for + [AdGroupAssetService.MutateAdGroupAssets][google.ads.googleads.v24.services.AdGroupAssetService.MutateAdGroupAssets]. + customer_id (:class:`str`): + Required. The ID of the customer + whose ad group assets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AdGroupAssetOperation]`): + Required. The list of operations to + perform on individual ad group assets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupAssetsResponse: + Response message for an ad group + asset mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_asset_service.MutateAdGroupAssetsRequest + ): + request = ad_group_asset_service.MutateAdGroupAssetsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_ad_group_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AdGroupAssetServiceAsyncClient": + 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__ = ("AdGroupAssetServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_service/client.py b/google/ads/googleads/v24/services/services/ad_group_asset_service/client.py new file mode 100644 index 000000000..c9fe9425b --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_service/client.py @@ -0,0 +1,936 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ad_group_asset_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdGroupAssetServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import AdGroupAssetServiceGrpcTransport +from .transports.grpc_asyncio import AdGroupAssetServiceGrpcAsyncIOTransport + + +class AdGroupAssetServiceClientMeta(type): + """Metaclass for the AdGroupAssetService 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[AdGroupAssetServiceTransport]] + _transport_registry["grpc"] = AdGroupAssetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AdGroupAssetServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdGroupAssetServiceTransport]: + """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 AdGroupAssetServiceClient(metaclass=AdGroupAssetServiceClientMeta): + """Service to manage ad group assets.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AdGroupAssetServiceClient: 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: + AdGroupAssetServiceClient: 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) -> AdGroupAssetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupAssetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_group_path( + customer_id: str, + ad_group_id: str, + ) -> str: + """Returns a fully-qualified ad_group string.""" + return "customers/{customer_id}/adGroups/{ad_group_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ) + + @staticmethod + def parse_ad_group_path(path: str) -> Dict[str, str]: + """Parses a ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_asset_path( + customer_id: str, + ad_group_id: str, + asset_id: str, + field_type: str, + ) -> str: + """Returns a fully-qualified ad_group_asset string.""" + return "customers/{customer_id}/adGroupAssets/{ad_group_id}~{asset_id}~{field_type}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + asset_id=asset_id, + field_type=field_type, + ) + + @staticmethod + def parse_ad_group_asset_path(path: str) -> Dict[str, str]: + """Parses a ad_group_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAssets/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_path( + customer_id: str, + asset_id: str, + ) -> str: + """Returns a fully-qualified asset string.""" + return "customers/{customer_id}/assets/{asset_id}".format( + customer_id=customer_id, + asset_id=asset_id, + ) + + @staticmethod + def parse_asset_path(path: str) -> Dict[str, str]: + """Parses a asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assets/(?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 = AdGroupAssetServiceClient._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 = AdGroupAssetServiceClient._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 + ): + """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 = AdGroupAssetServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AdGroupAssetServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AdGroupAssetServiceClient._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 = AdGroupAssetServiceClient._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): + """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, + AdGroupAssetServiceTransport, + Callable[..., AdGroupAssetServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group asset 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,AdGroupAssetServiceTransport,Callable[..., AdGroupAssetServiceTransport]]]): + 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 AdGroupAssetServiceTransport 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, + ) = AdGroupAssetServiceClient._read_environment_variables() + self._client_cert_source = ( + AdGroupAssetServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = AdGroupAssetServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AdGroupAssetServiceTransport) + if transport_provided: + # transport is a AdGroupAssetServiceTransport 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(AdGroupAssetServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AdGroupAssetServiceClient._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[AdGroupAssetServiceTransport], + Callable[..., AdGroupAssetServiceTransport], + ] = ( + AdGroupAssetServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AdGroupAssetServiceTransport], 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.ads.googleads.v24.services.AdGroupAssetServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupAssetService", + "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.ads.googleads.v24.services.AdGroupAssetService", + "credentialsType": None, + } + ), + ) + + def mutate_ad_group_assets( + self, + request: Optional[ + Union[ad_group_asset_service.MutateAdGroupAssetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_group_asset_service.AdGroupAssetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_asset_service.MutateAdGroupAssetsResponse: + r"""Creates, updates, or removes ad group assets. Operation statuses + are returned. + + List of thrown errors: `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ + `NotAllowlistedError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAdGroupAssetsRequest, dict]): + The request object. Request message for + [AdGroupAssetService.MutateAdGroupAssets][google.ads.googleads.v24.services.AdGroupAssetService.MutateAdGroupAssets]. + customer_id (str): + Required. The ID of the customer + whose ad group assets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupAssetOperation]): + Required. The list of operations to + perform on individual ad group assets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupAssetsResponse: + Response message for an ad group + asset mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_asset_service.MutateAdGroupAssetsRequest + ): + request = ad_group_asset_service.MutateAdGroupAssetsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_ad_group_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AdGroupAssetServiceClient": + 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() + + +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__ = ("AdGroupAssetServiceClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/README.rst b/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/README.rst new file mode 100644 index 000000000..50f5a0055 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AdGroupAssetServiceTransport` is the ABC for all transports. +- public child `AdGroupAssetServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AdGroupAssetServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAdGroupAssetServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AdGroupAssetServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/__init__.py b/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/__init__.py new file mode 100644 index 000000000..9738adeb3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AdGroupAssetServiceTransport +from .grpc import AdGroupAssetServiceGrpcTransport +from .grpc_asyncio import AdGroupAssetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupAssetServiceTransport]] +_transport_registry["grpc"] = AdGroupAssetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AdGroupAssetServiceGrpcAsyncIOTransport + +__all__ = ( + "AdGroupAssetServiceTransport", + "AdGroupAssetServiceGrpcTransport", + "AdGroupAssetServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/base.py b/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/base.py new file mode 100644 index 000000000..51d2551c0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ad_group_asset_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 AdGroupAssetServiceTransport(abc.ABC): + """Abstract transport class for AdGroupAssetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ad_group_assets: gapic_v1.method.wrap_method( + self.mutate_ad_group_assets, + 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 mutate_ad_group_assets( + self, + ) -> Callable[ + [ad_group_asset_service.MutateAdGroupAssetsRequest], + Union[ + ad_group_asset_service.MutateAdGroupAssetsResponse, + Awaitable[ad_group_asset_service.MutateAdGroupAssetsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AdGroupAssetServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/grpc.py b/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/grpc.py new file mode 100644 index 000000000..c9e993630 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/grpc.py @@ -0,0 +1,390 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_asset_service +from .base import AdGroupAssetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupAssetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupAssetService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupAssetServiceGrpcTransport(AdGroupAssetServiceTransport): + """gRPC backend transport for AdGroupAssetService. + + Service to manage ad group assets. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_ad_group_assets( + self, + ) -> Callable[ + [ad_group_asset_service.MutateAdGroupAssetsRequest], + ad_group_asset_service.MutateAdGroupAssetsResponse, + ]: + r"""Return a callable for the mutate ad group assets method over gRPC. + + Creates, updates, or removes ad group assets. Operation statuses + are returned. + + List of thrown errors: `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ + `NotAllowlistedError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateAdGroupAssetsRequest], + ~.MutateAdGroupAssetsResponse]: + 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 "mutate_ad_group_assets" not in self._stubs: + self._stubs["mutate_ad_group_assets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupAssetService/MutateAdGroupAssets", + request_serializer=ad_group_asset_service.MutateAdGroupAssetsRequest.serialize, + response_deserializer=ad_group_asset_service.MutateAdGroupAssetsResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_assets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AdGroupAssetServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..e5340e306 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_service/transports/grpc_asyncio.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_asset_service +from .base import AdGroupAssetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupAssetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupAssetService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupAssetServiceGrpcAsyncIOTransport(AdGroupAssetServiceTransport): + """gRPC AsyncIO backend transport for AdGroupAssetService. + + Service to manage ad group assets. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_ad_group_assets( + self, + ) -> Callable[ + [ad_group_asset_service.MutateAdGroupAssetsRequest], + Awaitable[ad_group_asset_service.MutateAdGroupAssetsResponse], + ]: + r"""Return a callable for the mutate ad group assets method over gRPC. + + Creates, updates, or removes ad group assets. Operation statuses + are returned. + + List of thrown errors: `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ + `NotAllowlistedError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateAdGroupAssetsRequest], + Awaitable[~.MutateAdGroupAssetsResponse]]: + 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 "mutate_ad_group_assets" not in self._stubs: + self._stubs["mutate_ad_group_assets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupAssetService/MutateAdGroupAssets", + request_serializer=ad_group_asset_service.MutateAdGroupAssetsRequest.serialize, + response_deserializer=ad_group_asset_service.MutateAdGroupAssetsResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_assets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_ad_group_assets: self._wrap_method( + self.mutate_ad_group_assets, + 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" + + +__all__ = ("AdGroupAssetServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_set_service/__init__.py b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/__init__.py new file mode 100644 index 000000000..e9b0640d2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AdGroupAssetSetServiceClient +from .async_client import AdGroupAssetSetServiceAsyncClient + +__all__ = ( + "AdGroupAssetSetServiceClient", + "AdGroupAssetSetServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_set_service/async_client.py b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/async_client.py new file mode 100644 index 000000000..4808d1122 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/async_client.py @@ -0,0 +1,435 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ad_group_asset_set_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AdGroupAssetSetServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import AdGroupAssetSetServiceClient + +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 AdGroupAssetSetServiceAsyncClient: + """Service to manage ad group asset set""" + + _client: AdGroupAssetSetServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AdGroupAssetSetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AdGroupAssetSetServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AdGroupAssetSetServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AdGroupAssetSetServiceClient._DEFAULT_UNIVERSE + + ad_group_path = staticmethod(AdGroupAssetSetServiceClient.ad_group_path) + parse_ad_group_path = staticmethod( + AdGroupAssetSetServiceClient.parse_ad_group_path + ) + ad_group_asset_set_path = staticmethod( + AdGroupAssetSetServiceClient.ad_group_asset_set_path + ) + parse_ad_group_asset_set_path = staticmethod( + AdGroupAssetSetServiceClient.parse_ad_group_asset_set_path + ) + asset_set_path = staticmethod(AdGroupAssetSetServiceClient.asset_set_path) + parse_asset_set_path = staticmethod( + AdGroupAssetSetServiceClient.parse_asset_set_path + ) + common_billing_account_path = staticmethod( + AdGroupAssetSetServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AdGroupAssetSetServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AdGroupAssetSetServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AdGroupAssetSetServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AdGroupAssetSetServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AdGroupAssetSetServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AdGroupAssetSetServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AdGroupAssetSetServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AdGroupAssetSetServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AdGroupAssetSetServiceClient.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: + AdGroupAssetSetServiceAsyncClient: The constructed client. + """ + return AdGroupAssetSetServiceClient.from_service_account_info.__func__(AdGroupAssetSetServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AdGroupAssetSetServiceAsyncClient: The constructed client. + """ + return AdGroupAssetSetServiceClient.from_service_account_file.__func__(AdGroupAssetSetServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AdGroupAssetSetServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AdGroupAssetSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupAssetSetServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AdGroupAssetSetServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AdGroupAssetSetServiceTransport, + Callable[..., AdGroupAssetSetServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group asset set 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,AdGroupAssetSetServiceTransport,Callable[..., AdGroupAssetSetServiceTransport]]]): + 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 AdGroupAssetSetServiceTransport 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 = AdGroupAssetSetServiceClient( + 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.ads.googleads.v24.services.AdGroupAssetSetServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupAssetSetService", + "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.ads.googleads.v24.services.AdGroupAssetSetService", + "credentialsType": None, + } + ), + ) + + async def mutate_ad_group_asset_sets( + self, + request: Optional[ + Union[ + ad_group_asset_set_service.MutateAdGroupAssetSetsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_group_asset_set_service.AdGroupAssetSetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_asset_set_service.MutateAdGroupAssetSetsResponse: + r"""Creates, or removes ad group asset sets. Operation + statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAdGroupAssetSetsRequest, dict]]): + The request object. Request message for + [AdGroupAssetSetService.MutateAdGroupAssetSets][google.ads.googleads.v24.services.AdGroupAssetSetService.MutateAdGroupAssetSets]. + customer_id (:class:`str`): + Required. The ID of the customer + whose ad group asset sets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AdGroupAssetSetOperation]`): + Required. The list of operations to + perform on individual ad group asset + sets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupAssetSetsResponse: + Response message for an ad group + asset set mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_asset_set_service.MutateAdGroupAssetSetsRequest + ): + request = ad_group_asset_set_service.MutateAdGroupAssetSetsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_ad_group_asset_sets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AdGroupAssetSetServiceAsyncClient": + 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__ = ("AdGroupAssetSetServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_set_service/client.py b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/client.py new file mode 100644 index 000000000..0928343d4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/client.py @@ -0,0 +1,945 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ad_group_asset_set_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AdGroupAssetSetServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AdGroupAssetSetServiceGrpcTransport +from .transports.grpc_asyncio import AdGroupAssetSetServiceGrpcAsyncIOTransport + + +class AdGroupAssetSetServiceClientMeta(type): + """Metaclass for the AdGroupAssetSetService 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[AdGroupAssetSetServiceTransport]] + _transport_registry["grpc"] = AdGroupAssetSetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AdGroupAssetSetServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdGroupAssetSetServiceTransport]: + """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 AdGroupAssetSetServiceClient(metaclass=AdGroupAssetSetServiceClientMeta): + """Service to manage ad group asset set""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AdGroupAssetSetServiceClient: 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: + AdGroupAssetSetServiceClient: 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) -> AdGroupAssetSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupAssetSetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_group_path( + customer_id: str, + ad_group_id: str, + ) -> str: + """Returns a fully-qualified ad_group string.""" + return "customers/{customer_id}/adGroups/{ad_group_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ) + + @staticmethod + def parse_ad_group_path(path: str) -> Dict[str, str]: + """Parses a ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_asset_set_path( + customer_id: str, + ad_group_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified ad_group_asset_set string.""" + return "customers/{customer_id}/adGroupAssetSets/{ad_group_id}~{asset_set_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + asset_set_id=asset_set_id, + ) + + @staticmethod + def parse_ad_group_asset_set_path(path: str) -> Dict[str, str]: + """Parses a ad_group_asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAssetSets/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_set_path( + customer_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified asset_set string.""" + return "customers/{customer_id}/assetSets/{asset_set_id}".format( + customer_id=customer_id, + asset_set_id=asset_set_id, + ) + + @staticmethod + def parse_asset_set_path(path: str) -> Dict[str, str]: + """Parses a asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetSets/(?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 = ( + AdGroupAssetSetServiceClient._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 = ( + AdGroupAssetSetServiceClient._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 + ): + """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 = AdGroupAssetSetServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AdGroupAssetSetServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AdGroupAssetSetServiceClient._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 = AdGroupAssetSetServiceClient._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): + """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, + AdGroupAssetSetServiceTransport, + Callable[..., AdGroupAssetSetServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group asset set 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,AdGroupAssetSetServiceTransport,Callable[..., AdGroupAssetSetServiceTransport]]]): + 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 AdGroupAssetSetServiceTransport 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, + ) = AdGroupAssetSetServiceClient._read_environment_variables() + self._client_cert_source = ( + AdGroupAssetSetServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + AdGroupAssetSetServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AdGroupAssetSetServiceTransport + ) + if transport_provided: + # transport is a AdGroupAssetSetServiceTransport 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(AdGroupAssetSetServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AdGroupAssetSetServiceClient._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[AdGroupAssetSetServiceTransport], + Callable[..., AdGroupAssetSetServiceTransport], + ] = ( + AdGroupAssetSetServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AdGroupAssetSetServiceTransport], 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.ads.googleads.v24.services.AdGroupAssetSetServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupAssetSetService", + "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.ads.googleads.v24.services.AdGroupAssetSetService", + "credentialsType": None, + } + ), + ) + + def mutate_ad_group_asset_sets( + self, + request: Optional[ + Union[ + ad_group_asset_set_service.MutateAdGroupAssetSetsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_group_asset_set_service.AdGroupAssetSetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_asset_set_service.MutateAdGroupAssetSetsResponse: + r"""Creates, or removes ad group asset sets. Operation + statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAdGroupAssetSetsRequest, dict]): + The request object. Request message for + [AdGroupAssetSetService.MutateAdGroupAssetSets][google.ads.googleads.v24.services.AdGroupAssetSetService.MutateAdGroupAssetSets]. + customer_id (str): + Required. The ID of the customer + whose ad group asset sets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupAssetSetOperation]): + Required. The list of operations to + perform on individual ad group asset + sets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupAssetSetsResponse: + Response message for an ad group + asset set mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_asset_set_service.MutateAdGroupAssetSetsRequest + ): + request = ad_group_asset_set_service.MutateAdGroupAssetSetsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_ad_group_asset_sets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AdGroupAssetSetServiceClient": + 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() + + +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__ = ("AdGroupAssetSetServiceClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/README.rst b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/README.rst new file mode 100644 index 000000000..76b18aa98 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AdGroupAssetSetServiceTransport` is the ABC for all transports. +- public child `AdGroupAssetSetServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AdGroupAssetSetServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAdGroupAssetSetServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AdGroupAssetSetServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/__init__.py b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/__init__.py new file mode 100644 index 000000000..24d5b0a2c --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AdGroupAssetSetServiceTransport +from .grpc import AdGroupAssetSetServiceGrpcTransport +from .grpc_asyncio import AdGroupAssetSetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupAssetSetServiceTransport]] +_transport_registry["grpc"] = AdGroupAssetSetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AdGroupAssetSetServiceGrpcAsyncIOTransport + +__all__ = ( + "AdGroupAssetSetServiceTransport", + "AdGroupAssetSetServiceGrpcTransport", + "AdGroupAssetSetServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/base.py b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/base.py new file mode 100644 index 000000000..e104204cb --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ad_group_asset_set_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 AdGroupAssetSetServiceTransport(abc.ABC): + """Abstract transport class for AdGroupAssetSetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ad_group_asset_sets: gapic_v1.method.wrap_method( + self.mutate_ad_group_asset_sets, + 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 mutate_ad_group_asset_sets( + self, + ) -> Callable[ + [ad_group_asset_set_service.MutateAdGroupAssetSetsRequest], + Union[ + ad_group_asset_set_service.MutateAdGroupAssetSetsResponse, + Awaitable[ + ad_group_asset_set_service.MutateAdGroupAssetSetsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AdGroupAssetSetServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/grpc.py b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/grpc.py new file mode 100644 index 000000000..b83a298c2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/grpc.py @@ -0,0 +1,384 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_asset_set_service +from .base import AdGroupAssetSetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupAssetSetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupAssetSetService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupAssetSetServiceGrpcTransport(AdGroupAssetSetServiceTransport): + """gRPC backend transport for AdGroupAssetSetService. + + Service to manage ad group asset set + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_ad_group_asset_sets( + self, + ) -> Callable[ + [ad_group_asset_set_service.MutateAdGroupAssetSetsRequest], + ad_group_asset_set_service.MutateAdGroupAssetSetsResponse, + ]: + r"""Return a callable for the mutate ad group asset sets method over gRPC. + + Creates, or removes ad group asset sets. Operation + statuses are returned. + + Returns: + Callable[[~.MutateAdGroupAssetSetsRequest], + ~.MutateAdGroupAssetSetsResponse]: + 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 "mutate_ad_group_asset_sets" not in self._stubs: + self._stubs["mutate_ad_group_asset_sets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupAssetSetService/MutateAdGroupAssetSets", + request_serializer=ad_group_asset_set_service.MutateAdGroupAssetSetsRequest.serialize, + response_deserializer=ad_group_asset_set_service.MutateAdGroupAssetSetsResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_asset_sets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AdGroupAssetSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..9b3092a0f --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_asset_set_service/transports/grpc_asyncio.py @@ -0,0 +1,407 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_asset_set_service +from .base import AdGroupAssetSetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupAssetSetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupAssetSetService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupAssetSetServiceGrpcAsyncIOTransport( + AdGroupAssetSetServiceTransport +): + """gRPC AsyncIO backend transport for AdGroupAssetSetService. + + Service to manage ad group asset set + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_ad_group_asset_sets( + self, + ) -> Callable[ + [ad_group_asset_set_service.MutateAdGroupAssetSetsRequest], + Awaitable[ad_group_asset_set_service.MutateAdGroupAssetSetsResponse], + ]: + r"""Return a callable for the mutate ad group asset sets method over gRPC. + + Creates, or removes ad group asset sets. Operation + statuses are returned. + + Returns: + Callable[[~.MutateAdGroupAssetSetsRequest], + Awaitable[~.MutateAdGroupAssetSetsResponse]]: + 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 "mutate_ad_group_asset_sets" not in self._stubs: + self._stubs["mutate_ad_group_asset_sets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupAssetSetService/MutateAdGroupAssetSets", + request_serializer=ad_group_asset_set_service.MutateAdGroupAssetSetsRequest.serialize, + response_deserializer=ad_group_asset_set_service.MutateAdGroupAssetSetsResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_asset_sets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_ad_group_asset_sets: self._wrap_method( + self.mutate_ad_group_asset_sets, + 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" + + +__all__ = ("AdGroupAssetSetServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/__init__.py b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/__init__.py new file mode 100644 index 000000000..a08d3bd92 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AdGroupBidModifierServiceClient +from .async_client import AdGroupBidModifierServiceAsyncClient + +__all__ = ( + "AdGroupBidModifierServiceClient", + "AdGroupBidModifierServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/async_client.py b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/async_client.py new file mode 100644 index 000000000..1991c272b --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/async_client.py @@ -0,0 +1,451 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + ad_group_bid_modifier_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AdGroupBidModifierServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import AdGroupBidModifierServiceClient + +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 AdGroupBidModifierServiceAsyncClient: + """Service to manage ad group bid modifiers.""" + + _client: AdGroupBidModifierServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AdGroupBidModifierServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + AdGroupBidModifierServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + AdGroupBidModifierServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AdGroupBidModifierServiceClient._DEFAULT_UNIVERSE + + ad_group_path = staticmethod(AdGroupBidModifierServiceClient.ad_group_path) + parse_ad_group_path = staticmethod( + AdGroupBidModifierServiceClient.parse_ad_group_path + ) + ad_group_bid_modifier_path = staticmethod( + AdGroupBidModifierServiceClient.ad_group_bid_modifier_path + ) + parse_ad_group_bid_modifier_path = staticmethod( + AdGroupBidModifierServiceClient.parse_ad_group_bid_modifier_path + ) + common_billing_account_path = staticmethod( + AdGroupBidModifierServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AdGroupBidModifierServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AdGroupBidModifierServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AdGroupBidModifierServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AdGroupBidModifierServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AdGroupBidModifierServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AdGroupBidModifierServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AdGroupBidModifierServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AdGroupBidModifierServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AdGroupBidModifierServiceClient.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: + AdGroupBidModifierServiceAsyncClient: The constructed client. + """ + return AdGroupBidModifierServiceClient.from_service_account_info.__func__(AdGroupBidModifierServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AdGroupBidModifierServiceAsyncClient: The constructed client. + """ + return AdGroupBidModifierServiceClient.from_service_account_file.__func__(AdGroupBidModifierServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AdGroupBidModifierServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AdGroupBidModifierServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupBidModifierServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AdGroupBidModifierServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AdGroupBidModifierServiceTransport, + Callable[..., AdGroupBidModifierServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group bid modifier 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,AdGroupBidModifierServiceTransport,Callable[..., AdGroupBidModifierServiceTransport]]]): + 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 AdGroupBidModifierServiceTransport 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 = AdGroupBidModifierServiceClient( + 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.ads.googleads.v24.services.AdGroupBidModifierServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupBidModifierService", + "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.ads.googleads.v24.services.AdGroupBidModifierService", + "credentialsType": None, + } + ), + ) + + async def mutate_ad_group_bid_modifiers( + self, + request: Optional[ + Union[ + ad_group_bid_modifier_service.MutateAdGroupBidModifiersRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + ad_group_bid_modifier_service.AdGroupBidModifierOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_bid_modifier_service.MutateAdGroupBidModifiersResponse: + r"""Creates, updates, or removes ad group bid modifiers. Operation + statuses are returned. + + List of thrown errors: `AdGroupBidModifierError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `CriterionError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAdGroupBidModifiersRequest, dict]]): + The request object. Request message for + [AdGroupBidModifierService.MutateAdGroupBidModifiers][google.ads.googleads.v24.services.AdGroupBidModifierService.MutateAdGroupBidModifiers]. + customer_id (:class:`str`): + Required. ID of the customer whose ad + group bid modifiers are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AdGroupBidModifierOperation]`): + Required. The list of operations to + perform on individual ad group bid + modifiers. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupBidModifiersResponse: + Response message for ad group bid + modifiers mutate. + + """ + # 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 = [customer_id, operations] + 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, + ad_group_bid_modifier_service.MutateAdGroupBidModifiersRequest, + ): + request = ( + ad_group_bid_modifier_service.MutateAdGroupBidModifiersRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_ad_group_bid_modifiers + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AdGroupBidModifierServiceAsyncClient": + 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__ = ("AdGroupBidModifierServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/client.py b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/client.py new file mode 100644 index 000000000..bd8d165bb --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/client.py @@ -0,0 +1,949 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + ad_group_bid_modifier_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AdGroupBidModifierServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AdGroupBidModifierServiceGrpcTransport +from .transports.grpc_asyncio import ( + AdGroupBidModifierServiceGrpcAsyncIOTransport, +) + + +class AdGroupBidModifierServiceClientMeta(type): + """Metaclass for the AdGroupBidModifierService 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[AdGroupBidModifierServiceTransport]] + _transport_registry["grpc"] = AdGroupBidModifierServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AdGroupBidModifierServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdGroupBidModifierServiceTransport]: + """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 AdGroupBidModifierServiceClient( + metaclass=AdGroupBidModifierServiceClientMeta +): + """Service to manage ad group bid modifiers.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AdGroupBidModifierServiceClient: 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: + AdGroupBidModifierServiceClient: 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) -> AdGroupBidModifierServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupBidModifierServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_group_path( + customer_id: str, + ad_group_id: str, + ) -> str: + """Returns a fully-qualified ad_group string.""" + return "customers/{customer_id}/adGroups/{ad_group_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ) + + @staticmethod + def parse_ad_group_path(path: str) -> Dict[str, str]: + """Parses a ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_bid_modifier_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified ad_group_bid_modifier string.""" + return "customers/{customer_id}/adGroupBidModifiers/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_ad_group_bid_modifier_path(path: str) -> Dict[str, str]: + """Parses a ad_group_bid_modifier path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupBidModifiers/(?P.+?)~(?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 = ( + AdGroupBidModifierServiceClient._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 = ( + AdGroupBidModifierServiceClient._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 + ): + """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 = ( + AdGroupBidModifierServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AdGroupBidModifierServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = AdGroupBidModifierServiceClient._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 = AdGroupBidModifierServiceClient._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): + """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, + AdGroupBidModifierServiceTransport, + Callable[..., AdGroupBidModifierServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group bid modifier 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,AdGroupBidModifierServiceTransport,Callable[..., AdGroupBidModifierServiceTransport]]]): + 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 AdGroupBidModifierServiceTransport 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, + ) = AdGroupBidModifierServiceClient._read_environment_variables() + self._client_cert_source = ( + AdGroupBidModifierServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + AdGroupBidModifierServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AdGroupBidModifierServiceTransport + ) + if transport_provided: + # transport is a AdGroupBidModifierServiceTransport 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( + AdGroupBidModifierServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AdGroupBidModifierServiceClient._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[AdGroupBidModifierServiceTransport], + Callable[..., AdGroupBidModifierServiceTransport], + ] = ( + AdGroupBidModifierServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AdGroupBidModifierServiceTransport], 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.ads.googleads.v24.services.AdGroupBidModifierServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupBidModifierService", + "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.ads.googleads.v24.services.AdGroupBidModifierService", + "credentialsType": None, + } + ), + ) + + def mutate_ad_group_bid_modifiers( + self, + request: Optional[ + Union[ + ad_group_bid_modifier_service.MutateAdGroupBidModifiersRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + ad_group_bid_modifier_service.AdGroupBidModifierOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_bid_modifier_service.MutateAdGroupBidModifiersResponse: + r"""Creates, updates, or removes ad group bid modifiers. Operation + statuses are returned. + + List of thrown errors: `AdGroupBidModifierError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `CriterionError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAdGroupBidModifiersRequest, dict]): + The request object. Request message for + [AdGroupBidModifierService.MutateAdGroupBidModifiers][google.ads.googleads.v24.services.AdGroupBidModifierService.MutateAdGroupBidModifiers]. + customer_id (str): + Required. ID of the customer whose ad + group bid modifiers are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupBidModifierOperation]): + Required. The list of operations to + perform on individual ad group bid + modifiers. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupBidModifiersResponse: + Response message for ad group bid + modifiers mutate. + + """ + # 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 = [customer_id, operations] + 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, + ad_group_bid_modifier_service.MutateAdGroupBidModifiersRequest, + ): + request = ( + ad_group_bid_modifier_service.MutateAdGroupBidModifiersRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_ad_group_bid_modifiers + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AdGroupBidModifierServiceClient": + 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() + + +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__ = ("AdGroupBidModifierServiceClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/README.rst b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/README.rst new file mode 100644 index 000000000..b5e3ae6d8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AdGroupBidModifierServiceTransport` is the ABC for all transports. +- public child `AdGroupBidModifierServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AdGroupBidModifierServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAdGroupBidModifierServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AdGroupBidModifierServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/__init__.py b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/__init__.py new file mode 100644 index 000000000..781794d6e --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AdGroupBidModifierServiceTransport +from .grpc import AdGroupBidModifierServiceGrpcTransport +from .grpc_asyncio import AdGroupBidModifierServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupBidModifierServiceTransport]] +_transport_registry["grpc"] = AdGroupBidModifierServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + AdGroupBidModifierServiceGrpcAsyncIOTransport +) + +__all__ = ( + "AdGroupBidModifierServiceTransport", + "AdGroupBidModifierServiceGrpcTransport", + "AdGroupBidModifierServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/base.py b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/base.py new file mode 100644 index 000000000..cda70e7d9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + ad_group_bid_modifier_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 AdGroupBidModifierServiceTransport(abc.ABC): + """Abstract transport class for AdGroupBidModifierService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ad_group_bid_modifiers: gapic_v1.method.wrap_method( + self.mutate_ad_group_bid_modifiers, + 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 mutate_ad_group_bid_modifiers( + self, + ) -> Callable[ + [ad_group_bid_modifier_service.MutateAdGroupBidModifiersRequest], + Union[ + ad_group_bid_modifier_service.MutateAdGroupBidModifiersResponse, + Awaitable[ + ad_group_bid_modifier_service.MutateAdGroupBidModifiersResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AdGroupBidModifierServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/grpc.py b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/grpc.py new file mode 100644 index 000000000..f8fecda68 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/grpc.py @@ -0,0 +1,399 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + ad_group_bid_modifier_service, +) +from .base import AdGroupBidModifierServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupBidModifierService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupBidModifierService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupBidModifierServiceGrpcTransport( + AdGroupBidModifierServiceTransport +): + """gRPC backend transport for AdGroupBidModifierService. + + Service to manage ad group bid modifiers. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_ad_group_bid_modifiers( + self, + ) -> Callable[ + [ad_group_bid_modifier_service.MutateAdGroupBidModifiersRequest], + ad_group_bid_modifier_service.MutateAdGroupBidModifiersResponse, + ]: + r"""Return a callable for the mutate ad group bid modifiers method over gRPC. + + Creates, updates, or removes ad group bid modifiers. Operation + statuses are returned. + + List of thrown errors: `AdGroupBidModifierError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `CriterionError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateAdGroupBidModifiersRequest], + ~.MutateAdGroupBidModifiersResponse]: + 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 "mutate_ad_group_bid_modifiers" not in self._stubs: + self._stubs["mutate_ad_group_bid_modifiers"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupBidModifierService/MutateAdGroupBidModifiers", + request_serializer=ad_group_bid_modifier_service.MutateAdGroupBidModifiersRequest.serialize, + response_deserializer=ad_group_bid_modifier_service.MutateAdGroupBidModifiersResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_bid_modifiers"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AdGroupBidModifierServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..e6e29cb9d --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_bid_modifier_service/transports/grpc_asyncio.py @@ -0,0 +1,422 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + ad_group_bid_modifier_service, +) +from .base import AdGroupBidModifierServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupBidModifierService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupBidModifierService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupBidModifierServiceGrpcAsyncIOTransport( + AdGroupBidModifierServiceTransport +): + """gRPC AsyncIO backend transport for AdGroupBidModifierService. + + Service to manage ad group bid modifiers. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_ad_group_bid_modifiers( + self, + ) -> Callable[ + [ad_group_bid_modifier_service.MutateAdGroupBidModifiersRequest], + Awaitable[ + ad_group_bid_modifier_service.MutateAdGroupBidModifiersResponse + ], + ]: + r"""Return a callable for the mutate ad group bid modifiers method over gRPC. + + Creates, updates, or removes ad group bid modifiers. Operation + statuses are returned. + + List of thrown errors: `AdGroupBidModifierError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `CriterionError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateAdGroupBidModifiersRequest], + Awaitable[~.MutateAdGroupBidModifiersResponse]]: + 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 "mutate_ad_group_bid_modifiers" not in self._stubs: + self._stubs["mutate_ad_group_bid_modifiers"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupBidModifierService/MutateAdGroupBidModifiers", + request_serializer=ad_group_bid_modifier_service.MutateAdGroupBidModifiersRequest.serialize, + response_deserializer=ad_group_bid_modifier_service.MutateAdGroupBidModifiersResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_bid_modifiers"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_ad_group_bid_modifiers: self._wrap_method( + self.mutate_ad_group_bid_modifiers, + 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" + + +__all__ = ("AdGroupBidModifierServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/__init__.py b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/__init__.py new file mode 100644 index 000000000..698fead75 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AdGroupCriterionCustomizerServiceClient +from .async_client import AdGroupCriterionCustomizerServiceAsyncClient + +__all__ = ( + "AdGroupCriterionCustomizerServiceClient", + "AdGroupCriterionCustomizerServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/async_client.py b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/async_client.py new file mode 100644 index 000000000..76be9cd81 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/async_client.py @@ -0,0 +1,455 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + ad_group_criterion_customizer_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AdGroupCriterionCustomizerServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import AdGroupCriterionCustomizerServiceClient + +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 AdGroupCriterionCustomizerServiceAsyncClient: + """Service to manage ad group criterion customizer""" + + _client: AdGroupCriterionCustomizerServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AdGroupCriterionCustomizerServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + AdGroupCriterionCustomizerServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + AdGroupCriterionCustomizerServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ( + AdGroupCriterionCustomizerServiceClient._DEFAULT_UNIVERSE + ) + + ad_group_criterion_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.ad_group_criterion_path + ) + parse_ad_group_criterion_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.parse_ad_group_criterion_path + ) + ad_group_criterion_customizer_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.ad_group_criterion_customizer_path + ) + parse_ad_group_criterion_customizer_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.parse_ad_group_criterion_customizer_path + ) + customizer_attribute_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.customizer_attribute_path + ) + parse_customizer_attribute_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.parse_customizer_attribute_path + ) + common_billing_account_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AdGroupCriterionCustomizerServiceClient.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: + AdGroupCriterionCustomizerServiceAsyncClient: The constructed client. + """ + return AdGroupCriterionCustomizerServiceClient.from_service_account_info.__func__(AdGroupCriterionCustomizerServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AdGroupCriterionCustomizerServiceAsyncClient: The constructed client. + """ + return AdGroupCriterionCustomizerServiceClient.from_service_account_file.__func__(AdGroupCriterionCustomizerServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AdGroupCriterionCustomizerServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AdGroupCriterionCustomizerServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupCriterionCustomizerServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + AdGroupCriterionCustomizerServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AdGroupCriterionCustomizerServiceTransport, + Callable[..., AdGroupCriterionCustomizerServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group criterion customizer 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,AdGroupCriterionCustomizerServiceTransport,Callable[..., AdGroupCriterionCustomizerServiceTransport]]]): + 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 AdGroupCriterionCustomizerServiceTransport 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 = AdGroupCriterionCustomizerServiceClient( + 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.ads.googleads.v24.services.AdGroupCriterionCustomizerServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupCriterionCustomizerService", + "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.ads.googleads.v24.services.AdGroupCriterionCustomizerService", + "credentialsType": None, + } + ), + ) + + async def mutate_ad_group_criterion_customizers( + self, + request: Optional[ + Union[ + ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + ad_group_criterion_customizer_service.AdGroupCriterionCustomizerOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersResponse + ): + r"""Creates, updates or removes ad group criterion + customizers. Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAdGroupCriterionCustomizersRequest, dict]]): + The request object. Request message for + [AdGroupCriterionCustomizerService.MutateAdGroupCriterionCustomizers][google.ads.googleads.v24.services.AdGroupCriterionCustomizerService.MutateAdGroupCriterionCustomizers]. + customer_id (:class:`str`): + Required. The ID of the customer + whose ad group criterion customizers are + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AdGroupCriterionCustomizerOperation]`): + Required. The list of operations to + perform on individual ad group criterion + customizers. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupCriterionCustomizersResponse: + Response message for an ad group + criterion customizer mutate. + + """ + # 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 = [customer_id, operations] + 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, + ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersRequest, + ): + request = ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_ad_group_criterion_customizers + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__( + self, + ) -> "AdGroupCriterionCustomizerServiceAsyncClient": + 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__ = ("AdGroupCriterionCustomizerServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/client.py b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/client.py new file mode 100644 index 000000000..17f304074 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/client.py @@ -0,0 +1,972 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + ad_group_criterion_customizer_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AdGroupCriterionCustomizerServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AdGroupCriterionCustomizerServiceGrpcTransport +from .transports.grpc_asyncio import ( + AdGroupCriterionCustomizerServiceGrpcAsyncIOTransport, +) + + +class AdGroupCriterionCustomizerServiceClientMeta(type): + """Metaclass for the AdGroupCriterionCustomizerService 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[AdGroupCriterionCustomizerServiceTransport]] + _transport_registry["grpc"] = AdGroupCriterionCustomizerServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AdGroupCriterionCustomizerServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdGroupCriterionCustomizerServiceTransport]: + """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 AdGroupCriterionCustomizerServiceClient( + metaclass=AdGroupCriterionCustomizerServiceClientMeta +): + """Service to manage ad group criterion customizer""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AdGroupCriterionCustomizerServiceClient: 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: + AdGroupCriterionCustomizerServiceClient: 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) -> AdGroupCriterionCustomizerServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupCriterionCustomizerServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_group_criterion_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified ad_group_criterion string.""" + return "customers/{customer_id}/adGroupCriteria/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_ad_group_criterion_path(path: str) -> Dict[str, str]: + """Parses a ad_group_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCriteria/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_criterion_customizer_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified ad_group_criterion_customizer string.""" + return "customers/{customer_id}/adGroupCriterionCustomizers/{ad_group_id}~{criterion_id}~{customizer_attribute_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_ad_group_criterion_customizer_path(path: str) -> Dict[str, str]: + """Parses a ad_group_criterion_customizer path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCriterionCustomizers/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customizer_attribute_path( + customer_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified customizer_attribute string.""" + return "customers/{customer_id}/customizerAttributes/{customizer_attribute_id}".format( + customer_id=customer_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_customizer_attribute_path(path: str) -> Dict[str, str]: + """Parses a customizer_attribute path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customizerAttributes/(?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 = ( + AdGroupCriterionCustomizerServiceClient._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 = ( + AdGroupCriterionCustomizerServiceClient._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 + ): + """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 = ( + AdGroupCriterionCustomizerServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + AdGroupCriterionCustomizerServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = AdGroupCriterionCustomizerServiceClient._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 = ( + AdGroupCriterionCustomizerServiceClient._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): + """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, + AdGroupCriterionCustomizerServiceTransport, + Callable[..., AdGroupCriterionCustomizerServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group criterion customizer 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,AdGroupCriterionCustomizerServiceTransport,Callable[..., AdGroupCriterionCustomizerServiceTransport]]]): + 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 AdGroupCriterionCustomizerServiceTransport 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, + ) = ( + AdGroupCriterionCustomizerServiceClient._read_environment_variables() + ) + self._client_cert_source = ( + AdGroupCriterionCustomizerServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + AdGroupCriterionCustomizerServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AdGroupCriterionCustomizerServiceTransport + ) + if transport_provided: + # transport is a AdGroupCriterionCustomizerServiceTransport 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( + AdGroupCriterionCustomizerServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AdGroupCriterionCustomizerServiceClient._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[AdGroupCriterionCustomizerServiceTransport], + Callable[..., AdGroupCriterionCustomizerServiceTransport], + ] = ( + AdGroupCriterionCustomizerServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AdGroupCriterionCustomizerServiceTransport], + 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.ads.googleads.v24.services.AdGroupCriterionCustomizerServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupCriterionCustomizerService", + "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.ads.googleads.v24.services.AdGroupCriterionCustomizerService", + "credentialsType": None, + } + ), + ) + + def mutate_ad_group_criterion_customizers( + self, + request: Optional[ + Union[ + ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + ad_group_criterion_customizer_service.AdGroupCriterionCustomizerOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersResponse + ): + r"""Creates, updates or removes ad group criterion + customizers. Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAdGroupCriterionCustomizersRequest, dict]): + The request object. Request message for + [AdGroupCriterionCustomizerService.MutateAdGroupCriterionCustomizers][google.ads.googleads.v24.services.AdGroupCriterionCustomizerService.MutateAdGroupCriterionCustomizers]. + customer_id (str): + Required. The ID of the customer + whose ad group criterion customizers are + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupCriterionCustomizerOperation]): + Required. The list of operations to + perform on individual ad group criterion + customizers. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupCriterionCustomizersResponse: + Response message for an ad group + criterion customizer mutate. + + """ + # 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 = [customer_id, operations] + 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, + ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersRequest, + ): + request = ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_ad_group_criterion_customizers + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AdGroupCriterionCustomizerServiceClient": + 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() + + +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__ = ("AdGroupCriterionCustomizerServiceClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/README.rst b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/README.rst new file mode 100644 index 000000000..4987f1747 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AdGroupCriterionCustomizerServiceTransport` is the ABC for all transports. +- public child `AdGroupCriterionCustomizerServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AdGroupCriterionCustomizerServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAdGroupCriterionCustomizerServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AdGroupCriterionCustomizerServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/__init__.py b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/__init__.py new file mode 100644 index 000000000..be338016d --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AdGroupCriterionCustomizerServiceTransport +from .grpc import AdGroupCriterionCustomizerServiceGrpcTransport +from .grpc_asyncio import AdGroupCriterionCustomizerServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupCriterionCustomizerServiceTransport]] +_transport_registry["grpc"] = AdGroupCriterionCustomizerServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + AdGroupCriterionCustomizerServiceGrpcAsyncIOTransport +) + +__all__ = ( + "AdGroupCriterionCustomizerServiceTransport", + "AdGroupCriterionCustomizerServiceGrpcTransport", + "AdGroupCriterionCustomizerServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/base.py b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/base.py new file mode 100644 index 000000000..ad3a2a5ed --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + ad_group_criterion_customizer_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 AdGroupCriterionCustomizerServiceTransport(abc.ABC): + """Abstract transport class for AdGroupCriterionCustomizerService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ad_group_criterion_customizers: gapic_v1.method.wrap_method( + self.mutate_ad_group_criterion_customizers, + 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 mutate_ad_group_criterion_customizers( + self, + ) -> Callable[ + [ + ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersRequest + ], + Union[ + ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersResponse, + Awaitable[ + ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AdGroupCriterionCustomizerServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/grpc.py b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/grpc.py new file mode 100644 index 000000000..0455fb214 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/grpc.py @@ -0,0 +1,394 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + ad_group_criterion_customizer_service, +) +from .base import ( + AdGroupCriterionCustomizerServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupCriterionCustomizerService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupCriterionCustomizerService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupCriterionCustomizerServiceGrpcTransport( + AdGroupCriterionCustomizerServiceTransport +): + """gRPC backend transport for AdGroupCriterionCustomizerService. + + Service to manage ad group criterion customizer + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_ad_group_criterion_customizers( + self, + ) -> Callable[ + [ + ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersRequest + ], + ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersResponse, + ]: + r"""Return a callable for the mutate ad group criterion + customizers method over gRPC. + + Creates, updates or removes ad group criterion + customizers. Operation statuses are returned. + + Returns: + Callable[[~.MutateAdGroupCriterionCustomizersRequest], + ~.MutateAdGroupCriterionCustomizersResponse]: + 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 "mutate_ad_group_criterion_customizers" not in self._stubs: + self._stubs["mutate_ad_group_criterion_customizers"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupCriterionCustomizerService/MutateAdGroupCriterionCustomizers", + request_serializer=ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersRequest.serialize, + response_deserializer=ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_criterion_customizers"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AdGroupCriterionCustomizerServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..26040e703 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_customizer_service/transports/grpc_asyncio.py @@ -0,0 +1,417 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + ad_group_criterion_customizer_service, +) +from .base import ( + AdGroupCriterionCustomizerServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupCriterionCustomizerService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupCriterionCustomizerService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupCriterionCustomizerServiceGrpcAsyncIOTransport( + AdGroupCriterionCustomizerServiceTransport +): + """gRPC AsyncIO backend transport for AdGroupCriterionCustomizerService. + + Service to manage ad group criterion customizer + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_ad_group_criterion_customizers( + self, + ) -> Callable[ + [ + ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersRequest + ], + Awaitable[ + ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersResponse + ], + ]: + r"""Return a callable for the mutate ad group criterion + customizers method over gRPC. + + Creates, updates or removes ad group criterion + customizers. Operation statuses are returned. + + Returns: + Callable[[~.MutateAdGroupCriterionCustomizersRequest], + Awaitable[~.MutateAdGroupCriterionCustomizersResponse]]: + 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 "mutate_ad_group_criterion_customizers" not in self._stubs: + self._stubs["mutate_ad_group_criterion_customizers"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupCriterionCustomizerService/MutateAdGroupCriterionCustomizers", + request_serializer=ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersRequest.serialize, + response_deserializer=ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_criterion_customizers"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_ad_group_criterion_customizers: self._wrap_method( + self.mutate_ad_group_criterion_customizers, + 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" + + +__all__ = ("AdGroupCriterionCustomizerServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/__init__.py b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/__init__.py new file mode 100644 index 000000000..2a1a74b3d --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AdGroupCriterionLabelServiceClient +from .async_client import AdGroupCriterionLabelServiceAsyncClient + +__all__ = ( + "AdGroupCriterionLabelServiceClient", + "AdGroupCriterionLabelServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/async_client.py b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/async_client.py new file mode 100644 index 000000000..169ed49cd --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/async_client.py @@ -0,0 +1,449 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + ad_group_criterion_label_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AdGroupCriterionLabelServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import AdGroupCriterionLabelServiceClient + +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 AdGroupCriterionLabelServiceAsyncClient: + """Service to manage labels on ad group criteria.""" + + _client: AdGroupCriterionLabelServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AdGroupCriterionLabelServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + AdGroupCriterionLabelServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + AdGroupCriterionLabelServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AdGroupCriterionLabelServiceClient._DEFAULT_UNIVERSE + + ad_group_criterion_path = staticmethod( + AdGroupCriterionLabelServiceClient.ad_group_criterion_path + ) + parse_ad_group_criterion_path = staticmethod( + AdGroupCriterionLabelServiceClient.parse_ad_group_criterion_path + ) + ad_group_criterion_label_path = staticmethod( + AdGroupCriterionLabelServiceClient.ad_group_criterion_label_path + ) + parse_ad_group_criterion_label_path = staticmethod( + AdGroupCriterionLabelServiceClient.parse_ad_group_criterion_label_path + ) + label_path = staticmethod(AdGroupCriterionLabelServiceClient.label_path) + parse_label_path = staticmethod( + AdGroupCriterionLabelServiceClient.parse_label_path + ) + common_billing_account_path = staticmethod( + AdGroupCriterionLabelServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AdGroupCriterionLabelServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AdGroupCriterionLabelServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AdGroupCriterionLabelServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AdGroupCriterionLabelServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AdGroupCriterionLabelServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AdGroupCriterionLabelServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AdGroupCriterionLabelServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AdGroupCriterionLabelServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AdGroupCriterionLabelServiceClient.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: + AdGroupCriterionLabelServiceAsyncClient: The constructed client. + """ + return AdGroupCriterionLabelServiceClient.from_service_account_info.__func__(AdGroupCriterionLabelServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AdGroupCriterionLabelServiceAsyncClient: The constructed client. + """ + return AdGroupCriterionLabelServiceClient.from_service_account_file.__func__(AdGroupCriterionLabelServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AdGroupCriterionLabelServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AdGroupCriterionLabelServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupCriterionLabelServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AdGroupCriterionLabelServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AdGroupCriterionLabelServiceTransport, + Callable[..., AdGroupCriterionLabelServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group criterion label 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,AdGroupCriterionLabelServiceTransport,Callable[..., AdGroupCriterionLabelServiceTransport]]]): + 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 AdGroupCriterionLabelServiceTransport 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 = AdGroupCriterionLabelServiceClient( + 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.ads.googleads.v24.services.AdGroupCriterionLabelServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupCriterionLabelService", + "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.ads.googleads.v24.services.AdGroupCriterionLabelService", + "credentialsType": None, + } + ), + ) + + async def mutate_ad_group_criterion_labels( + self, + request: Optional[ + Union[ + ad_group_criterion_label_service.MutateAdGroupCriterionLabelsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + ad_group_criterion_label_service.AdGroupCriterionLabelOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_criterion_label_service.MutateAdGroupCriterionLabelsResponse: + r"""Creates and removes ad group criterion labels. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAdGroupCriterionLabelsRequest, dict]]): + The request object. Request message for + [AdGroupCriterionLabelService.MutateAdGroupCriterionLabels][google.ads.googleads.v24.services.AdGroupCriterionLabelService.MutateAdGroupCriterionLabels]. + customer_id (:class:`str`): + Required. ID of the customer whose ad + group criterion labels are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AdGroupCriterionLabelOperation]`): + Required. The list of operations to + perform on ad group criterion labels. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupCriterionLabelsResponse: + Response message for an ad group + criterion labels mutate. + + """ + # 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 = [customer_id, operations] + 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, + ad_group_criterion_label_service.MutateAdGroupCriterionLabelsRequest, + ): + request = ad_group_criterion_label_service.MutateAdGroupCriterionLabelsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_ad_group_criterion_labels + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AdGroupCriterionLabelServiceAsyncClient": + 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__ = ("AdGroupCriterionLabelServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/client.py b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/client.py new file mode 100644 index 000000000..8ba889db0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/client.py @@ -0,0 +1,969 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + ad_group_criterion_label_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AdGroupCriterionLabelServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AdGroupCriterionLabelServiceGrpcTransport +from .transports.grpc_asyncio import ( + AdGroupCriterionLabelServiceGrpcAsyncIOTransport, +) + + +class AdGroupCriterionLabelServiceClientMeta(type): + """Metaclass for the AdGroupCriterionLabelService 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[AdGroupCriterionLabelServiceTransport]] + _transport_registry["grpc"] = AdGroupCriterionLabelServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AdGroupCriterionLabelServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdGroupCriterionLabelServiceTransport]: + """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 AdGroupCriterionLabelServiceClient( + metaclass=AdGroupCriterionLabelServiceClientMeta +): + """Service to manage labels on ad group criteria.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AdGroupCriterionLabelServiceClient: 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: + AdGroupCriterionLabelServiceClient: 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) -> AdGroupCriterionLabelServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupCriterionLabelServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_group_criterion_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified ad_group_criterion string.""" + return "customers/{customer_id}/adGroupCriteria/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_ad_group_criterion_path(path: str) -> Dict[str, str]: + """Parses a ad_group_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCriteria/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_criterion_label_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified ad_group_criterion_label string.""" + return "customers/{customer_id}/adGroupCriterionLabels/{ad_group_id}~{criterion_id}~{label_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + label_id=label_id, + ) + + @staticmethod + def parse_ad_group_criterion_label_path(path: str) -> Dict[str, str]: + """Parses a ad_group_criterion_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCriterionLabels/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def label_path( + customer_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified label string.""" + return "customers/{customer_id}/labels/{label_id}".format( + customer_id=customer_id, + label_id=label_id, + ) + + @staticmethod + def parse_label_path(path: str) -> Dict[str, str]: + """Parses a label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/labels/(?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 = ( + AdGroupCriterionLabelServiceClient._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 = ( + AdGroupCriterionLabelServiceClient._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 + ): + """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 = ( + AdGroupCriterionLabelServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + AdGroupCriterionLabelServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = AdGroupCriterionLabelServiceClient._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 = AdGroupCriterionLabelServiceClient._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): + """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, + AdGroupCriterionLabelServiceTransport, + Callable[..., AdGroupCriterionLabelServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group criterion label 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,AdGroupCriterionLabelServiceTransport,Callable[..., AdGroupCriterionLabelServiceTransport]]]): + 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 AdGroupCriterionLabelServiceTransport 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, + ) = AdGroupCriterionLabelServiceClient._read_environment_variables() + self._client_cert_source = ( + AdGroupCriterionLabelServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + AdGroupCriterionLabelServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AdGroupCriterionLabelServiceTransport + ) + if transport_provided: + # transport is a AdGroupCriterionLabelServiceTransport 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( + AdGroupCriterionLabelServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AdGroupCriterionLabelServiceClient._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[AdGroupCriterionLabelServiceTransport], + Callable[..., AdGroupCriterionLabelServiceTransport], + ] = ( + AdGroupCriterionLabelServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AdGroupCriterionLabelServiceTransport], + 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.ads.googleads.v24.services.AdGroupCriterionLabelServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupCriterionLabelService", + "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.ads.googleads.v24.services.AdGroupCriterionLabelService", + "credentialsType": None, + } + ), + ) + + def mutate_ad_group_criterion_labels( + self, + request: Optional[ + Union[ + ad_group_criterion_label_service.MutateAdGroupCriterionLabelsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + ad_group_criterion_label_service.AdGroupCriterionLabelOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_criterion_label_service.MutateAdGroupCriterionLabelsResponse: + r"""Creates and removes ad group criterion labels. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAdGroupCriterionLabelsRequest, dict]): + The request object. Request message for + [AdGroupCriterionLabelService.MutateAdGroupCriterionLabels][google.ads.googleads.v24.services.AdGroupCriterionLabelService.MutateAdGroupCriterionLabels]. + customer_id (str): + Required. ID of the customer whose ad + group criterion labels are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupCriterionLabelOperation]): + Required. The list of operations to + perform on ad group criterion labels. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupCriterionLabelsResponse: + Response message for an ad group + criterion labels mutate. + + """ + # 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 = [customer_id, operations] + 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, + ad_group_criterion_label_service.MutateAdGroupCriterionLabelsRequest, + ): + request = ad_group_criterion_label_service.MutateAdGroupCriterionLabelsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_ad_group_criterion_labels + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AdGroupCriterionLabelServiceClient": + 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() + + +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__ = ("AdGroupCriterionLabelServiceClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/README.rst b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/README.rst new file mode 100644 index 000000000..3691411c0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AdGroupCriterionLabelServiceTransport` is the ABC for all transports. +- public child `AdGroupCriterionLabelServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AdGroupCriterionLabelServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAdGroupCriterionLabelServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AdGroupCriterionLabelServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/__init__.py b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/__init__.py new file mode 100644 index 000000000..879eeb971 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AdGroupCriterionLabelServiceTransport +from .grpc import AdGroupCriterionLabelServiceGrpcTransport +from .grpc_asyncio import AdGroupCriterionLabelServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupCriterionLabelServiceTransport]] +_transport_registry["grpc"] = AdGroupCriterionLabelServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + AdGroupCriterionLabelServiceGrpcAsyncIOTransport +) + +__all__ = ( + "AdGroupCriterionLabelServiceTransport", + "AdGroupCriterionLabelServiceGrpcTransport", + "AdGroupCriterionLabelServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/base.py b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/base.py new file mode 100644 index 000000000..82eb4d3cb --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + ad_group_criterion_label_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 AdGroupCriterionLabelServiceTransport(abc.ABC): + """Abstract transport class for AdGroupCriterionLabelService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ad_group_criterion_labels: gapic_v1.method.wrap_method( + self.mutate_ad_group_criterion_labels, + 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 mutate_ad_group_criterion_labels( + self, + ) -> Callable[ + [ad_group_criterion_label_service.MutateAdGroupCriterionLabelsRequest], + Union[ + ad_group_criterion_label_service.MutateAdGroupCriterionLabelsResponse, + Awaitable[ + ad_group_criterion_label_service.MutateAdGroupCriterionLabelsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AdGroupCriterionLabelServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/grpc.py b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/grpc.py new file mode 100644 index 000000000..2b2c5147d --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/grpc.py @@ -0,0 +1,394 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + ad_group_criterion_label_service, +) +from .base import AdGroupCriterionLabelServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupCriterionLabelService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupCriterionLabelService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupCriterionLabelServiceGrpcTransport( + AdGroupCriterionLabelServiceTransport +): + """gRPC backend transport for AdGroupCriterionLabelService. + + Service to manage labels on ad group criteria. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_ad_group_criterion_labels( + self, + ) -> Callable[ + [ad_group_criterion_label_service.MutateAdGroupCriterionLabelsRequest], + ad_group_criterion_label_service.MutateAdGroupCriterionLabelsResponse, + ]: + r"""Return a callable for the mutate ad group criterion + labels method over gRPC. + + Creates and removes ad group criterion labels. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateAdGroupCriterionLabelsRequest], + ~.MutateAdGroupCriterionLabelsResponse]: + 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 "mutate_ad_group_criterion_labels" not in self._stubs: + self._stubs["mutate_ad_group_criterion_labels"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupCriterionLabelService/MutateAdGroupCriterionLabels", + request_serializer=ad_group_criterion_label_service.MutateAdGroupCriterionLabelsRequest.serialize, + response_deserializer=ad_group_criterion_label_service.MutateAdGroupCriterionLabelsResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_criterion_labels"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AdGroupCriterionLabelServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..9416f5fe8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_label_service/transports/grpc_asyncio.py @@ -0,0 +1,417 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + ad_group_criterion_label_service, +) +from .base import AdGroupCriterionLabelServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupCriterionLabelService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupCriterionLabelService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupCriterionLabelServiceGrpcAsyncIOTransport( + AdGroupCriterionLabelServiceTransport +): + """gRPC AsyncIO backend transport for AdGroupCriterionLabelService. + + Service to manage labels on ad group criteria. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_ad_group_criterion_labels( + self, + ) -> Callable[ + [ad_group_criterion_label_service.MutateAdGroupCriterionLabelsRequest], + Awaitable[ + ad_group_criterion_label_service.MutateAdGroupCriterionLabelsResponse + ], + ]: + r"""Return a callable for the mutate ad group criterion + labels method over gRPC. + + Creates and removes ad group criterion labels. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateAdGroupCriterionLabelsRequest], + Awaitable[~.MutateAdGroupCriterionLabelsResponse]]: + 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 "mutate_ad_group_criterion_labels" not in self._stubs: + self._stubs["mutate_ad_group_criterion_labels"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupCriterionLabelService/MutateAdGroupCriterionLabels", + request_serializer=ad_group_criterion_label_service.MutateAdGroupCriterionLabelsRequest.serialize, + response_deserializer=ad_group_criterion_label_service.MutateAdGroupCriterionLabelsResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_criterion_labels"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_ad_group_criterion_labels: self._wrap_method( + self.mutate_ad_group_criterion_labels, + 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" + + +__all__ = ("AdGroupCriterionLabelServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_service/__init__.py b/google/ads/googleads/v24/services/services/ad_group_criterion_service/__init__.py new file mode 100644 index 000000000..1932fae30 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AdGroupCriterionServiceClient +from .async_client import AdGroupCriterionServiceAsyncClient + +__all__ = ( + "AdGroupCriterionServiceClient", + "AdGroupCriterionServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_service/async_client.py b/google/ads/googleads/v24/services/services/ad_group_criterion_service/async_client.py new file mode 100644 index 000000000..beb2d9b53 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_service/async_client.py @@ -0,0 +1,469 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ad_group_criterion_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AdGroupCriterionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import AdGroupCriterionServiceClient + +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 AdGroupCriterionServiceAsyncClient: + """Service to manage ad group criteria.""" + + _client: AdGroupCriterionServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AdGroupCriterionServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AdGroupCriterionServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AdGroupCriterionServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AdGroupCriterionServiceClient._DEFAULT_UNIVERSE + + ad_group_path = staticmethod(AdGroupCriterionServiceClient.ad_group_path) + parse_ad_group_path = staticmethod( + AdGroupCriterionServiceClient.parse_ad_group_path + ) + ad_group_criterion_path = staticmethod( + AdGroupCriterionServiceClient.ad_group_criterion_path + ) + parse_ad_group_criterion_path = staticmethod( + AdGroupCriterionServiceClient.parse_ad_group_criterion_path + ) + ad_group_criterion_label_path = staticmethod( + AdGroupCriterionServiceClient.ad_group_criterion_label_path + ) + parse_ad_group_criterion_label_path = staticmethod( + AdGroupCriterionServiceClient.parse_ad_group_criterion_label_path + ) + combined_audience_path = staticmethod( + AdGroupCriterionServiceClient.combined_audience_path + ) + parse_combined_audience_path = staticmethod( + AdGroupCriterionServiceClient.parse_combined_audience_path + ) + mobile_app_category_constant_path = staticmethod( + AdGroupCriterionServiceClient.mobile_app_category_constant_path + ) + parse_mobile_app_category_constant_path = staticmethod( + AdGroupCriterionServiceClient.parse_mobile_app_category_constant_path + ) + topic_constant_path = staticmethod( + AdGroupCriterionServiceClient.topic_constant_path + ) + parse_topic_constant_path = staticmethod( + AdGroupCriterionServiceClient.parse_topic_constant_path + ) + common_billing_account_path = staticmethod( + AdGroupCriterionServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AdGroupCriterionServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AdGroupCriterionServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AdGroupCriterionServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AdGroupCriterionServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AdGroupCriterionServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AdGroupCriterionServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AdGroupCriterionServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AdGroupCriterionServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AdGroupCriterionServiceClient.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: + AdGroupCriterionServiceAsyncClient: The constructed client. + """ + return AdGroupCriterionServiceClient.from_service_account_info.__func__(AdGroupCriterionServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AdGroupCriterionServiceAsyncClient: The constructed client. + """ + return AdGroupCriterionServiceClient.from_service_account_file.__func__(AdGroupCriterionServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AdGroupCriterionServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AdGroupCriterionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupCriterionServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AdGroupCriterionServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AdGroupCriterionServiceTransport, + Callable[..., AdGroupCriterionServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group criterion 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,AdGroupCriterionServiceTransport,Callable[..., AdGroupCriterionServiceTransport]]]): + 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 AdGroupCriterionServiceTransport 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 = AdGroupCriterionServiceClient( + 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.ads.googleads.v24.services.AdGroupCriterionServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupCriterionService", + "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.ads.googleads.v24.services.AdGroupCriterionService", + "credentialsType": None, + } + ), + ) + + async def mutate_ad_group_criteria( + self, + request: Optional[ + Union[ad_group_criterion_service.MutateAdGroupCriteriaRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + ad_group_criterion_service.AdGroupCriterionOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_criterion_service.MutateAdGroupCriteriaResponse: + r"""Creates, updates, or removes criteria. Operation statuses are + returned. + + List of thrown errors: `AdGroupCriterionError <>`__ + `AdxError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ `BiddingError <>`__ + `BiddingStrategyError <>`__ `CollectionSizeError <>`__ + `ContextError <>`__ `CriterionError <>`__ `DatabaseError <>`__ + `DateError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `MultiplierError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `PolicyViolationError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAdGroupCriteriaRequest, dict]]): + The request object. Request message for + [AdGroupCriterionService.MutateAdGroupCriteria][google.ads.googleads.v24.services.AdGroupCriterionService.MutateAdGroupCriteria]. + customer_id (:class:`str`): + Required. ID of the customer whose + criteria are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AdGroupCriterionOperation]`): + Required. The list of operations to + perform on individual criteria. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupCriteriaResponse: + Response message for an ad group + criterion mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_criterion_service.MutateAdGroupCriteriaRequest + ): + request = ad_group_criterion_service.MutateAdGroupCriteriaRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_ad_group_criteria + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AdGroupCriterionServiceAsyncClient": + 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__ = ("AdGroupCriterionServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_service/client.py b/google/ads/googleads/v24/services/services/ad_group_criterion_service/client.py new file mode 100644 index 000000000..56043e43a --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_service/client.py @@ -0,0 +1,1018 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ad_group_criterion_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AdGroupCriterionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AdGroupCriterionServiceGrpcTransport +from .transports.grpc_asyncio import AdGroupCriterionServiceGrpcAsyncIOTransport + + +class AdGroupCriterionServiceClientMeta(type): + """Metaclass for the AdGroupCriterionService 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[AdGroupCriterionServiceTransport]] + _transport_registry["grpc"] = AdGroupCriterionServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AdGroupCriterionServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdGroupCriterionServiceTransport]: + """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 AdGroupCriterionServiceClient( + metaclass=AdGroupCriterionServiceClientMeta +): + """Service to manage ad group criteria.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AdGroupCriterionServiceClient: 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: + AdGroupCriterionServiceClient: 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) -> AdGroupCriterionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupCriterionServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_group_path( + customer_id: str, + ad_group_id: str, + ) -> str: + """Returns a fully-qualified ad_group string.""" + return "customers/{customer_id}/adGroups/{ad_group_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ) + + @staticmethod + def parse_ad_group_path(path: str) -> Dict[str, str]: + """Parses a ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_criterion_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified ad_group_criterion string.""" + return "customers/{customer_id}/adGroupCriteria/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_ad_group_criterion_path(path: str) -> Dict[str, str]: + """Parses a ad_group_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCriteria/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_criterion_label_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified ad_group_criterion_label string.""" + return "customers/{customer_id}/adGroupCriterionLabels/{ad_group_id}~{criterion_id}~{label_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + label_id=label_id, + ) + + @staticmethod + def parse_ad_group_criterion_label_path(path: str) -> Dict[str, str]: + """Parses a ad_group_criterion_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCriterionLabels/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def combined_audience_path( + customer_id: str, + combined_audience_id: str, + ) -> str: + """Returns a fully-qualified combined_audience string.""" + return "customers/{customer_id}/combinedAudiences/{combined_audience_id}".format( + customer_id=customer_id, + combined_audience_id=combined_audience_id, + ) + + @staticmethod + def parse_combined_audience_path(path: str) -> Dict[str, str]: + """Parses a combined_audience path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/combinedAudiences/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def mobile_app_category_constant_path( + mobile_app_category_id: str, + ) -> str: + """Returns a fully-qualified mobile_app_category_constant string.""" + return "mobileAppCategoryConstants/{mobile_app_category_id}".format( + mobile_app_category_id=mobile_app_category_id, + ) + + @staticmethod + def parse_mobile_app_category_constant_path(path: str) -> Dict[str, str]: + """Parses a mobile_app_category_constant path into its component segments.""" + m = re.match( + r"^mobileAppCategoryConstants/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def topic_constant_path( + topic_id: str, + ) -> str: + """Returns a fully-qualified topic_constant string.""" + return "topicConstants/{topic_id}".format( + topic_id=topic_id, + ) + + @staticmethod + def parse_topic_constant_path(path: str) -> Dict[str, str]: + """Parses a topic_constant path into its component segments.""" + m = re.match(r"^topicConstants/(?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 = ( + AdGroupCriterionServiceClient._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 = ( + AdGroupCriterionServiceClient._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 + ): + """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 = AdGroupCriterionServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AdGroupCriterionServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AdGroupCriterionServiceClient._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 = AdGroupCriterionServiceClient._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): + """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, + AdGroupCriterionServiceTransport, + Callable[..., AdGroupCriterionServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group criterion 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,AdGroupCriterionServiceTransport,Callable[..., AdGroupCriterionServiceTransport]]]): + 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 AdGroupCriterionServiceTransport 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, + ) = AdGroupCriterionServiceClient._read_environment_variables() + self._client_cert_source = ( + AdGroupCriterionServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + AdGroupCriterionServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AdGroupCriterionServiceTransport + ) + if transport_provided: + # transport is a AdGroupCriterionServiceTransport 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(AdGroupCriterionServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AdGroupCriterionServiceClient._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[AdGroupCriterionServiceTransport], + Callable[..., AdGroupCriterionServiceTransport], + ] = ( + AdGroupCriterionServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AdGroupCriterionServiceTransport], 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.ads.googleads.v24.services.AdGroupCriterionServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupCriterionService", + "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.ads.googleads.v24.services.AdGroupCriterionService", + "credentialsType": None, + } + ), + ) + + def mutate_ad_group_criteria( + self, + request: Optional[ + Union[ad_group_criterion_service.MutateAdGroupCriteriaRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + ad_group_criterion_service.AdGroupCriterionOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_criterion_service.MutateAdGroupCriteriaResponse: + r"""Creates, updates, or removes criteria. Operation statuses are + returned. + + List of thrown errors: `AdGroupCriterionError <>`__ + `AdxError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ `BiddingError <>`__ + `BiddingStrategyError <>`__ `CollectionSizeError <>`__ + `ContextError <>`__ `CriterionError <>`__ `DatabaseError <>`__ + `DateError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `MultiplierError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `PolicyViolationError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAdGroupCriteriaRequest, dict]): + The request object. Request message for + [AdGroupCriterionService.MutateAdGroupCriteria][google.ads.googleads.v24.services.AdGroupCriterionService.MutateAdGroupCriteria]. + customer_id (str): + Required. ID of the customer whose + criteria are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupCriterionOperation]): + Required. The list of operations to + perform on individual criteria. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupCriteriaResponse: + Response message for an ad group + criterion mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_criterion_service.MutateAdGroupCriteriaRequest + ): + request = ad_group_criterion_service.MutateAdGroupCriteriaRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_ad_group_criteria + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AdGroupCriterionServiceClient": + 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() + + +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__ = ("AdGroupCriterionServiceClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/README.rst b/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/README.rst new file mode 100644 index 000000000..f9d616117 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AdGroupCriterionServiceTransport` is the ABC for all transports. +- public child `AdGroupCriterionServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AdGroupCriterionServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAdGroupCriterionServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AdGroupCriterionServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/__init__.py b/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/__init__.py new file mode 100644 index 000000000..a44d83a57 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AdGroupCriterionServiceTransport +from .grpc import AdGroupCriterionServiceGrpcTransport +from .grpc_asyncio import AdGroupCriterionServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupCriterionServiceTransport]] +_transport_registry["grpc"] = AdGroupCriterionServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + AdGroupCriterionServiceGrpcAsyncIOTransport +) + +__all__ = ( + "AdGroupCriterionServiceTransport", + "AdGroupCriterionServiceGrpcTransport", + "AdGroupCriterionServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/base.py b/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/base.py new file mode 100644 index 000000000..70f8746ca --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ad_group_criterion_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 AdGroupCriterionServiceTransport(abc.ABC): + """Abstract transport class for AdGroupCriterionService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ad_group_criteria: gapic_v1.method.wrap_method( + self.mutate_ad_group_criteria, + 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 mutate_ad_group_criteria( + self, + ) -> Callable[ + [ad_group_criterion_service.MutateAdGroupCriteriaRequest], + Union[ + ad_group_criterion_service.MutateAdGroupCriteriaResponse, + Awaitable[ad_group_criterion_service.MutateAdGroupCriteriaResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AdGroupCriterionServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/grpc.py b/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/grpc.py new file mode 100644 index 000000000..89cf075b5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/grpc.py @@ -0,0 +1,400 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_criterion_service +from .base import AdGroupCriterionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupCriterionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupCriterionService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupCriterionServiceGrpcTransport(AdGroupCriterionServiceTransport): + """gRPC backend transport for AdGroupCriterionService. + + Service to manage ad group criteria. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_ad_group_criteria( + self, + ) -> Callable[ + [ad_group_criterion_service.MutateAdGroupCriteriaRequest], + ad_group_criterion_service.MutateAdGroupCriteriaResponse, + ]: + r"""Return a callable for the mutate ad group criteria method over gRPC. + + Creates, updates, or removes criteria. Operation statuses are + returned. + + List of thrown errors: `AdGroupCriterionError <>`__ + `AdxError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ `BiddingError <>`__ + `BiddingStrategyError <>`__ `CollectionSizeError <>`__ + `ContextError <>`__ `CriterionError <>`__ `DatabaseError <>`__ + `DateError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `MultiplierError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `PolicyViolationError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateAdGroupCriteriaRequest], + ~.MutateAdGroupCriteriaResponse]: + 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 "mutate_ad_group_criteria" not in self._stubs: + self._stubs["mutate_ad_group_criteria"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupCriterionService/MutateAdGroupCriteria", + request_serializer=ad_group_criterion_service.MutateAdGroupCriteriaRequest.serialize, + response_deserializer=ad_group_criterion_service.MutateAdGroupCriteriaResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_criteria"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AdGroupCriterionServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..316b7839e --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_criterion_service/transports/grpc_asyncio.py @@ -0,0 +1,423 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_criterion_service +from .base import AdGroupCriterionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupCriterionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupCriterionService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupCriterionServiceGrpcAsyncIOTransport( + AdGroupCriterionServiceTransport +): + """gRPC AsyncIO backend transport for AdGroupCriterionService. + + Service to manage ad group criteria. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_ad_group_criteria( + self, + ) -> Callable[ + [ad_group_criterion_service.MutateAdGroupCriteriaRequest], + Awaitable[ad_group_criterion_service.MutateAdGroupCriteriaResponse], + ]: + r"""Return a callable for the mutate ad group criteria method over gRPC. + + Creates, updates, or removes criteria. Operation statuses are + returned. + + List of thrown errors: `AdGroupCriterionError <>`__ + `AdxError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ `BiddingError <>`__ + `BiddingStrategyError <>`__ `CollectionSizeError <>`__ + `ContextError <>`__ `CriterionError <>`__ `DatabaseError <>`__ + `DateError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `MultiplierError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `PolicyViolationError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateAdGroupCriteriaRequest], + Awaitable[~.MutateAdGroupCriteriaResponse]]: + 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 "mutate_ad_group_criteria" not in self._stubs: + self._stubs["mutate_ad_group_criteria"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupCriterionService/MutateAdGroupCriteria", + request_serializer=ad_group_criterion_service.MutateAdGroupCriteriaRequest.serialize, + response_deserializer=ad_group_criterion_service.MutateAdGroupCriteriaResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_criteria"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_ad_group_criteria: self._wrap_method( + self.mutate_ad_group_criteria, + 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" + + +__all__ = ("AdGroupCriterionServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_customizer_service/__init__.py b/google/ads/googleads/v24/services/services/ad_group_customizer_service/__init__.py new file mode 100644 index 000000000..13838eb40 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_customizer_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AdGroupCustomizerServiceClient +from .async_client import AdGroupCustomizerServiceAsyncClient + +__all__ = ( + "AdGroupCustomizerServiceClient", + "AdGroupCustomizerServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_customizer_service/async_client.py b/google/ads/googleads/v24/services/services/ad_group_customizer_service/async_client.py new file mode 100644 index 000000000..717fec963 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_customizer_service/async_client.py @@ -0,0 +1,442 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ad_group_customizer_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AdGroupCustomizerServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import AdGroupCustomizerServiceClient + +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 AdGroupCustomizerServiceAsyncClient: + """Service to manage ad group customizer""" + + _client: AdGroupCustomizerServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AdGroupCustomizerServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AdGroupCustomizerServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AdGroupCustomizerServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AdGroupCustomizerServiceClient._DEFAULT_UNIVERSE + + ad_group_path = staticmethod(AdGroupCustomizerServiceClient.ad_group_path) + parse_ad_group_path = staticmethod( + AdGroupCustomizerServiceClient.parse_ad_group_path + ) + ad_group_customizer_path = staticmethod( + AdGroupCustomizerServiceClient.ad_group_customizer_path + ) + parse_ad_group_customizer_path = staticmethod( + AdGroupCustomizerServiceClient.parse_ad_group_customizer_path + ) + customizer_attribute_path = staticmethod( + AdGroupCustomizerServiceClient.customizer_attribute_path + ) + parse_customizer_attribute_path = staticmethod( + AdGroupCustomizerServiceClient.parse_customizer_attribute_path + ) + common_billing_account_path = staticmethod( + AdGroupCustomizerServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AdGroupCustomizerServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AdGroupCustomizerServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AdGroupCustomizerServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AdGroupCustomizerServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AdGroupCustomizerServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AdGroupCustomizerServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AdGroupCustomizerServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AdGroupCustomizerServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AdGroupCustomizerServiceClient.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: + AdGroupCustomizerServiceAsyncClient: The constructed client. + """ + return AdGroupCustomizerServiceClient.from_service_account_info.__func__(AdGroupCustomizerServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AdGroupCustomizerServiceAsyncClient: The constructed client. + """ + return AdGroupCustomizerServiceClient.from_service_account_file.__func__(AdGroupCustomizerServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AdGroupCustomizerServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AdGroupCustomizerServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupCustomizerServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AdGroupCustomizerServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AdGroupCustomizerServiceTransport, + Callable[..., AdGroupCustomizerServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group customizer 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,AdGroupCustomizerServiceTransport,Callable[..., AdGroupCustomizerServiceTransport]]]): + 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 AdGroupCustomizerServiceTransport 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 = AdGroupCustomizerServiceClient( + 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.ads.googleads.v24.services.AdGroupCustomizerServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupCustomizerService", + "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.ads.googleads.v24.services.AdGroupCustomizerService", + "credentialsType": None, + } + ), + ) + + async def mutate_ad_group_customizers( + self, + request: Optional[ + Union[ + ad_group_customizer_service.MutateAdGroupCustomizersRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + ad_group_customizer_service.AdGroupCustomizerOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_customizer_service.MutateAdGroupCustomizersResponse: + r"""Creates, updates or removes ad group customizers. + Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAdGroupCustomizersRequest, dict]]): + The request object. Request message for + [AdGroupCustomizerService.MutateAdGroupCustomizers][google.ads.googleads.v24.services.AdGroupCustomizerService.MutateAdGroupCustomizers]. + customer_id (:class:`str`): + Required. The ID of the customer + whose ad group customizers are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AdGroupCustomizerOperation]`): + Required. The list of operations to + perform on individual ad group + customizers. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupCustomizersResponse: + Response message for an ad group + customizer mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_customizer_service.MutateAdGroupCustomizersRequest + ): + request = ( + ad_group_customizer_service.MutateAdGroupCustomizersRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_ad_group_customizers + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AdGroupCustomizerServiceAsyncClient": + 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__ = ("AdGroupCustomizerServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_customizer_service/client.py b/google/ads/googleads/v24/services/services/ad_group_customizer_service/client.py new file mode 100644 index 000000000..1fc141b01 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_customizer_service/client.py @@ -0,0 +1,952 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ad_group_customizer_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AdGroupCustomizerServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AdGroupCustomizerServiceGrpcTransport +from .transports.grpc_asyncio import ( + AdGroupCustomizerServiceGrpcAsyncIOTransport, +) + + +class AdGroupCustomizerServiceClientMeta(type): + """Metaclass for the AdGroupCustomizerService 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[AdGroupCustomizerServiceTransport]] + _transport_registry["grpc"] = AdGroupCustomizerServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AdGroupCustomizerServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdGroupCustomizerServiceTransport]: + """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 AdGroupCustomizerServiceClient( + metaclass=AdGroupCustomizerServiceClientMeta +): + """Service to manage ad group customizer""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AdGroupCustomizerServiceClient: 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: + AdGroupCustomizerServiceClient: 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) -> AdGroupCustomizerServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupCustomizerServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_group_path( + customer_id: str, + ad_group_id: str, + ) -> str: + """Returns a fully-qualified ad_group string.""" + return "customers/{customer_id}/adGroups/{ad_group_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ) + + @staticmethod + def parse_ad_group_path(path: str) -> Dict[str, str]: + """Parses a ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_customizer_path( + customer_id: str, + ad_group_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified ad_group_customizer string.""" + return "customers/{customer_id}/adGroupCustomizers/{ad_group_id}~{customizer_attribute_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_ad_group_customizer_path(path: str) -> Dict[str, str]: + """Parses a ad_group_customizer path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCustomizers/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customizer_attribute_path( + customer_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified customizer_attribute string.""" + return "customers/{customer_id}/customizerAttributes/{customizer_attribute_id}".format( + customer_id=customer_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_customizer_attribute_path(path: str) -> Dict[str, str]: + """Parses a customizer_attribute path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customizerAttributes/(?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 = ( + AdGroupCustomizerServiceClient._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 = ( + AdGroupCustomizerServiceClient._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 + ): + """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 = AdGroupCustomizerServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AdGroupCustomizerServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = AdGroupCustomizerServiceClient._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 = AdGroupCustomizerServiceClient._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): + """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, + AdGroupCustomizerServiceTransport, + Callable[..., AdGroupCustomizerServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group customizer 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,AdGroupCustomizerServiceTransport,Callable[..., AdGroupCustomizerServiceTransport]]]): + 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 AdGroupCustomizerServiceTransport 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, + ) = AdGroupCustomizerServiceClient._read_environment_variables() + self._client_cert_source = ( + AdGroupCustomizerServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + AdGroupCustomizerServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AdGroupCustomizerServiceTransport + ) + if transport_provided: + # transport is a AdGroupCustomizerServiceTransport 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(AdGroupCustomizerServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AdGroupCustomizerServiceClient._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[AdGroupCustomizerServiceTransport], + Callable[..., AdGroupCustomizerServiceTransport], + ] = ( + AdGroupCustomizerServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AdGroupCustomizerServiceTransport], 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.ads.googleads.v24.services.AdGroupCustomizerServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupCustomizerService", + "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.ads.googleads.v24.services.AdGroupCustomizerService", + "credentialsType": None, + } + ), + ) + + def mutate_ad_group_customizers( + self, + request: Optional[ + Union[ + ad_group_customizer_service.MutateAdGroupCustomizersRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + ad_group_customizer_service.AdGroupCustomizerOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_customizer_service.MutateAdGroupCustomizersResponse: + r"""Creates, updates or removes ad group customizers. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAdGroupCustomizersRequest, dict]): + The request object. Request message for + [AdGroupCustomizerService.MutateAdGroupCustomizers][google.ads.googleads.v24.services.AdGroupCustomizerService.MutateAdGroupCustomizers]. + customer_id (str): + Required. The ID of the customer + whose ad group customizers are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupCustomizerOperation]): + Required. The list of operations to + perform on individual ad group + customizers. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupCustomizersResponse: + Response message for an ad group + customizer mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_customizer_service.MutateAdGroupCustomizersRequest + ): + request = ( + ad_group_customizer_service.MutateAdGroupCustomizersRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_ad_group_customizers + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AdGroupCustomizerServiceClient": + 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() + + +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__ = ("AdGroupCustomizerServiceClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/README.rst b/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/README.rst new file mode 100644 index 000000000..be17a8416 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AdGroupCustomizerServiceTransport` is the ABC for all transports. +- public child `AdGroupCustomizerServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AdGroupCustomizerServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAdGroupCustomizerServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AdGroupCustomizerServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/__init__.py b/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/__init__.py new file mode 100644 index 000000000..247e24ccf --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AdGroupCustomizerServiceTransport +from .grpc import AdGroupCustomizerServiceGrpcTransport +from .grpc_asyncio import AdGroupCustomizerServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupCustomizerServiceTransport]] +_transport_registry["grpc"] = AdGroupCustomizerServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + AdGroupCustomizerServiceGrpcAsyncIOTransport +) + +__all__ = ( + "AdGroupCustomizerServiceTransport", + "AdGroupCustomizerServiceGrpcTransport", + "AdGroupCustomizerServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/base.py b/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/base.py new file mode 100644 index 000000000..9e426a7af --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ad_group_customizer_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 AdGroupCustomizerServiceTransport(abc.ABC): + """Abstract transport class for AdGroupCustomizerService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ad_group_customizers: gapic_v1.method.wrap_method( + self.mutate_ad_group_customizers, + 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 mutate_ad_group_customizers( + self, + ) -> Callable[ + [ad_group_customizer_service.MutateAdGroupCustomizersRequest], + Union[ + ad_group_customizer_service.MutateAdGroupCustomizersResponse, + Awaitable[ + ad_group_customizer_service.MutateAdGroupCustomizersResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AdGroupCustomizerServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/grpc.py b/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/grpc.py new file mode 100644 index 000000000..9253fc9ab --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/grpc.py @@ -0,0 +1,384 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_customizer_service +from .base import AdGroupCustomizerServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupCustomizerService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupCustomizerService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupCustomizerServiceGrpcTransport(AdGroupCustomizerServiceTransport): + """gRPC backend transport for AdGroupCustomizerService. + + Service to manage ad group customizer + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_ad_group_customizers( + self, + ) -> Callable[ + [ad_group_customizer_service.MutateAdGroupCustomizersRequest], + ad_group_customizer_service.MutateAdGroupCustomizersResponse, + ]: + r"""Return a callable for the mutate ad group customizers method over gRPC. + + Creates, updates or removes ad group customizers. + Operation statuses are returned. + + Returns: + Callable[[~.MutateAdGroupCustomizersRequest], + ~.MutateAdGroupCustomizersResponse]: + 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 "mutate_ad_group_customizers" not in self._stubs: + self._stubs["mutate_ad_group_customizers"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupCustomizerService/MutateAdGroupCustomizers", + request_serializer=ad_group_customizer_service.MutateAdGroupCustomizersRequest.serialize, + response_deserializer=ad_group_customizer_service.MutateAdGroupCustomizersResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_customizers"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AdGroupCustomizerServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..3c8bc0e60 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_customizer_service/transports/grpc_asyncio.py @@ -0,0 +1,407 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_customizer_service +from .base import AdGroupCustomizerServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupCustomizerService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupCustomizerService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupCustomizerServiceGrpcAsyncIOTransport( + AdGroupCustomizerServiceTransport +): + """gRPC AsyncIO backend transport for AdGroupCustomizerService. + + Service to manage ad group customizer + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_ad_group_customizers( + self, + ) -> Callable[ + [ad_group_customizer_service.MutateAdGroupCustomizersRequest], + Awaitable[ad_group_customizer_service.MutateAdGroupCustomizersResponse], + ]: + r"""Return a callable for the mutate ad group customizers method over gRPC. + + Creates, updates or removes ad group customizers. + Operation statuses are returned. + + Returns: + Callable[[~.MutateAdGroupCustomizersRequest], + Awaitable[~.MutateAdGroupCustomizersResponse]]: + 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 "mutate_ad_group_customizers" not in self._stubs: + self._stubs["mutate_ad_group_customizers"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupCustomizerService/MutateAdGroupCustomizers", + request_serializer=ad_group_customizer_service.MutateAdGroupCustomizersRequest.serialize, + response_deserializer=ad_group_customizer_service.MutateAdGroupCustomizersResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_customizers"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_ad_group_customizers: self._wrap_method( + self.mutate_ad_group_customizers, + 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" + + +__all__ = ("AdGroupCustomizerServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_label_service/__init__.py b/google/ads/googleads/v24/services/services/ad_group_label_service/__init__.py new file mode 100644 index 000000000..982539127 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_label_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AdGroupLabelServiceClient +from .async_client import AdGroupLabelServiceAsyncClient + +__all__ = ( + "AdGroupLabelServiceClient", + "AdGroupLabelServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_label_service/async_client.py b/google/ads/googleads/v24/services/services/ad_group_label_service/async_client.py new file mode 100644 index 000000000..6f6deb912 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_label_service/async_client.py @@ -0,0 +1,430 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ad_group_label_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdGroupLabelServiceTransport, DEFAULT_CLIENT_INFO +from .client import AdGroupLabelServiceClient + +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 AdGroupLabelServiceAsyncClient: + """Service to manage labels on ad groups.""" + + _client: AdGroupLabelServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AdGroupLabelServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AdGroupLabelServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AdGroupLabelServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AdGroupLabelServiceClient._DEFAULT_UNIVERSE + + ad_group_path = staticmethod(AdGroupLabelServiceClient.ad_group_path) + parse_ad_group_path = staticmethod( + AdGroupLabelServiceClient.parse_ad_group_path + ) + ad_group_label_path = staticmethod( + AdGroupLabelServiceClient.ad_group_label_path + ) + parse_ad_group_label_path = staticmethod( + AdGroupLabelServiceClient.parse_ad_group_label_path + ) + label_path = staticmethod(AdGroupLabelServiceClient.label_path) + parse_label_path = staticmethod(AdGroupLabelServiceClient.parse_label_path) + common_billing_account_path = staticmethod( + AdGroupLabelServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AdGroupLabelServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AdGroupLabelServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AdGroupLabelServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AdGroupLabelServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AdGroupLabelServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AdGroupLabelServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AdGroupLabelServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AdGroupLabelServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AdGroupLabelServiceClient.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: + AdGroupLabelServiceAsyncClient: The constructed client. + """ + return AdGroupLabelServiceClient.from_service_account_info.__func__(AdGroupLabelServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AdGroupLabelServiceAsyncClient: The constructed client. + """ + return AdGroupLabelServiceClient.from_service_account_file.__func__(AdGroupLabelServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AdGroupLabelServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AdGroupLabelServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupLabelServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AdGroupLabelServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AdGroupLabelServiceTransport, + Callable[..., AdGroupLabelServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group label 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,AdGroupLabelServiceTransport,Callable[..., AdGroupLabelServiceTransport]]]): + 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 AdGroupLabelServiceTransport 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 = AdGroupLabelServiceClient( + 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.ads.googleads.v24.services.AdGroupLabelServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupLabelService", + "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.ads.googleads.v24.services.AdGroupLabelService", + "credentialsType": None, + } + ), + ) + + async def mutate_ad_group_labels( + self, + request: Optional[ + Union[ad_group_label_service.MutateAdGroupLabelsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_group_label_service.AdGroupLabelOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_label_service.MutateAdGroupLabelsResponse: + r"""Creates and removes ad group labels. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAdGroupLabelsRequest, dict]]): + The request object. Request message for + [AdGroupLabelService.MutateAdGroupLabels][google.ads.googleads.v24.services.AdGroupLabelService.MutateAdGroupLabels]. + customer_id (:class:`str`): + Required. ID of the customer whose ad + group labels are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AdGroupLabelOperation]`): + Required. The list of operations to + perform on ad group labels. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupLabelsResponse: + Response message for an ad group + labels mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_label_service.MutateAdGroupLabelsRequest + ): + request = ad_group_label_service.MutateAdGroupLabelsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_ad_group_labels + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AdGroupLabelServiceAsyncClient": + 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__ = ("AdGroupLabelServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_label_service/client.py b/google/ads/googleads/v24/services/services/ad_group_label_service/client.py new file mode 100644 index 000000000..df5c1b9e8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_label_service/client.py @@ -0,0 +1,933 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ad_group_label_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdGroupLabelServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import AdGroupLabelServiceGrpcTransport +from .transports.grpc_asyncio import AdGroupLabelServiceGrpcAsyncIOTransport + + +class AdGroupLabelServiceClientMeta(type): + """Metaclass for the AdGroupLabelService 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[AdGroupLabelServiceTransport]] + _transport_registry["grpc"] = AdGroupLabelServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AdGroupLabelServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdGroupLabelServiceTransport]: + """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 AdGroupLabelServiceClient(metaclass=AdGroupLabelServiceClientMeta): + """Service to manage labels on ad groups.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AdGroupLabelServiceClient: 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: + AdGroupLabelServiceClient: 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) -> AdGroupLabelServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupLabelServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_group_path( + customer_id: str, + ad_group_id: str, + ) -> str: + """Returns a fully-qualified ad_group string.""" + return "customers/{customer_id}/adGroups/{ad_group_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ) + + @staticmethod + def parse_ad_group_path(path: str) -> Dict[str, str]: + """Parses a ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_label_path( + customer_id: str, + ad_group_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified ad_group_label string.""" + return "customers/{customer_id}/adGroupLabels/{ad_group_id}~{label_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + label_id=label_id, + ) + + @staticmethod + def parse_ad_group_label_path(path: str) -> Dict[str, str]: + """Parses a ad_group_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupLabels/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def label_path( + customer_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified label string.""" + return "customers/{customer_id}/labels/{label_id}".format( + customer_id=customer_id, + label_id=label_id, + ) + + @staticmethod + def parse_label_path(path: str) -> Dict[str, str]: + """Parses a label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/labels/(?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 = AdGroupLabelServiceClient._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 = AdGroupLabelServiceClient._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 + ): + """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 = AdGroupLabelServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AdGroupLabelServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AdGroupLabelServiceClient._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 = AdGroupLabelServiceClient._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): + """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, + AdGroupLabelServiceTransport, + Callable[..., AdGroupLabelServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group label 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,AdGroupLabelServiceTransport,Callable[..., AdGroupLabelServiceTransport]]]): + 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 AdGroupLabelServiceTransport 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, + ) = AdGroupLabelServiceClient._read_environment_variables() + self._client_cert_source = ( + AdGroupLabelServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = AdGroupLabelServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AdGroupLabelServiceTransport) + if transport_provided: + # transport is a AdGroupLabelServiceTransport 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(AdGroupLabelServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AdGroupLabelServiceClient._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[AdGroupLabelServiceTransport], + Callable[..., AdGroupLabelServiceTransport], + ] = ( + AdGroupLabelServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AdGroupLabelServiceTransport], 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.ads.googleads.v24.services.AdGroupLabelServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupLabelService", + "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.ads.googleads.v24.services.AdGroupLabelService", + "credentialsType": None, + } + ), + ) + + def mutate_ad_group_labels( + self, + request: Optional[ + Union[ad_group_label_service.MutateAdGroupLabelsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_group_label_service.AdGroupLabelOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_label_service.MutateAdGroupLabelsResponse: + r"""Creates and removes ad group labels. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAdGroupLabelsRequest, dict]): + The request object. Request message for + [AdGroupLabelService.MutateAdGroupLabels][google.ads.googleads.v24.services.AdGroupLabelService.MutateAdGroupLabels]. + customer_id (str): + Required. ID of the customer whose ad + group labels are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupLabelOperation]): + Required. The list of operations to + perform on ad group labels. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupLabelsResponse: + Response message for an ad group + labels mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_label_service.MutateAdGroupLabelsRequest + ): + request = ad_group_label_service.MutateAdGroupLabelsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_ad_group_labels + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AdGroupLabelServiceClient": + 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() + + +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__ = ("AdGroupLabelServiceClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_label_service/transports/README.rst b/google/ads/googleads/v24/services/services/ad_group_label_service/transports/README.rst new file mode 100644 index 000000000..780dd8f70 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_label_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AdGroupLabelServiceTransport` is the ABC for all transports. +- public child `AdGroupLabelServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AdGroupLabelServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAdGroupLabelServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AdGroupLabelServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/ad_group_label_service/transports/__init__.py b/google/ads/googleads/v24/services/services/ad_group_label_service/transports/__init__.py new file mode 100644 index 000000000..ca71142c6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_label_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AdGroupLabelServiceTransport +from .grpc import AdGroupLabelServiceGrpcTransport +from .grpc_asyncio import AdGroupLabelServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupLabelServiceTransport]] +_transport_registry["grpc"] = AdGroupLabelServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AdGroupLabelServiceGrpcAsyncIOTransport + +__all__ = ( + "AdGroupLabelServiceTransport", + "AdGroupLabelServiceGrpcTransport", + "AdGroupLabelServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_label_service/transports/base.py b/google/ads/googleads/v24/services/services/ad_group_label_service/transports/base.py new file mode 100644 index 000000000..7d522d2f7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_label_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ad_group_label_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 AdGroupLabelServiceTransport(abc.ABC): + """Abstract transport class for AdGroupLabelService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ad_group_labels: gapic_v1.method.wrap_method( + self.mutate_ad_group_labels, + 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 mutate_ad_group_labels( + self, + ) -> Callable[ + [ad_group_label_service.MutateAdGroupLabelsRequest], + Union[ + ad_group_label_service.MutateAdGroupLabelsResponse, + Awaitable[ad_group_label_service.MutateAdGroupLabelsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AdGroupLabelServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_label_service/transports/grpc.py b/google/ads/googleads/v24/services/services/ad_group_label_service/transports/grpc.py new file mode 100644 index 000000000..4430eea00 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_label_service/transports/grpc.py @@ -0,0 +1,390 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_label_service +from .base import AdGroupLabelServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupLabelService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupLabelService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupLabelServiceGrpcTransport(AdGroupLabelServiceTransport): + """gRPC backend transport for AdGroupLabelService. + + Service to manage labels on ad groups. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_ad_group_labels( + self, + ) -> Callable[ + [ad_group_label_service.MutateAdGroupLabelsRequest], + ad_group_label_service.MutateAdGroupLabelsResponse, + ]: + r"""Return a callable for the mutate ad group labels method over gRPC. + + Creates and removes ad group labels. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateAdGroupLabelsRequest], + ~.MutateAdGroupLabelsResponse]: + 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 "mutate_ad_group_labels" not in self._stubs: + self._stubs["mutate_ad_group_labels"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupLabelService/MutateAdGroupLabels", + request_serializer=ad_group_label_service.MutateAdGroupLabelsRequest.serialize, + response_deserializer=ad_group_label_service.MutateAdGroupLabelsResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_labels"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AdGroupLabelServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_label_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/ad_group_label_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..19028d83a --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_label_service/transports/grpc_asyncio.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_label_service +from .base import AdGroupLabelServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupLabelService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupLabelService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupLabelServiceGrpcAsyncIOTransport(AdGroupLabelServiceTransport): + """gRPC AsyncIO backend transport for AdGroupLabelService. + + Service to manage labels on ad groups. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_ad_group_labels( + self, + ) -> Callable[ + [ad_group_label_service.MutateAdGroupLabelsRequest], + Awaitable[ad_group_label_service.MutateAdGroupLabelsResponse], + ]: + r"""Return a callable for the mutate ad group labels method over gRPC. + + Creates and removes ad group labels. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateAdGroupLabelsRequest], + Awaitable[~.MutateAdGroupLabelsResponse]]: + 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 "mutate_ad_group_labels" not in self._stubs: + self._stubs["mutate_ad_group_labels"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupLabelService/MutateAdGroupLabels", + request_serializer=ad_group_label_service.MutateAdGroupLabelsRequest.serialize, + response_deserializer=ad_group_label_service.MutateAdGroupLabelsResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_group_labels"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_ad_group_labels: self._wrap_method( + self.mutate_ad_group_labels, + 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" + + +__all__ = ("AdGroupLabelServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_service/__init__.py b/google/ads/googleads/v24/services/services/ad_group_service/__init__.py new file mode 100644 index 000000000..608cbc9d1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AdGroupServiceClient +from .async_client import AdGroupServiceAsyncClient + +__all__ = ( + "AdGroupServiceClient", + "AdGroupServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_service/async_client.py b/google/ads/googleads/v24/services/services/ad_group_service/async_client.py new file mode 100644 index 000000000..c72480107 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_service/async_client.py @@ -0,0 +1,427 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ad_group_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdGroupServiceTransport, DEFAULT_CLIENT_INFO +from .client import AdGroupServiceClient + +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 AdGroupServiceAsyncClient: + """Service to manage ad groups.""" + + _client: AdGroupServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AdGroupServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AdGroupServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = AdGroupServiceClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = AdGroupServiceClient._DEFAULT_UNIVERSE + + ad_group_path = staticmethod(AdGroupServiceClient.ad_group_path) + parse_ad_group_path = staticmethod(AdGroupServiceClient.parse_ad_group_path) + ad_group_label_path = staticmethod(AdGroupServiceClient.ad_group_label_path) + parse_ad_group_label_path = staticmethod( + AdGroupServiceClient.parse_ad_group_label_path + ) + campaign_path = staticmethod(AdGroupServiceClient.campaign_path) + parse_campaign_path = staticmethod(AdGroupServiceClient.parse_campaign_path) + common_billing_account_path = staticmethod( + AdGroupServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AdGroupServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(AdGroupServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + AdGroupServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AdGroupServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AdGroupServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod(AdGroupServiceClient.common_project_path) + parse_common_project_path = staticmethod( + AdGroupServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AdGroupServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AdGroupServiceClient.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: + AdGroupServiceAsyncClient: The constructed client. + """ + return AdGroupServiceClient.from_service_account_info.__func__(AdGroupServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AdGroupServiceAsyncClient: The constructed client. + """ + return AdGroupServiceClient.from_service_account_file.__func__(AdGroupServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AdGroupServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AdGroupServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AdGroupServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AdGroupServiceTransport, + Callable[..., AdGroupServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group 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,AdGroupServiceTransport,Callable[..., AdGroupServiceTransport]]]): + 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 AdGroupServiceTransport 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 = AdGroupServiceClient( + 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.ads.googleads.v24.services.AdGroupServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupService", + "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.ads.googleads.v24.services.AdGroupService", + "credentialsType": None, + } + ), + ) + + async def mutate_ad_groups( + self, + request: Optional[ + Union[ad_group_service.MutateAdGroupsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_group_service.AdGroupOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_service.MutateAdGroupsResponse: + r"""Creates, updates, or removes ad groups. Operation statuses are + returned. + + List of thrown errors: `AdGroupError <>`__ `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `BiddingError <>`__ `BiddingStrategyError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MultiplierError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SettingError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAdGroupsRequest, dict]]): + The request object. Request message for + [AdGroupService.MutateAdGroups][google.ads.googleads.v24.services.AdGroupService.MutateAdGroups]. + customer_id (:class:`str`): + Required. The ID of the customer + whose ad groups are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AdGroupOperation]`): + Required. The list of operations to + perform on individual ad groups. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupsResponse: + Response message for an ad group + mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_service.MutateAdGroupsRequest): + request = ad_group_service.MutateAdGroupsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_ad_groups + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AdGroupServiceAsyncClient": + 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__ = ("AdGroupServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_service/client.py b/google/ads/googleads/v24/services/services/ad_group_service/client.py new file mode 100644 index 000000000..8745acc81 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_service/client.py @@ -0,0 +1,933 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ad_group_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdGroupServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import AdGroupServiceGrpcTransport +from .transports.grpc_asyncio import AdGroupServiceGrpcAsyncIOTransport + + +class AdGroupServiceClientMeta(type): + """Metaclass for the AdGroupService 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[AdGroupServiceTransport]] + _transport_registry["grpc"] = AdGroupServiceGrpcTransport + _transport_registry["grpc_asyncio"] = AdGroupServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdGroupServiceTransport]: + """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 AdGroupServiceClient(metaclass=AdGroupServiceClientMeta): + """Service to manage ad groups.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AdGroupServiceClient: 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: + AdGroupServiceClient: 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) -> AdGroupServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_group_path( + customer_id: str, + ad_group_id: str, + ) -> str: + """Returns a fully-qualified ad_group string.""" + return "customers/{customer_id}/adGroups/{ad_group_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ) + + @staticmethod + def parse_ad_group_path(path: str) -> Dict[str, str]: + """Parses a ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_label_path( + customer_id: str, + ad_group_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified ad_group_label string.""" + return "customers/{customer_id}/adGroupLabels/{ad_group_id}~{label_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + label_id=label_id, + ) + + @staticmethod + def parse_ad_group_label_path(path: str) -> Dict[str, str]: + """Parses a ad_group_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupLabels/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?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 = AdGroupServiceClient._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 = AdGroupServiceClient._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 + ): + """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 = AdGroupServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AdGroupServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AdGroupServiceClient._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 = AdGroupServiceClient._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): + """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, + AdGroupServiceTransport, + Callable[..., AdGroupServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad group 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,AdGroupServiceTransport,Callable[..., AdGroupServiceTransport]]]): + 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 AdGroupServiceTransport 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, + ) = AdGroupServiceClient._read_environment_variables() + self._client_cert_source = AdGroupServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = AdGroupServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AdGroupServiceTransport) + if transport_provided: + # transport is a AdGroupServiceTransport 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(AdGroupServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AdGroupServiceClient._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[AdGroupServiceTransport], + Callable[..., AdGroupServiceTransport], + ] = ( + AdGroupServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., AdGroupServiceTransport], 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.ads.googleads.v24.services.AdGroupServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdGroupService", + "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.ads.googleads.v24.services.AdGroupService", + "credentialsType": None, + } + ), + ) + + def mutate_ad_groups( + self, + request: Optional[ + Union[ad_group_service.MutateAdGroupsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_group_service.AdGroupOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_group_service.MutateAdGroupsResponse: + r"""Creates, updates, or removes ad groups. Operation statuses are + returned. + + List of thrown errors: `AdGroupError <>`__ `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `BiddingError <>`__ `BiddingStrategyError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MultiplierError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SettingError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAdGroupsRequest, dict]): + The request object. Request message for + [AdGroupService.MutateAdGroups][google.ads.googleads.v24.services.AdGroupService.MutateAdGroups]. + customer_id (str): + Required. The ID of the customer + whose ad groups are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupOperation]): + Required. The list of operations to + perform on individual ad groups. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdGroupsResponse: + Response message for an ad group + mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_group_service.MutateAdGroupsRequest): + request = ad_group_service.MutateAdGroupsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.mutate_ad_groups] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AdGroupServiceClient": + 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() + + +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__ = ("AdGroupServiceClient",) diff --git a/google/ads/googleads/v24/services/services/ad_group_service/transports/README.rst b/google/ads/googleads/v24/services/services/ad_group_service/transports/README.rst new file mode 100644 index 000000000..df6add77d --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AdGroupServiceTransport` is the ABC for all transports. +- public child `AdGroupServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AdGroupServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAdGroupServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AdGroupServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/ad_group_service/transports/__init__.py b/google/ads/googleads/v24/services/services/ad_group_service/transports/__init__.py new file mode 100644 index 000000000..fb012f847 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AdGroupServiceTransport +from .grpc import AdGroupServiceGrpcTransport +from .grpc_asyncio import AdGroupServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupServiceTransport]] +_transport_registry["grpc"] = AdGroupServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AdGroupServiceGrpcAsyncIOTransport + +__all__ = ( + "AdGroupServiceTransport", + "AdGroupServiceGrpcTransport", + "AdGroupServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/ad_group_service/transports/base.py b/google/ads/googleads/v24/services/services/ad_group_service/transports/base.py new file mode 100644 index 000000000..49c08d10f --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ad_group_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 AdGroupServiceTransport(abc.ABC): + """Abstract transport class for AdGroupService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ad_groups: gapic_v1.method.wrap_method( + self.mutate_ad_groups, + 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 mutate_ad_groups( + self, + ) -> Callable[ + [ad_group_service.MutateAdGroupsRequest], + Union[ + ad_group_service.MutateAdGroupsResponse, + Awaitable[ad_group_service.MutateAdGroupsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AdGroupServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_service/transports/grpc.py b/google/ads/googleads/v24/services/services/ad_group_service/transports/grpc.py new file mode 100644 index 000000000..b10e52b66 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_service/transports/grpc.py @@ -0,0 +1,397 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_service +from .base import AdGroupServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupServiceGrpcTransport(AdGroupServiceTransport): + """gRPC backend transport for AdGroupService. + + Service to manage ad groups. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_ad_groups( + self, + ) -> Callable[ + [ad_group_service.MutateAdGroupsRequest], + ad_group_service.MutateAdGroupsResponse, + ]: + r"""Return a callable for the mutate ad groups method over gRPC. + + Creates, updates, or removes ad groups. Operation statuses are + returned. + + List of thrown errors: `AdGroupError <>`__ `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `BiddingError <>`__ `BiddingStrategyError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MultiplierError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SettingError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateAdGroupsRequest], + ~.MutateAdGroupsResponse]: + 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 "mutate_ad_groups" not in self._stubs: + self._stubs["mutate_ad_groups"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupService/MutateAdGroups", + request_serializer=ad_group_service.MutateAdGroupsRequest.serialize, + response_deserializer=ad_group_service.MutateAdGroupsResponse.deserialize, + ) + return self._stubs["mutate_ad_groups"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AdGroupServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_group_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/ad_group_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..07e1322d8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_group_service/transports/grpc_asyncio.py @@ -0,0 +1,418 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ad_group_service +from .base import AdGroupServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdGroupService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdGroupService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdGroupServiceGrpcAsyncIOTransport(AdGroupServiceTransport): + """gRPC AsyncIO backend transport for AdGroupService. + + Service to manage ad groups. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_ad_groups( + self, + ) -> Callable[ + [ad_group_service.MutateAdGroupsRequest], + Awaitable[ad_group_service.MutateAdGroupsResponse], + ]: + r"""Return a callable for the mutate ad groups method over gRPC. + + Creates, updates, or removes ad groups. Operation statuses are + returned. + + List of thrown errors: `AdGroupError <>`__ `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `BiddingError <>`__ `BiddingStrategyError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MultiplierError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SettingError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateAdGroupsRequest], + Awaitable[~.MutateAdGroupsResponse]]: + 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 "mutate_ad_groups" not in self._stubs: + self._stubs["mutate_ad_groups"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdGroupService/MutateAdGroups", + request_serializer=ad_group_service.MutateAdGroupsRequest.serialize, + response_deserializer=ad_group_service.MutateAdGroupsResponse.deserialize, + ) + return self._stubs["mutate_ad_groups"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_ad_groups: self._wrap_method( + self.mutate_ad_groups, + 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" + + +__all__ = ("AdGroupServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_parameter_service/__init__.py b/google/ads/googleads/v24/services/services/ad_parameter_service/__init__.py new file mode 100644 index 000000000..37268dc5d --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_parameter_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AdParameterServiceClient +from .async_client import AdParameterServiceAsyncClient + +__all__ = ( + "AdParameterServiceClient", + "AdParameterServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/ad_parameter_service/async_client.py b/google/ads/googleads/v24/services/services/ad_parameter_service/async_client.py new file mode 100644 index 000000000..65c84c54e --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_parameter_service/async_client.py @@ -0,0 +1,428 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ad_parameter_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdParameterServiceTransport, DEFAULT_CLIENT_INFO +from .client import AdParameterServiceClient + +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 AdParameterServiceAsyncClient: + """Service to manage ad parameters.""" + + _client: AdParameterServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AdParameterServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AdParameterServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AdParameterServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AdParameterServiceClient._DEFAULT_UNIVERSE + + ad_group_criterion_path = staticmethod( + AdParameterServiceClient.ad_group_criterion_path + ) + parse_ad_group_criterion_path = staticmethod( + AdParameterServiceClient.parse_ad_group_criterion_path + ) + ad_parameter_path = staticmethod(AdParameterServiceClient.ad_parameter_path) + parse_ad_parameter_path = staticmethod( + AdParameterServiceClient.parse_ad_parameter_path + ) + common_billing_account_path = staticmethod( + AdParameterServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AdParameterServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AdParameterServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AdParameterServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AdParameterServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AdParameterServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AdParameterServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AdParameterServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AdParameterServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AdParameterServiceClient.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: + AdParameterServiceAsyncClient: The constructed client. + """ + return AdParameterServiceClient.from_service_account_info.__func__(AdParameterServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AdParameterServiceAsyncClient: The constructed client. + """ + return AdParameterServiceClient.from_service_account_file.__func__(AdParameterServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AdParameterServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AdParameterServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdParameterServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AdParameterServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AdParameterServiceTransport, + Callable[..., AdParameterServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad parameter 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,AdParameterServiceTransport,Callable[..., AdParameterServiceTransport]]]): + 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 AdParameterServiceTransport 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 = AdParameterServiceClient( + 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.ads.googleads.v24.services.AdParameterServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdParameterService", + "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.ads.googleads.v24.services.AdParameterService", + "credentialsType": None, + } + ), + ) + + async def mutate_ad_parameters( + self, + request: Optional[ + Union[ad_parameter_service.MutateAdParametersRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_parameter_service.AdParameterOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_parameter_service.MutateAdParametersResponse: + r"""Creates, updates, or removes ad parameters. Operation statuses + are returned. + + List of thrown errors: `AdParameterError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAdParametersRequest, dict]]): + The request object. Request message for + [AdParameterService.MutateAdParameters][google.ads.googleads.v24.services.AdParameterService.MutateAdParameters] + customer_id (:class:`str`): + Required. The ID of the customer + whose ad parameters are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AdParameterOperation]`): + Required. The list of operations to + perform on individual ad parameters. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdParametersResponse: + Response message for an ad parameter + mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_parameter_service.MutateAdParametersRequest + ): + request = ad_parameter_service.MutateAdParametersRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_ad_parameters + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AdParameterServiceAsyncClient": + 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__ = ("AdParameterServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/ad_parameter_service/client.py b/google/ads/googleads/v24/services/services/ad_parameter_service/client.py new file mode 100644 index 000000000..c3d44b936 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_parameter_service/client.py @@ -0,0 +1,914 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ad_parameter_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdParameterServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import AdParameterServiceGrpcTransport +from .transports.grpc_asyncio import AdParameterServiceGrpcAsyncIOTransport + + +class AdParameterServiceClientMeta(type): + """Metaclass for the AdParameterService 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[AdParameterServiceTransport]] + _transport_registry["grpc"] = AdParameterServiceGrpcTransport + _transport_registry["grpc_asyncio"] = AdParameterServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdParameterServiceTransport]: + """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 AdParameterServiceClient(metaclass=AdParameterServiceClientMeta): + """Service to manage ad parameters.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AdParameterServiceClient: 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: + AdParameterServiceClient: 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) -> AdParameterServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdParameterServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_group_criterion_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified ad_group_criterion string.""" + return "customers/{customer_id}/adGroupCriteria/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_ad_group_criterion_path(path: str) -> Dict[str, str]: + """Parses a ad_group_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCriteria/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_parameter_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + parameter_index: str, + ) -> str: + """Returns a fully-qualified ad_parameter string.""" + return "customers/{customer_id}/adParameters/{ad_group_id}~{criterion_id}~{parameter_index}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + parameter_index=parameter_index, + ) + + @staticmethod + def parse_ad_parameter_path(path: str) -> Dict[str, str]: + """Parses a ad_parameter path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adParameters/(?P.+?)~(?P.+?)~(?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 = AdParameterServiceClient._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 = AdParameterServiceClient._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 + ): + """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 = AdParameterServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AdParameterServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AdParameterServiceClient._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 = AdParameterServiceClient._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): + """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, + AdParameterServiceTransport, + Callable[..., AdParameterServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad parameter 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,AdParameterServiceTransport,Callable[..., AdParameterServiceTransport]]]): + 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 AdParameterServiceTransport 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, + ) = AdParameterServiceClient._read_environment_variables() + self._client_cert_source = ( + AdParameterServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = AdParameterServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AdParameterServiceTransport) + if transport_provided: + # transport is a AdParameterServiceTransport 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(AdParameterServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AdParameterServiceClient._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[AdParameterServiceTransport], + Callable[..., AdParameterServiceTransport], + ] = ( + AdParameterServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., AdParameterServiceTransport], 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.ads.googleads.v24.services.AdParameterServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdParameterService", + "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.ads.googleads.v24.services.AdParameterService", + "credentialsType": None, + } + ), + ) + + def mutate_ad_parameters( + self, + request: Optional[ + Union[ad_parameter_service.MutateAdParametersRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_parameter_service.AdParameterOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_parameter_service.MutateAdParametersResponse: + r"""Creates, updates, or removes ad parameters. Operation statuses + are returned. + + List of thrown errors: `AdParameterError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAdParametersRequest, dict]): + The request object. Request message for + [AdParameterService.MutateAdParameters][google.ads.googleads.v24.services.AdParameterService.MutateAdParameters] + customer_id (str): + Required. The ID of the customer + whose ad parameters are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdParameterOperation]): + Required. The list of operations to + perform on individual ad parameters. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdParametersResponse: + Response message for an ad parameter + mutate. + + """ + # 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 = [customer_id, operations] + 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, ad_parameter_service.MutateAdParametersRequest + ): + request = ad_parameter_service.MutateAdParametersRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_ad_parameters + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AdParameterServiceClient": + 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() + + +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__ = ("AdParameterServiceClient",) diff --git a/google/ads/googleads/v24/services/services/ad_parameter_service/transports/README.rst b/google/ads/googleads/v24/services/services/ad_parameter_service/transports/README.rst new file mode 100644 index 000000000..22f8d45fc --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_parameter_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AdParameterServiceTransport` is the ABC for all transports. +- public child `AdParameterServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AdParameterServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAdParameterServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AdParameterServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/ad_parameter_service/transports/__init__.py b/google/ads/googleads/v24/services/services/ad_parameter_service/transports/__init__.py new file mode 100644 index 000000000..7d237da8a --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_parameter_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AdParameterServiceTransport +from .grpc import AdParameterServiceGrpcTransport +from .grpc_asyncio import AdParameterServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdParameterServiceTransport]] +_transport_registry["grpc"] = AdParameterServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AdParameterServiceGrpcAsyncIOTransport + +__all__ = ( + "AdParameterServiceTransport", + "AdParameterServiceGrpcTransport", + "AdParameterServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/ad_parameter_service/transports/base.py b/google/ads/googleads/v24/services/services/ad_parameter_service/transports/base.py new file mode 100644 index 000000000..9d357ee8f --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_parameter_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ad_parameter_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 AdParameterServiceTransport(abc.ABC): + """Abstract transport class for AdParameterService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ad_parameters: gapic_v1.method.wrap_method( + self.mutate_ad_parameters, + 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 mutate_ad_parameters( + self, + ) -> Callable[ + [ad_parameter_service.MutateAdParametersRequest], + Union[ + ad_parameter_service.MutateAdParametersResponse, + Awaitable[ad_parameter_service.MutateAdParametersResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AdParameterServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_parameter_service/transports/grpc.py b/google/ads/googleads/v24/services/services/ad_parameter_service/transports/grpc.py new file mode 100644 index 000000000..0075c1b65 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_parameter_service/transports/grpc.py @@ -0,0 +1,390 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ad_parameter_service +from .base import AdParameterServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdParameterService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdParameterService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdParameterServiceGrpcTransport(AdParameterServiceTransport): + """gRPC backend transport for AdParameterService. + + Service to manage ad parameters. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_ad_parameters( + self, + ) -> Callable[ + [ad_parameter_service.MutateAdParametersRequest], + ad_parameter_service.MutateAdParametersResponse, + ]: + r"""Return a callable for the mutate ad parameters method over gRPC. + + Creates, updates, or removes ad parameters. Operation statuses + are returned. + + List of thrown errors: `AdParameterError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateAdParametersRequest], + ~.MutateAdParametersResponse]: + 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 "mutate_ad_parameters" not in self._stubs: + self._stubs["mutate_ad_parameters"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdParameterService/MutateAdParameters", + request_serializer=ad_parameter_service.MutateAdParametersRequest.serialize, + response_deserializer=ad_parameter_service.MutateAdParametersResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_parameters"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AdParameterServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_parameter_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/ad_parameter_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..8434f82fb --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_parameter_service/transports/grpc_asyncio.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ad_parameter_service +from .base import AdParameterServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdParameterService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdParameterService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdParameterServiceGrpcAsyncIOTransport(AdParameterServiceTransport): + """gRPC AsyncIO backend transport for AdParameterService. + + Service to manage ad parameters. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_ad_parameters( + self, + ) -> Callable[ + [ad_parameter_service.MutateAdParametersRequest], + Awaitable[ad_parameter_service.MutateAdParametersResponse], + ]: + r"""Return a callable for the mutate ad parameters method over gRPC. + + Creates, updates, or removes ad parameters. Operation statuses + are returned. + + List of thrown errors: `AdParameterError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateAdParametersRequest], + Awaitable[~.MutateAdParametersResponse]]: + 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 "mutate_ad_parameters" not in self._stubs: + self._stubs["mutate_ad_parameters"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdParameterService/MutateAdParameters", + request_serializer=ad_parameter_service.MutateAdParametersRequest.serialize, + response_deserializer=ad_parameter_service.MutateAdParametersResponse.deserialize, + ) + ) + return self._stubs["mutate_ad_parameters"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_ad_parameters: self._wrap_method( + self.mutate_ad_parameters, + 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" + + +__all__ = ("AdParameterServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_service/__init__.py b/google/ads/googleads/v24/services/services/ad_service/__init__.py new file mode 100644 index 000000000..b3d7a2afb --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AdServiceClient +from .async_client import AdServiceAsyncClient + +__all__ = ( + "AdServiceClient", + "AdServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/ad_service/async_client.py b/google/ads/googleads/v24/services/services/ad_service/async_client.py new file mode 100644 index 000000000..0d9eca0b1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_service/async_client.py @@ -0,0 +1,412 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ad_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdServiceTransport, DEFAULT_CLIENT_INFO +from .client import AdServiceClient + +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 AdServiceAsyncClient: + """Service to manage ads.""" + + _client: AdServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AdServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AdServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = AdServiceClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = AdServiceClient._DEFAULT_UNIVERSE + + ad_path = staticmethod(AdServiceClient.ad_path) + parse_ad_path = staticmethod(AdServiceClient.parse_ad_path) + common_billing_account_path = staticmethod( + AdServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AdServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(AdServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + AdServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AdServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AdServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod(AdServiceClient.common_project_path) + parse_common_project_path = staticmethod( + AdServiceClient.parse_common_project_path + ) + common_location_path = staticmethod(AdServiceClient.common_location_path) + parse_common_location_path = staticmethod( + AdServiceClient.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: + AdServiceAsyncClient: The constructed client. + """ + return AdServiceClient.from_service_account_info.__func__(AdServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AdServiceAsyncClient: The constructed client. + """ + return AdServiceClient.from_service_account_file.__func__(AdServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AdServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AdServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AdServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, AdServiceTransport, Callable[..., AdServiceTransport]] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad 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,AdServiceTransport,Callable[..., AdServiceTransport]]]): + 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 AdServiceTransport 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 = AdServiceClient( + 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.ads.googleads.v24.services.AdServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdService", + "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.ads.googleads.v24.services.AdService", + "credentialsType": None, + } + ), + ) + + async def mutate_ads( + self, + request: Optional[Union[ad_service.MutateAdsRequest, dict]] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[MutableSequence[ad_service.AdOperation]] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_service.MutateAdsResponse: + r"""Updates ads. Operation statuses are returned. Updating ads is + not supported for TextAd, ExpandedDynamicSearchAd, GmailAd and + ImageAd. + + List of thrown errors: `AdCustomizerError <>`__ `AdError <>`__ + `AdSharingError <>`__ `AdxError <>`__ `AssetError <>`__ + `AssetLinkError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FeedAttributeReferenceError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `FunctionError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `IdError <>`__ + `ImageError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MediaBundleError <>`__ `MediaFileError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `PolicyFindingError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAdsRequest, dict]]): + The request object. Request message for + [AdService.MutateAds][google.ads.googleads.v24.services.AdService.MutateAds]. + customer_id (:class:`str`): + Required. The ID of the customer + whose ads are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AdOperation]`): + Required. The list of operations to + perform on individual ads. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdsResponse: + Response message for an ad mutate. + """ + # 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 = [customer_id, operations] + 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, ad_service.MutateAdsRequest): + request = ad_service.MutateAdsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_ads + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AdServiceAsyncClient": + 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__ = ("AdServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/ad_service/client.py b/google/ads/googleads/v24/services/services/ad_service/client.py new file mode 100644 index 000000000..718617aec --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_service/client.py @@ -0,0 +1,880 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ad_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import AdServiceGrpcTransport +from .transports.grpc_asyncio import AdServiceGrpcAsyncIOTransport + + +class AdServiceClientMeta(type): + """Metaclass for the AdService 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[AdServiceTransport]] + _transport_registry["grpc"] = AdServiceGrpcTransport + _transport_registry["grpc_asyncio"] = AdServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdServiceTransport]: + """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 AdServiceClient(metaclass=AdServiceClientMeta): + """Service to manage ads.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AdServiceClient: 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: + AdServiceClient: 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) -> AdServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_path( + customer_id: str, + ad_id: str, + ) -> str: + """Returns a fully-qualified ad string.""" + return "customers/{customer_id}/ads/{ad_id}".format( + customer_id=customer_id, + ad_id=ad_id, + ) + + @staticmethod + def parse_ad_path(path: str) -> Dict[str, str]: + """Parses a ad path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/ads/(?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 = AdServiceClient._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 = AdServiceClient._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 + ): + """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 = AdServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AdServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = AdServiceClient._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 = AdServiceClient._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): + """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, AdServiceTransport, Callable[..., AdServiceTransport]] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the ad 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,AdServiceTransport,Callable[..., AdServiceTransport]]]): + 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 AdServiceTransport 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, + ) = AdServiceClient._read_environment_variables() + self._client_cert_source = AdServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = AdServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AdServiceTransport) + if transport_provided: + # transport is a AdServiceTransport 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(AdServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AdServiceClient._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[AdServiceTransport], Callable[..., AdServiceTransport] + ] = ( + AdServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., AdServiceTransport], 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.ads.googleads.v24.services.AdServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AdService", + "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.ads.googleads.v24.services.AdService", + "credentialsType": None, + } + ), + ) + + def mutate_ads( + self, + request: Optional[Union[ad_service.MutateAdsRequest, dict]] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[MutableSequence[ad_service.AdOperation]] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ad_service.MutateAdsResponse: + r"""Updates ads. Operation statuses are returned. Updating ads is + not supported for TextAd, ExpandedDynamicSearchAd, GmailAd and + ImageAd. + + List of thrown errors: `AdCustomizerError <>`__ `AdError <>`__ + `AdSharingError <>`__ `AdxError <>`__ `AssetError <>`__ + `AssetLinkError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FeedAttributeReferenceError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `FunctionError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `IdError <>`__ + `ImageError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MediaBundleError <>`__ `MediaFileError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `PolicyFindingError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAdsRequest, dict]): + The request object. Request message for + [AdService.MutateAds][google.ads.googleads.v24.services.AdService.MutateAds]. + customer_id (str): + Required. The ID of the customer + whose ads are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdOperation]): + Required. The list of operations to + perform on individual ads. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAdsResponse: + Response message for an ad mutate. + """ + # 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 = [customer_id, operations] + 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, ad_service.MutateAdsRequest): + request = ad_service.MutateAdsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.mutate_ads] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AdServiceClient": + 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() + + +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__ = ("AdServiceClient",) diff --git a/google/ads/googleads/v24/services/services/ad_service/transports/README.rst b/google/ads/googleads/v24/services/services/ad_service/transports/README.rst new file mode 100644 index 000000000..95dfae546 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AdServiceTransport` is the ABC for all transports. +- public child `AdServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AdServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAdServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AdServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/ad_service/transports/__init__.py b/google/ads/googleads/v24/services/services/ad_service/transports/__init__.py new file mode 100644 index 000000000..a214eba26 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_service/transports/__init__.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AdServiceTransport +from .grpc import AdServiceGrpcTransport +from .grpc_asyncio import AdServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = OrderedDict() # type: Dict[str, Type[AdServiceTransport]] +_transport_registry["grpc"] = AdServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AdServiceGrpcAsyncIOTransport + +__all__ = ( + "AdServiceTransport", + "AdServiceGrpcTransport", + "AdServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/ad_service/transports/base.py b/google/ads/googleads/v24/services/services/ad_service/transports/base.py new file mode 100644 index 000000000..082c7d3d2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ad_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 AdServiceTransport(abc.ABC): + """Abstract transport class for AdService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ads: gapic_v1.method.wrap_method( + self.mutate_ads, + 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 mutate_ads( + self, + ) -> Callable[ + [ad_service.MutateAdsRequest], + Union[ + ad_service.MutateAdsResponse, + Awaitable[ad_service.MutateAdsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AdServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_service/transports/grpc.py b/google/ads/googleads/v24/services/services/ad_service/transports/grpc.py new file mode 100644 index 000000000..6072c051c --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_service/transports/grpc.py @@ -0,0 +1,397 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ad_service +from .base import AdServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdServiceGrpcTransport(AdServiceTransport): + """gRPC backend transport for AdService. + + Service to manage ads. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_ads( + self, + ) -> Callable[[ad_service.MutateAdsRequest], ad_service.MutateAdsResponse]: + r"""Return a callable for the mutate ads method over gRPC. + + Updates ads. Operation statuses are returned. Updating ads is + not supported for TextAd, ExpandedDynamicSearchAd, GmailAd and + ImageAd. + + List of thrown errors: `AdCustomizerError <>`__ `AdError <>`__ + `AdSharingError <>`__ `AdxError <>`__ `AssetError <>`__ + `AssetLinkError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FeedAttributeReferenceError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `FunctionError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `IdError <>`__ + `ImageError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MediaBundleError <>`__ `MediaFileError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `PolicyFindingError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateAdsRequest], + ~.MutateAdsResponse]: + 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 "mutate_ads" not in self._stubs: + self._stubs["mutate_ads"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdService/MutateAds", + request_serializer=ad_service.MutateAdsRequest.serialize, + response_deserializer=ad_service.MutateAdsResponse.deserialize, + ) + return self._stubs["mutate_ads"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AdServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/ad_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/ad_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..f172e99ca --- /dev/null +++ b/google/ads/googleads/v24/services/services/ad_service/transports/grpc_asyncio.py @@ -0,0 +1,420 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ad_service +from .base import AdServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AdService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AdService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AdServiceGrpcAsyncIOTransport(AdServiceTransport): + """gRPC AsyncIO backend transport for AdService. + + Service to manage ads. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_ads( + self, + ) -> Callable[ + [ad_service.MutateAdsRequest], Awaitable[ad_service.MutateAdsResponse] + ]: + r"""Return a callable for the mutate ads method over gRPC. + + Updates ads. Operation statuses are returned. Updating ads is + not supported for TextAd, ExpandedDynamicSearchAd, GmailAd and + ImageAd. + + List of thrown errors: `AdCustomizerError <>`__ `AdError <>`__ + `AdSharingError <>`__ `AdxError <>`__ `AssetError <>`__ + `AssetLinkError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FeedAttributeReferenceError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `FunctionError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `IdError <>`__ + `ImageError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MediaBundleError <>`__ `MediaFileError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `PolicyFindingError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateAdsRequest], + Awaitable[~.MutateAdsResponse]]: + 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 "mutate_ads" not in self._stubs: + self._stubs["mutate_ads"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AdService/MutateAds", + request_serializer=ad_service.MutateAdsRequest.serialize, + response_deserializer=ad_service.MutateAdsResponse.deserialize, + ) + return self._stubs["mutate_ads"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_ads: self._wrap_method( + self.mutate_ads, + 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" + + +__all__ = ("AdServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_generation_service/__init__.py b/google/ads/googleads/v24/services/services/asset_generation_service/__init__.py new file mode 100644 index 000000000..f9f403217 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_generation_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AssetGenerationServiceClient +from .async_client import AssetGenerationServiceAsyncClient + +__all__ = ( + "AssetGenerationServiceClient", + "AssetGenerationServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/asset_generation_service/async_client.py b/google/ads/googleads/v24/services/services/asset_generation_service/async_client.py new file mode 100644 index 000000000..f972fbe78 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_generation_service/async_client.py @@ -0,0 +1,466 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import asset_generation_service +from .transports.base import ( + AssetGenerationServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import AssetGenerationServiceClient + +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 AssetGenerationServiceAsyncClient: + """Service for generating new assets with generative AI.""" + + _client: AssetGenerationServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AssetGenerationServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AssetGenerationServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AssetGenerationServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AssetGenerationServiceClient._DEFAULT_UNIVERSE + + ad_group_ad_path = staticmethod( + AssetGenerationServiceClient.ad_group_ad_path + ) + parse_ad_group_ad_path = staticmethod( + AssetGenerationServiceClient.parse_ad_group_ad_path + ) + asset_group_path = staticmethod( + AssetGenerationServiceClient.asset_group_path + ) + parse_asset_group_path = staticmethod( + AssetGenerationServiceClient.parse_asset_group_path + ) + common_billing_account_path = staticmethod( + AssetGenerationServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AssetGenerationServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AssetGenerationServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AssetGenerationServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AssetGenerationServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AssetGenerationServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AssetGenerationServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AssetGenerationServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AssetGenerationServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AssetGenerationServiceClient.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: + AssetGenerationServiceAsyncClient: The constructed client. + """ + return AssetGenerationServiceClient.from_service_account_info.__func__(AssetGenerationServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AssetGenerationServiceAsyncClient: The constructed client. + """ + return AssetGenerationServiceClient.from_service_account_file.__func__(AssetGenerationServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AssetGenerationServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AssetGenerationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetGenerationServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AssetGenerationServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AssetGenerationServiceTransport, + Callable[..., AssetGenerationServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset generation service async client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,AssetGenerationServiceTransport,Callable[..., AssetGenerationServiceTransport]]]): + 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 AssetGenerationServiceTransport 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 = AssetGenerationServiceClient( + 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.ads.googleads.v24.services.AssetGenerationServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetGenerationService", + "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.ads.googleads.v24.services.AssetGenerationService", + "credentialsType": None, + } + ), + ) + + async def generate_text( + self, + request: Optional[ + Union[asset_generation_service.GenerateTextRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_generation_service.GenerateTextResponse: + r"""Uses generative AI to generate text that can be used as assets + in a campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `AssetGenerationError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateTextRequest, dict]]): + The request object. Request message for + [AssetGenerationService.GenerateText][google.ads.googleads.v24.services.AssetGenerationService.GenerateText] + 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.googleads.v24.services.types.GenerateTextResponse: + Response message for + [AssetGenerationService.GenerateText][google.ads.googleads.v24.services.AssetGenerationService.GenerateText] + + """ + # 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, asset_generation_service.GenerateTextRequest + ): + request = asset_generation_service.GenerateTextRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_text + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_images( + self, + request: Optional[ + Union[asset_generation_service.GenerateImagesRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_generation_service.GenerateImagesResponse: + r"""Uses generative AI to generate images that can be used as assets + in a campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `AssetGenerationError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateImagesRequest, dict]]): + The request object. Request message for + [AssetGenerationService.GenerateImages][google.ads.googleads.v24.services.AssetGenerationService.GenerateImages] + 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.googleads.v24.services.types.GenerateImagesResponse: + Response message for + [AssetGenerationService.GenerateImages][google.ads.googleads.v24.services.AssetGenerationService.GenerateImages] + + """ + # 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, asset_generation_service.GenerateImagesRequest + ): + request = asset_generation_service.GenerateImagesRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_images + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AssetGenerationServiceAsyncClient": + 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__ = ("AssetGenerationServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/asset_generation_service/client.py b/google/ads/googleads/v24/services/services/asset_generation_service/client.py new file mode 100644 index 000000000..5a3b2ccef --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_generation_service/client.py @@ -0,0 +1,947 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import asset_generation_service +from .transports.base import ( + AssetGenerationServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AssetGenerationServiceGrpcTransport +from .transports.grpc_asyncio import AssetGenerationServiceGrpcAsyncIOTransport + + +class AssetGenerationServiceClientMeta(type): + """Metaclass for the AssetGenerationService 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[AssetGenerationServiceTransport]] + _transport_registry["grpc"] = AssetGenerationServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AssetGenerationServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AssetGenerationServiceTransport]: + """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 AssetGenerationServiceClient(metaclass=AssetGenerationServiceClientMeta): + """Service for generating new assets with generative AI.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AssetGenerationServiceClient: 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: + AssetGenerationServiceClient: 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) -> AssetGenerationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetGenerationServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_group_ad_path( + customer_id: str, + ad_group_id: str, + ad_id: str, + ) -> str: + """Returns a fully-qualified ad_group_ad string.""" + return ( + "customers/{customer_id}/adGroupAds/{ad_group_id}~{ad_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ad_id=ad_id, + ) + ) + + @staticmethod + def parse_ad_group_ad_path(path: str) -> Dict[str, str]: + """Parses a ad_group_ad path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAds/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_path( + customer_id: str, + asset_group_id: str, + ) -> str: + """Returns a fully-qualified asset_group string.""" + return "customers/{customer_id}/assetGroups/{asset_group_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + ) + + @staticmethod + def parse_asset_group_path(path: str) -> Dict[str, str]: + """Parses a asset_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroups/(?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 = ( + AssetGenerationServiceClient._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 = ( + AssetGenerationServiceClient._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 + ): + """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 = AssetGenerationServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AssetGenerationServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AssetGenerationServiceClient._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 = AssetGenerationServiceClient._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): + """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, + AssetGenerationServiceTransport, + Callable[..., AssetGenerationServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset generation service client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,AssetGenerationServiceTransport,Callable[..., AssetGenerationServiceTransport]]]): + 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 AssetGenerationServiceTransport 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, + ) = AssetGenerationServiceClient._read_environment_variables() + self._client_cert_source = ( + AssetGenerationServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + AssetGenerationServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AssetGenerationServiceTransport + ) + if transport_provided: + # transport is a AssetGenerationServiceTransport 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(AssetGenerationServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AssetGenerationServiceClient._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[AssetGenerationServiceTransport], + Callable[..., AssetGenerationServiceTransport], + ] = ( + AssetGenerationServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AssetGenerationServiceTransport], 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.ads.googleads.v24.services.AssetGenerationServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetGenerationService", + "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.ads.googleads.v24.services.AssetGenerationService", + "credentialsType": None, + } + ), + ) + + def generate_text( + self, + request: Optional[ + Union[asset_generation_service.GenerateTextRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_generation_service.GenerateTextResponse: + r"""Uses generative AI to generate text that can be used as assets + in a campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `AssetGenerationError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateTextRequest, dict]): + The request object. Request message for + [AssetGenerationService.GenerateText][google.ads.googleads.v24.services.AssetGenerationService.GenerateText] + 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.googleads.v24.services.types.GenerateTextResponse: + Response message for + [AssetGenerationService.GenerateText][google.ads.googleads.v24.services.AssetGenerationService.GenerateText] + + """ + # 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, asset_generation_service.GenerateTextRequest + ): + request = asset_generation_service.GenerateTextRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.generate_text] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_images( + self, + request: Optional[ + Union[asset_generation_service.GenerateImagesRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_generation_service.GenerateImagesResponse: + r"""Uses generative AI to generate images that can be used as assets + in a campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `AssetGenerationError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateImagesRequest, dict]): + The request object. Request message for + [AssetGenerationService.GenerateImages][google.ads.googleads.v24.services.AssetGenerationService.GenerateImages] + 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.googleads.v24.services.types.GenerateImagesResponse: + Response message for + [AssetGenerationService.GenerateImages][google.ads.googleads.v24.services.AssetGenerationService.GenerateImages] + + """ + # 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, asset_generation_service.GenerateImagesRequest + ): + request = asset_generation_service.GenerateImagesRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.generate_images] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AssetGenerationServiceClient": + 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() + + +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__ = ("AssetGenerationServiceClient",) diff --git a/google/ads/googleads/v24/services/services/asset_generation_service/transports/README.rst b/google/ads/googleads/v24/services/services/asset_generation_service/transports/README.rst new file mode 100644 index 000000000..7802b04f7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_generation_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AssetGenerationServiceTransport` is the ABC for all transports. +- public child `AssetGenerationServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AssetGenerationServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAssetGenerationServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AssetGenerationServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/asset_generation_service/transports/__init__.py b/google/ads/googleads/v24/services/services/asset_generation_service/transports/__init__.py new file mode 100644 index 000000000..51a5edebd --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_generation_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AssetGenerationServiceTransport +from .grpc import AssetGenerationServiceGrpcTransport +from .grpc_asyncio import AssetGenerationServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetGenerationServiceTransport]] +_transport_registry["grpc"] = AssetGenerationServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AssetGenerationServiceGrpcAsyncIOTransport + +__all__ = ( + "AssetGenerationServiceTransport", + "AssetGenerationServiceGrpcTransport", + "AssetGenerationServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/asset_generation_service/transports/base.py b/google/ads/googleads/v24/services/services/asset_generation_service/transports/base.py new file mode 100644 index 000000000..d209ce159 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_generation_service/transports/base.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import asset_generation_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 AssetGenerationServiceTransport(abc.ABC): + """Abstract transport class for AssetGenerationService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.generate_text: gapic_v1.method.wrap_method( + self.generate_text, + default_timeout=None, + client_info=client_info, + ), + self.generate_images: gapic_v1.method.wrap_method( + self.generate_images, + 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 generate_text( + self, + ) -> Callable[ + [asset_generation_service.GenerateTextRequest], + Union[ + asset_generation_service.GenerateTextResponse, + Awaitable[asset_generation_service.GenerateTextResponse], + ], + ]: + raise NotImplementedError() + + @property + def generate_images( + self, + ) -> Callable[ + [asset_generation_service.GenerateImagesRequest], + Union[ + asset_generation_service.GenerateImagesResponse, + Awaitable[asset_generation_service.GenerateImagesResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AssetGenerationServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_generation_service/transports/grpc.py b/google/ads/googleads/v24/services/services/asset_generation_service/transports/grpc.py new file mode 100644 index 000000000..b07c1996a --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_generation_service/transports/grpc.py @@ -0,0 +1,422 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import asset_generation_service +from .base import AssetGenerationServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AssetGenerationService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetGenerationService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetGenerationServiceGrpcTransport(AssetGenerationServiceTransport): + """gRPC backend transport for AssetGenerationService. + + Service for generating new assets with generative AI. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 generate_text( + self, + ) -> Callable[ + [asset_generation_service.GenerateTextRequest], + asset_generation_service.GenerateTextResponse, + ]: + r"""Return a callable for the generate text method over gRPC. + + Uses generative AI to generate text that can be used as assets + in a campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `AssetGenerationError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateTextRequest], + ~.GenerateTextResponse]: + 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 "generate_text" not in self._stubs: + self._stubs["generate_text"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetGenerationService/GenerateText", + request_serializer=asset_generation_service.GenerateTextRequest.serialize, + response_deserializer=asset_generation_service.GenerateTextResponse.deserialize, + ) + return self._stubs["generate_text"] + + @property + def generate_images( + self, + ) -> Callable[ + [asset_generation_service.GenerateImagesRequest], + asset_generation_service.GenerateImagesResponse, + ]: + r"""Return a callable for the generate images method over gRPC. + + Uses generative AI to generate images that can be used as assets + in a campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `AssetGenerationError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateImagesRequest], + ~.GenerateImagesResponse]: + 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 "generate_images" not in self._stubs: + self._stubs["generate_images"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetGenerationService/GenerateImages", + request_serializer=asset_generation_service.GenerateImagesRequest.serialize, + response_deserializer=asset_generation_service.GenerateImagesResponse.deserialize, + ) + return self._stubs["generate_images"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AssetGenerationServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_generation_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/asset_generation_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..c7392617b --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_generation_service/transports/grpc_asyncio.py @@ -0,0 +1,450 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import asset_generation_service +from .base import AssetGenerationServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AssetGenerationService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetGenerationService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetGenerationServiceGrpcAsyncIOTransport( + AssetGenerationServiceTransport +): + """gRPC AsyncIO backend transport for AssetGenerationService. + + Service for generating new assets with generative AI. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 generate_text( + self, + ) -> Callable[ + [asset_generation_service.GenerateTextRequest], + Awaitable[asset_generation_service.GenerateTextResponse], + ]: + r"""Return a callable for the generate text method over gRPC. + + Uses generative AI to generate text that can be used as assets + in a campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `AssetGenerationError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateTextRequest], + Awaitable[~.GenerateTextResponse]]: + 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 "generate_text" not in self._stubs: + self._stubs["generate_text"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetGenerationService/GenerateText", + request_serializer=asset_generation_service.GenerateTextRequest.serialize, + response_deserializer=asset_generation_service.GenerateTextResponse.deserialize, + ) + return self._stubs["generate_text"] + + @property + def generate_images( + self, + ) -> Callable[ + [asset_generation_service.GenerateImagesRequest], + Awaitable[asset_generation_service.GenerateImagesResponse], + ]: + r"""Return a callable for the generate images method over gRPC. + + Uses generative AI to generate images that can be used as assets + in a campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `AssetGenerationError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateImagesRequest], + Awaitable[~.GenerateImagesResponse]]: + 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 "generate_images" not in self._stubs: + self._stubs["generate_images"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetGenerationService/GenerateImages", + request_serializer=asset_generation_service.GenerateImagesRequest.serialize, + response_deserializer=asset_generation_service.GenerateImagesResponse.deserialize, + ) + return self._stubs["generate_images"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.generate_text: self._wrap_method( + self.generate_text, + default_timeout=None, + client_info=client_info, + ), + self.generate_images: self._wrap_method( + self.generate_images, + 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" + + +__all__ = ("AssetGenerationServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_group_asset_service/__init__.py b/google/ads/googleads/v24/services/services/asset_group_asset_service/__init__.py new file mode 100644 index 000000000..89160ead7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_asset_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AssetGroupAssetServiceClient +from .async_client import AssetGroupAssetServiceAsyncClient + +__all__ = ( + "AssetGroupAssetServiceClient", + "AssetGroupAssetServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/asset_group_asset_service/async_client.py b/google/ads/googleads/v24/services/services/asset_group_asset_service/async_client.py new file mode 100644 index 000000000..a64ca9863 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_asset_service/async_client.py @@ -0,0 +1,435 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import asset_group_asset_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AssetGroupAssetServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import AssetGroupAssetServiceClient + +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 AssetGroupAssetServiceAsyncClient: + """Service to manage asset group asset.""" + + _client: AssetGroupAssetServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AssetGroupAssetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AssetGroupAssetServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AssetGroupAssetServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AssetGroupAssetServiceClient._DEFAULT_UNIVERSE + + asset_path = staticmethod(AssetGroupAssetServiceClient.asset_path) + parse_asset_path = staticmethod( + AssetGroupAssetServiceClient.parse_asset_path + ) + asset_group_path = staticmethod( + AssetGroupAssetServiceClient.asset_group_path + ) + parse_asset_group_path = staticmethod( + AssetGroupAssetServiceClient.parse_asset_group_path + ) + asset_group_asset_path = staticmethod( + AssetGroupAssetServiceClient.asset_group_asset_path + ) + parse_asset_group_asset_path = staticmethod( + AssetGroupAssetServiceClient.parse_asset_group_asset_path + ) + common_billing_account_path = staticmethod( + AssetGroupAssetServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AssetGroupAssetServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AssetGroupAssetServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AssetGroupAssetServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AssetGroupAssetServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AssetGroupAssetServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AssetGroupAssetServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AssetGroupAssetServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AssetGroupAssetServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AssetGroupAssetServiceClient.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: + AssetGroupAssetServiceAsyncClient: The constructed client. + """ + return AssetGroupAssetServiceClient.from_service_account_info.__func__(AssetGroupAssetServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AssetGroupAssetServiceAsyncClient: The constructed client. + """ + return AssetGroupAssetServiceClient.from_service_account_file.__func__(AssetGroupAssetServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AssetGroupAssetServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AssetGroupAssetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetGroupAssetServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AssetGroupAssetServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AssetGroupAssetServiceTransport, + Callable[..., AssetGroupAssetServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset group asset 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,AssetGroupAssetServiceTransport,Callable[..., AssetGroupAssetServiceTransport]]]): + 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 AssetGroupAssetServiceTransport 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 = AssetGroupAssetServiceClient( + 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.ads.googleads.v24.services.AssetGroupAssetServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetGroupAssetService", + "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.ads.googleads.v24.services.AssetGroupAssetService", + "credentialsType": None, + } + ), + ) + + async def mutate_asset_group_assets( + self, + request: Optional[ + Union[asset_group_asset_service.MutateAssetGroupAssetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[asset_group_asset_service.AssetGroupAssetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_group_asset_service.MutateAssetGroupAssetsResponse: + r"""Creates, updates or removes asset group assets. + Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAssetGroupAssetsRequest, dict]]): + The request object. Request message for + [AssetGroupAssetService.MutateAssetGroupAssets][google.ads.googleads.v24.services.AssetGroupAssetService.MutateAssetGroupAssets]. + customer_id (:class:`str`): + Required. The ID of the customer + whose asset group assets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AssetGroupAssetOperation]`): + Required. The list of operations to + perform on individual asset group + assets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAssetGroupAssetsResponse: + Response message for an asset group + asset mutate. + + """ + # 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 = [customer_id, operations] + 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, asset_group_asset_service.MutateAssetGroupAssetsRequest + ): + request = asset_group_asset_service.MutateAssetGroupAssetsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_asset_group_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AssetGroupAssetServiceAsyncClient": + 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__ = ("AssetGroupAssetServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/asset_group_asset_service/client.py b/google/ads/googleads/v24/services/services/asset_group_asset_service/client.py new file mode 100644 index 000000000..58fa444c1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_asset_service/client.py @@ -0,0 +1,944 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import asset_group_asset_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AssetGroupAssetServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AssetGroupAssetServiceGrpcTransport +from .transports.grpc_asyncio import AssetGroupAssetServiceGrpcAsyncIOTransport + + +class AssetGroupAssetServiceClientMeta(type): + """Metaclass for the AssetGroupAssetService 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[AssetGroupAssetServiceTransport]] + _transport_registry["grpc"] = AssetGroupAssetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AssetGroupAssetServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AssetGroupAssetServiceTransport]: + """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 AssetGroupAssetServiceClient(metaclass=AssetGroupAssetServiceClientMeta): + """Service to manage asset group asset.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AssetGroupAssetServiceClient: 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: + AssetGroupAssetServiceClient: 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) -> AssetGroupAssetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetGroupAssetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def asset_path( + customer_id: str, + asset_id: str, + ) -> str: + """Returns a fully-qualified asset string.""" + return "customers/{customer_id}/assets/{asset_id}".format( + customer_id=customer_id, + asset_id=asset_id, + ) + + @staticmethod + def parse_asset_path(path: str) -> Dict[str, str]: + """Parses a asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assets/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_path( + customer_id: str, + asset_group_id: str, + ) -> str: + """Returns a fully-qualified asset_group string.""" + return "customers/{customer_id}/assetGroups/{asset_group_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + ) + + @staticmethod + def parse_asset_group_path(path: str) -> Dict[str, str]: + """Parses a asset_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_asset_path( + customer_id: str, + asset_group_id: str, + asset_id: str, + field_type: str, + ) -> str: + """Returns a fully-qualified asset_group_asset string.""" + return "customers/{customer_id}/assetGroupAssets/{asset_group_id}~{asset_id}~{field_type}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + asset_id=asset_id, + field_type=field_type, + ) + + @staticmethod + def parse_asset_group_asset_path(path: str) -> Dict[str, str]: + """Parses a asset_group_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroupAssets/(?P.+?)~(?P.+?)~(?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 = ( + AssetGroupAssetServiceClient._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 = ( + AssetGroupAssetServiceClient._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 + ): + """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 = AssetGroupAssetServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AssetGroupAssetServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AssetGroupAssetServiceClient._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 = AssetGroupAssetServiceClient._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): + """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, + AssetGroupAssetServiceTransport, + Callable[..., AssetGroupAssetServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset group asset 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,AssetGroupAssetServiceTransport,Callable[..., AssetGroupAssetServiceTransport]]]): + 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 AssetGroupAssetServiceTransport 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, + ) = AssetGroupAssetServiceClient._read_environment_variables() + self._client_cert_source = ( + AssetGroupAssetServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + AssetGroupAssetServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AssetGroupAssetServiceTransport + ) + if transport_provided: + # transport is a AssetGroupAssetServiceTransport 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(AssetGroupAssetServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AssetGroupAssetServiceClient._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[AssetGroupAssetServiceTransport], + Callable[..., AssetGroupAssetServiceTransport], + ] = ( + AssetGroupAssetServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AssetGroupAssetServiceTransport], 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.ads.googleads.v24.services.AssetGroupAssetServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetGroupAssetService", + "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.ads.googleads.v24.services.AssetGroupAssetService", + "credentialsType": None, + } + ), + ) + + def mutate_asset_group_assets( + self, + request: Optional[ + Union[asset_group_asset_service.MutateAssetGroupAssetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[asset_group_asset_service.AssetGroupAssetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_group_asset_service.MutateAssetGroupAssetsResponse: + r"""Creates, updates or removes asset group assets. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAssetGroupAssetsRequest, dict]): + The request object. Request message for + [AssetGroupAssetService.MutateAssetGroupAssets][google.ads.googleads.v24.services.AssetGroupAssetService.MutateAssetGroupAssets]. + customer_id (str): + Required. The ID of the customer + whose asset group assets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AssetGroupAssetOperation]): + Required. The list of operations to + perform on individual asset group + assets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAssetGroupAssetsResponse: + Response message for an asset group + asset mutate. + + """ + # 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 = [customer_id, operations] + 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, asset_group_asset_service.MutateAssetGroupAssetsRequest + ): + request = asset_group_asset_service.MutateAssetGroupAssetsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_asset_group_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AssetGroupAssetServiceClient": + 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() + + +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__ = ("AssetGroupAssetServiceClient",) diff --git a/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/README.rst b/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/README.rst new file mode 100644 index 000000000..e4d600f12 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AssetGroupAssetServiceTransport` is the ABC for all transports. +- public child `AssetGroupAssetServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AssetGroupAssetServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAssetGroupAssetServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AssetGroupAssetServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/__init__.py b/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/__init__.py new file mode 100644 index 000000000..31935167d --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AssetGroupAssetServiceTransport +from .grpc import AssetGroupAssetServiceGrpcTransport +from .grpc_asyncio import AssetGroupAssetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetGroupAssetServiceTransport]] +_transport_registry["grpc"] = AssetGroupAssetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AssetGroupAssetServiceGrpcAsyncIOTransport + +__all__ = ( + "AssetGroupAssetServiceTransport", + "AssetGroupAssetServiceGrpcTransport", + "AssetGroupAssetServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/base.py b/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/base.py new file mode 100644 index 000000000..df6786c50 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import asset_group_asset_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 AssetGroupAssetServiceTransport(abc.ABC): + """Abstract transport class for AssetGroupAssetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_asset_group_assets: gapic_v1.method.wrap_method( + self.mutate_asset_group_assets, + 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 mutate_asset_group_assets( + self, + ) -> Callable[ + [asset_group_asset_service.MutateAssetGroupAssetsRequest], + Union[ + asset_group_asset_service.MutateAssetGroupAssetsResponse, + Awaitable[asset_group_asset_service.MutateAssetGroupAssetsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AssetGroupAssetServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/grpc.py b/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/grpc.py new file mode 100644 index 000000000..e046d3b60 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/grpc.py @@ -0,0 +1,384 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import asset_group_asset_service +from .base import AssetGroupAssetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AssetGroupAssetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetGroupAssetService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetGroupAssetServiceGrpcTransport(AssetGroupAssetServiceTransport): + """gRPC backend transport for AssetGroupAssetService. + + Service to manage asset group asset. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_asset_group_assets( + self, + ) -> Callable[ + [asset_group_asset_service.MutateAssetGroupAssetsRequest], + asset_group_asset_service.MutateAssetGroupAssetsResponse, + ]: + r"""Return a callable for the mutate asset group assets method over gRPC. + + Creates, updates or removes asset group assets. + Operation statuses are returned. + + Returns: + Callable[[~.MutateAssetGroupAssetsRequest], + ~.MutateAssetGroupAssetsResponse]: + 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 "mutate_asset_group_assets" not in self._stubs: + self._stubs["mutate_asset_group_assets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetGroupAssetService/MutateAssetGroupAssets", + request_serializer=asset_group_asset_service.MutateAssetGroupAssetsRequest.serialize, + response_deserializer=asset_group_asset_service.MutateAssetGroupAssetsResponse.deserialize, + ) + ) + return self._stubs["mutate_asset_group_assets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AssetGroupAssetServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..f68ea4885 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_asset_service/transports/grpc_asyncio.py @@ -0,0 +1,407 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import asset_group_asset_service +from .base import AssetGroupAssetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AssetGroupAssetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetGroupAssetService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetGroupAssetServiceGrpcAsyncIOTransport( + AssetGroupAssetServiceTransport +): + """gRPC AsyncIO backend transport for AssetGroupAssetService. + + Service to manage asset group asset. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_asset_group_assets( + self, + ) -> Callable[ + [asset_group_asset_service.MutateAssetGroupAssetsRequest], + Awaitable[asset_group_asset_service.MutateAssetGroupAssetsResponse], + ]: + r"""Return a callable for the mutate asset group assets method over gRPC. + + Creates, updates or removes asset group assets. + Operation statuses are returned. + + Returns: + Callable[[~.MutateAssetGroupAssetsRequest], + Awaitable[~.MutateAssetGroupAssetsResponse]]: + 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 "mutate_asset_group_assets" not in self._stubs: + self._stubs["mutate_asset_group_assets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetGroupAssetService/MutateAssetGroupAssets", + request_serializer=asset_group_asset_service.MutateAssetGroupAssetsRequest.serialize, + response_deserializer=asset_group_asset_service.MutateAssetGroupAssetsResponse.deserialize, + ) + ) + return self._stubs["mutate_asset_group_assets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_asset_group_assets: self._wrap_method( + self.mutate_asset_group_assets, + 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" + + +__all__ = ("AssetGroupAssetServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/__init__.py b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/__init__.py new file mode 100644 index 000000000..32437e129 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AssetGroupListingGroupFilterServiceClient +from .async_client import AssetGroupListingGroupFilterServiceAsyncClient + +__all__ = ( + "AssetGroupListingGroupFilterServiceClient", + "AssetGroupListingGroupFilterServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/async_client.py b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/async_client.py new file mode 100644 index 000000000..bf5d047fa --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/async_client.py @@ -0,0 +1,458 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + asset_group_listing_group_filter_service, +) +from .transports.base import ( + AssetGroupListingGroupFilterServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import AssetGroupListingGroupFilterServiceClient + +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 AssetGroupListingGroupFilterServiceAsyncClient: + """Service to manage asset group listing group filter.""" + + _client: AssetGroupListingGroupFilterServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ( + AssetGroupListingGroupFilterServiceClient.DEFAULT_ENDPOINT + ) + DEFAULT_MTLS_ENDPOINT = ( + AssetGroupListingGroupFilterServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + AssetGroupListingGroupFilterServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ( + AssetGroupListingGroupFilterServiceClient._DEFAULT_UNIVERSE + ) + + asset_group_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.asset_group_path + ) + parse_asset_group_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.parse_asset_group_path + ) + asset_group_listing_group_filter_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.asset_group_listing_group_filter_path + ) + parse_asset_group_listing_group_filter_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.parse_asset_group_listing_group_filter_path + ) + shared_set_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.shared_set_path + ) + parse_shared_set_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.parse_shared_set_path + ) + common_billing_account_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AssetGroupListingGroupFilterServiceClient.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: + AssetGroupListingGroupFilterServiceAsyncClient: The constructed client. + """ + return AssetGroupListingGroupFilterServiceClient.from_service_account_info.__func__(AssetGroupListingGroupFilterServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AssetGroupListingGroupFilterServiceAsyncClient: The constructed client. + """ + return AssetGroupListingGroupFilterServiceClient.from_service_account_file.__func__(AssetGroupListingGroupFilterServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AssetGroupListingGroupFilterServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AssetGroupListingGroupFilterServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetGroupListingGroupFilterServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + AssetGroupListingGroupFilterServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AssetGroupListingGroupFilterServiceTransport, + Callable[..., AssetGroupListingGroupFilterServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset group listing group filter 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,AssetGroupListingGroupFilterServiceTransport,Callable[..., AssetGroupListingGroupFilterServiceTransport]]]): + 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 AssetGroupListingGroupFilterServiceTransport 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 = AssetGroupListingGroupFilterServiceClient( + 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.ads.googleads.v24.services.AssetGroupListingGroupFilterServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetGroupListingGroupFilterService", + "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.ads.googleads.v24.services.AssetGroupListingGroupFilterService", + "credentialsType": None, + } + ), + ) + + async def mutate_asset_group_listing_group_filters( + self, + request: Optional[ + Union[ + asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + asset_group_listing_group_filter_service.AssetGroupListingGroupFilterOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersResponse + ): + r"""Creates, updates or removes asset group listing group + filters. Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAssetGroupListingGroupFiltersRequest, dict]]): + The request object. Request message for + [AssetGroupListingGroupFilterService.MutateAssetGroupListingGroupFilters][google.ads.googleads.v24.services.AssetGroupListingGroupFilterService.MutateAssetGroupListingGroupFilters]. + partial_failure is not supported because the tree needs + to be validated together. + customer_id (:class:`str`): + Required. The ID of the customer + whose asset group listing group filters + are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AssetGroupListingGroupFilterOperation]`): + Required. The list of operations to + perform on individual asset group + listing group filters. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAssetGroupListingGroupFiltersResponse: + Response message for an asset group + listing group filter mutate. + + """ + # 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 = [customer_id, operations] + 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, + asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersRequest, + ): + request = asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_asset_group_listing_group_filters + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__( + self, + ) -> "AssetGroupListingGroupFilterServiceAsyncClient": + 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__ = ("AssetGroupListingGroupFilterServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/client.py b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/client.py new file mode 100644 index 000000000..dd16a69a9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/client.py @@ -0,0 +1,973 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + asset_group_listing_group_filter_service, +) +from .transports.base import ( + AssetGroupListingGroupFilterServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AssetGroupListingGroupFilterServiceGrpcTransport +from .transports.grpc_asyncio import ( + AssetGroupListingGroupFilterServiceGrpcAsyncIOTransport, +) + + +class AssetGroupListingGroupFilterServiceClientMeta(type): + """Metaclass for the AssetGroupListingGroupFilterService 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[AssetGroupListingGroupFilterServiceTransport]] + _transport_registry["grpc"] = ( + AssetGroupListingGroupFilterServiceGrpcTransport + ) + _transport_registry["grpc_asyncio"] = ( + AssetGroupListingGroupFilterServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AssetGroupListingGroupFilterServiceTransport]: + """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 AssetGroupListingGroupFilterServiceClient( + metaclass=AssetGroupListingGroupFilterServiceClientMeta +): + """Service to manage asset group listing group filter.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AssetGroupListingGroupFilterServiceClient: 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: + AssetGroupListingGroupFilterServiceClient: 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) -> AssetGroupListingGroupFilterServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetGroupListingGroupFilterServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def asset_group_path( + customer_id: str, + asset_group_id: str, + ) -> str: + """Returns a fully-qualified asset_group string.""" + return "customers/{customer_id}/assetGroups/{asset_group_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + ) + + @staticmethod + def parse_asset_group_path(path: str) -> Dict[str, str]: + """Parses a asset_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_listing_group_filter_path( + customer_id: str, + asset_group_id: str, + listing_group_filter_id: str, + ) -> str: + """Returns a fully-qualified asset_group_listing_group_filter string.""" + return "customers/{customer_id}/assetGroupListingGroupFilters/{asset_group_id}~{listing_group_filter_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + listing_group_filter_id=listing_group_filter_id, + ) + + @staticmethod + def parse_asset_group_listing_group_filter_path( + path: str, + ) -> Dict[str, str]: + """Parses a asset_group_listing_group_filter path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroupListingGroupFilters/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def shared_set_path( + customer_id: str, + shared_set_id: str, + ) -> str: + """Returns a fully-qualified shared_set string.""" + return "customers/{customer_id}/sharedSets/{shared_set_id}".format( + customer_id=customer_id, + shared_set_id=shared_set_id, + ) + + @staticmethod + def parse_shared_set_path(path: str) -> Dict[str, str]: + """Parses a shared_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/sharedSets/(?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 = ( + AssetGroupListingGroupFilterServiceClient._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 = ( + AssetGroupListingGroupFilterServiceClient._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 + ): + """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 = ( + AssetGroupListingGroupFilterServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + AssetGroupListingGroupFilterServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = AssetGroupListingGroupFilterServiceClient._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 = ( + AssetGroupListingGroupFilterServiceClient._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): + """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, + AssetGroupListingGroupFilterServiceTransport, + Callable[..., AssetGroupListingGroupFilterServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset group listing group filter 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,AssetGroupListingGroupFilterServiceTransport,Callable[..., AssetGroupListingGroupFilterServiceTransport]]]): + 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 AssetGroupListingGroupFilterServiceTransport 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, + ) = ( + AssetGroupListingGroupFilterServiceClient._read_environment_variables() + ) + self._client_cert_source = ( + AssetGroupListingGroupFilterServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + AssetGroupListingGroupFilterServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AssetGroupListingGroupFilterServiceTransport + ) + if transport_provided: + # transport is a AssetGroupListingGroupFilterServiceTransport 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( + AssetGroupListingGroupFilterServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AssetGroupListingGroupFilterServiceClient._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[AssetGroupListingGroupFilterServiceTransport], + Callable[..., AssetGroupListingGroupFilterServiceTransport], + ] = ( + AssetGroupListingGroupFilterServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AssetGroupListingGroupFilterServiceTransport], + 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.ads.googleads.v24.services.AssetGroupListingGroupFilterServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetGroupListingGroupFilterService", + "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.ads.googleads.v24.services.AssetGroupListingGroupFilterService", + "credentialsType": None, + } + ), + ) + + def mutate_asset_group_listing_group_filters( + self, + request: Optional[ + Union[ + asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + asset_group_listing_group_filter_service.AssetGroupListingGroupFilterOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersResponse + ): + r"""Creates, updates or removes asset group listing group + filters. Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAssetGroupListingGroupFiltersRequest, dict]): + The request object. Request message for + [AssetGroupListingGroupFilterService.MutateAssetGroupListingGroupFilters][google.ads.googleads.v24.services.AssetGroupListingGroupFilterService.MutateAssetGroupListingGroupFilters]. + partial_failure is not supported because the tree needs + to be validated together. + customer_id (str): + Required. The ID of the customer + whose asset group listing group filters + are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AssetGroupListingGroupFilterOperation]): + Required. The list of operations to + perform on individual asset group + listing group filters. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAssetGroupListingGroupFiltersResponse: + Response message for an asset group + listing group filter mutate. + + """ + # 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 = [customer_id, operations] + 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, + asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersRequest, + ): + request = asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_asset_group_listing_group_filters + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AssetGroupListingGroupFilterServiceClient": + 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() + + +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__ = ("AssetGroupListingGroupFilterServiceClient",) diff --git a/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/README.rst b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/README.rst new file mode 100644 index 000000000..dce390062 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AssetGroupListingGroupFilterServiceTransport` is the ABC for all transports. +- public child `AssetGroupListingGroupFilterServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AssetGroupListingGroupFilterServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAssetGroupListingGroupFilterServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AssetGroupListingGroupFilterServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/__init__.py b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/__init__.py new file mode 100644 index 000000000..f84845af1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/__init__.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AssetGroupListingGroupFilterServiceTransport +from .grpc import AssetGroupListingGroupFilterServiceGrpcTransport +from .grpc_asyncio import ( + AssetGroupListingGroupFilterServiceGrpcAsyncIOTransport, +) + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetGroupListingGroupFilterServiceTransport]] +_transport_registry["grpc"] = AssetGroupListingGroupFilterServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + AssetGroupListingGroupFilterServiceGrpcAsyncIOTransport +) + +__all__ = ( + "AssetGroupListingGroupFilterServiceTransport", + "AssetGroupListingGroupFilterServiceGrpcTransport", + "AssetGroupListingGroupFilterServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/base.py b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/base.py new file mode 100644 index 000000000..c90e35402 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + asset_group_listing_group_filter_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 AssetGroupListingGroupFilterServiceTransport(abc.ABC): + """Abstract transport class for AssetGroupListingGroupFilterService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_asset_group_listing_group_filters: gapic_v1.method.wrap_method( + self.mutate_asset_group_listing_group_filters, + 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 mutate_asset_group_listing_group_filters( + self, + ) -> Callable[ + [ + asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersRequest + ], + Union[ + asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersResponse, + Awaitable[ + asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AssetGroupListingGroupFilterServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/grpc.py b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/grpc.py new file mode 100644 index 000000000..2d612ad66 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/grpc.py @@ -0,0 +1,394 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + asset_group_listing_group_filter_service, +) +from .base import ( + AssetGroupListingGroupFilterServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.AssetGroupListingGroupFilterService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetGroupListingGroupFilterService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetGroupListingGroupFilterServiceGrpcTransport( + AssetGroupListingGroupFilterServiceTransport +): + """gRPC backend transport for AssetGroupListingGroupFilterService. + + Service to manage asset group listing group filter. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_asset_group_listing_group_filters( + self, + ) -> Callable[ + [ + asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersRequest + ], + asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersResponse, + ]: + r"""Return a callable for the mutate asset group listing + group filters method over gRPC. + + Creates, updates or removes asset group listing group + filters. Operation statuses are returned. + + Returns: + Callable[[~.MutateAssetGroupListingGroupFiltersRequest], + ~.MutateAssetGroupListingGroupFiltersResponse]: + 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 "mutate_asset_group_listing_group_filters" not in self._stubs: + self._stubs["mutate_asset_group_listing_group_filters"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetGroupListingGroupFilterService/MutateAssetGroupListingGroupFilters", + request_serializer=asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersRequest.serialize, + response_deserializer=asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersResponse.deserialize, + ) + ) + return self._stubs["mutate_asset_group_listing_group_filters"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AssetGroupListingGroupFilterServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..dacbf3671 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_listing_group_filter_service/transports/grpc_asyncio.py @@ -0,0 +1,417 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + asset_group_listing_group_filter_service, +) +from .base import ( + AssetGroupListingGroupFilterServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.AssetGroupListingGroupFilterService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetGroupListingGroupFilterService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetGroupListingGroupFilterServiceGrpcAsyncIOTransport( + AssetGroupListingGroupFilterServiceTransport +): + """gRPC AsyncIO backend transport for AssetGroupListingGroupFilterService. + + Service to manage asset group listing group filter. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_asset_group_listing_group_filters( + self, + ) -> Callable[ + [ + asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersRequest + ], + Awaitable[ + asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersResponse + ], + ]: + r"""Return a callable for the mutate asset group listing + group filters method over gRPC. + + Creates, updates or removes asset group listing group + filters. Operation statuses are returned. + + Returns: + Callable[[~.MutateAssetGroupListingGroupFiltersRequest], + Awaitable[~.MutateAssetGroupListingGroupFiltersResponse]]: + 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 "mutate_asset_group_listing_group_filters" not in self._stubs: + self._stubs["mutate_asset_group_listing_group_filters"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetGroupListingGroupFilterService/MutateAssetGroupListingGroupFilters", + request_serializer=asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersRequest.serialize, + response_deserializer=asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersResponse.deserialize, + ) + ) + return self._stubs["mutate_asset_group_listing_group_filters"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_asset_group_listing_group_filters: self._wrap_method( + self.mutate_asset_group_listing_group_filters, + 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" + + +__all__ = ("AssetGroupListingGroupFilterServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_group_service/__init__.py b/google/ads/googleads/v24/services/services/asset_group_service/__init__.py new file mode 100644 index 000000000..3ffee9a02 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AssetGroupServiceClient +from .async_client import AssetGroupServiceAsyncClient + +__all__ = ( + "AssetGroupServiceClient", + "AssetGroupServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/asset_group_service/async_client.py b/google/ads/googleads/v24/services/services/asset_group_service/async_client.py new file mode 100644 index 000000000..f95bf8ea1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_service/async_client.py @@ -0,0 +1,420 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import asset_group_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AssetGroupServiceTransport, DEFAULT_CLIENT_INFO +from .client import AssetGroupServiceClient + +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 AssetGroupServiceAsyncClient: + """Service to manage asset group""" + + _client: AssetGroupServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AssetGroupServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AssetGroupServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AssetGroupServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AssetGroupServiceClient._DEFAULT_UNIVERSE + + asset_group_path = staticmethod(AssetGroupServiceClient.asset_group_path) + parse_asset_group_path = staticmethod( + AssetGroupServiceClient.parse_asset_group_path + ) + campaign_path = staticmethod(AssetGroupServiceClient.campaign_path) + parse_campaign_path = staticmethod( + AssetGroupServiceClient.parse_campaign_path + ) + common_billing_account_path = staticmethod( + AssetGroupServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AssetGroupServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AssetGroupServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AssetGroupServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AssetGroupServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AssetGroupServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AssetGroupServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AssetGroupServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AssetGroupServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AssetGroupServiceClient.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: + AssetGroupServiceAsyncClient: The constructed client. + """ + return AssetGroupServiceClient.from_service_account_info.__func__(AssetGroupServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AssetGroupServiceAsyncClient: The constructed client. + """ + return AssetGroupServiceClient.from_service_account_file.__func__(AssetGroupServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AssetGroupServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AssetGroupServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetGroupServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AssetGroupServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AssetGroupServiceTransport, + Callable[..., AssetGroupServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset group 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,AssetGroupServiceTransport,Callable[..., AssetGroupServiceTransport]]]): + 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 AssetGroupServiceTransport 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 = AssetGroupServiceClient( + 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.ads.googleads.v24.services.AssetGroupServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetGroupService", + "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.ads.googleads.v24.services.AssetGroupService", + "credentialsType": None, + } + ), + ) + + async def mutate_asset_groups( + self, + request: Optional[ + Union[asset_group_service.MutateAssetGroupsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[asset_group_service.AssetGroupOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_group_service.MutateAssetGroupsResponse: + r"""Creates, updates or removes asset groups. Operation + statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAssetGroupsRequest, dict]]): + The request object. Request message for + [AssetGroupService.MutateAssetGroups][google.ads.googleads.v24.services.AssetGroupService.MutateAssetGroups]. + customer_id (:class:`str`): + Required. The ID of the customer + whose asset groups are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AssetGroupOperation]`): + Required. The list of operations to + perform on individual asset groups. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAssetGroupsResponse: + Response message for an asset group + mutate. + + """ + # 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 = [customer_id, operations] + 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, asset_group_service.MutateAssetGroupsRequest + ): + request = asset_group_service.MutateAssetGroupsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_asset_groups + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AssetGroupServiceAsyncClient": + 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__ = ("AssetGroupServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/asset_group_service/client.py b/google/ads/googleads/v24/services/services/asset_group_service/client.py new file mode 100644 index 000000000..23266b567 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_service/client.py @@ -0,0 +1,902 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import asset_group_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AssetGroupServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import AssetGroupServiceGrpcTransport +from .transports.grpc_asyncio import AssetGroupServiceGrpcAsyncIOTransport + + +class AssetGroupServiceClientMeta(type): + """Metaclass for the AssetGroupService 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[AssetGroupServiceTransport]] + _transport_registry["grpc"] = AssetGroupServiceGrpcTransport + _transport_registry["grpc_asyncio"] = AssetGroupServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AssetGroupServiceTransport]: + """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 AssetGroupServiceClient(metaclass=AssetGroupServiceClientMeta): + """Service to manage asset group""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AssetGroupServiceClient: 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: + AssetGroupServiceClient: 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) -> AssetGroupServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetGroupServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def asset_group_path( + customer_id: str, + asset_group_id: str, + ) -> str: + """Returns a fully-qualified asset_group string.""" + return "customers/{customer_id}/assetGroups/{asset_group_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + ) + + @staticmethod + def parse_asset_group_path(path: str) -> Dict[str, str]: + """Parses a asset_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?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 = AssetGroupServiceClient._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 = AssetGroupServiceClient._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 + ): + """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 = AssetGroupServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AssetGroupServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AssetGroupServiceClient._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 = AssetGroupServiceClient._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): + """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, + AssetGroupServiceTransport, + Callable[..., AssetGroupServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset group 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,AssetGroupServiceTransport,Callable[..., AssetGroupServiceTransport]]]): + 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 AssetGroupServiceTransport 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, + ) = AssetGroupServiceClient._read_environment_variables() + self._client_cert_source = ( + AssetGroupServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = AssetGroupServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AssetGroupServiceTransport) + if transport_provided: + # transport is a AssetGroupServiceTransport 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(AssetGroupServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AssetGroupServiceClient._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[AssetGroupServiceTransport], + Callable[..., AssetGroupServiceTransport], + ] = ( + AssetGroupServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., AssetGroupServiceTransport], 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.ads.googleads.v24.services.AssetGroupServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetGroupService", + "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.ads.googleads.v24.services.AssetGroupService", + "credentialsType": None, + } + ), + ) + + def mutate_asset_groups( + self, + request: Optional[ + Union[asset_group_service.MutateAssetGroupsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[asset_group_service.AssetGroupOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_group_service.MutateAssetGroupsResponse: + r"""Creates, updates or removes asset groups. Operation + statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAssetGroupsRequest, dict]): + The request object. Request message for + [AssetGroupService.MutateAssetGroups][google.ads.googleads.v24.services.AssetGroupService.MutateAssetGroups]. + customer_id (str): + Required. The ID of the customer + whose asset groups are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AssetGroupOperation]): + Required. The list of operations to + perform on individual asset groups. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAssetGroupsResponse: + Response message for an asset group + mutate. + + """ + # 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 = [customer_id, operations] + 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, asset_group_service.MutateAssetGroupsRequest + ): + request = asset_group_service.MutateAssetGroupsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_asset_groups + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AssetGroupServiceClient": + 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() + + +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__ = ("AssetGroupServiceClient",) diff --git a/google/ads/googleads/v24/services/services/asset_group_service/transports/README.rst b/google/ads/googleads/v24/services/services/asset_group_service/transports/README.rst new file mode 100644 index 000000000..1a505e0a5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AssetGroupServiceTransport` is the ABC for all transports. +- public child `AssetGroupServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AssetGroupServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAssetGroupServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AssetGroupServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/asset_group_service/transports/__init__.py b/google/ads/googleads/v24/services/services/asset_group_service/transports/__init__.py new file mode 100644 index 000000000..a84a70dd1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AssetGroupServiceTransport +from .grpc import AssetGroupServiceGrpcTransport +from .grpc_asyncio import AssetGroupServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetGroupServiceTransport]] +_transport_registry["grpc"] = AssetGroupServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AssetGroupServiceGrpcAsyncIOTransport + +__all__ = ( + "AssetGroupServiceTransport", + "AssetGroupServiceGrpcTransport", + "AssetGroupServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/asset_group_service/transports/base.py b/google/ads/googleads/v24/services/services/asset_group_service/transports/base.py new file mode 100644 index 000000000..2674ee203 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import asset_group_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 AssetGroupServiceTransport(abc.ABC): + """Abstract transport class for AssetGroupService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_asset_groups: gapic_v1.method.wrap_method( + self.mutate_asset_groups, + 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 mutate_asset_groups( + self, + ) -> Callable[ + [asset_group_service.MutateAssetGroupsRequest], + Union[ + asset_group_service.MutateAssetGroupsResponse, + Awaitable[asset_group_service.MutateAssetGroupsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AssetGroupServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_group_service/transports/grpc.py b/google/ads/googleads/v24/services/services/asset_group_service/transports/grpc.py new file mode 100644 index 000000000..6004dd736 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_service/transports/grpc.py @@ -0,0 +1,384 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import asset_group_service +from .base import AssetGroupServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AssetGroupService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetGroupService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetGroupServiceGrpcTransport(AssetGroupServiceTransport): + """gRPC backend transport for AssetGroupService. + + Service to manage asset group + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_asset_groups( + self, + ) -> Callable[ + [asset_group_service.MutateAssetGroupsRequest], + asset_group_service.MutateAssetGroupsResponse, + ]: + r"""Return a callable for the mutate asset groups method over gRPC. + + Creates, updates or removes asset groups. Operation + statuses are returned. + + Returns: + Callable[[~.MutateAssetGroupsRequest], + ~.MutateAssetGroupsResponse]: + 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 "mutate_asset_groups" not in self._stubs: + self._stubs["mutate_asset_groups"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetGroupService/MutateAssetGroups", + request_serializer=asset_group_service.MutateAssetGroupsRequest.serialize, + response_deserializer=asset_group_service.MutateAssetGroupsResponse.deserialize, + ) + ) + return self._stubs["mutate_asset_groups"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AssetGroupServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_group_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/asset_group_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..33d9e0dbd --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_service/transports/grpc_asyncio.py @@ -0,0 +1,405 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import asset_group_service +from .base import AssetGroupServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AssetGroupService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetGroupService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetGroupServiceGrpcAsyncIOTransport(AssetGroupServiceTransport): + """gRPC AsyncIO backend transport for AssetGroupService. + + Service to manage asset group + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_asset_groups( + self, + ) -> Callable[ + [asset_group_service.MutateAssetGroupsRequest], + Awaitable[asset_group_service.MutateAssetGroupsResponse], + ]: + r"""Return a callable for the mutate asset groups method over gRPC. + + Creates, updates or removes asset groups. Operation + statuses are returned. + + Returns: + Callable[[~.MutateAssetGroupsRequest], + Awaitable[~.MutateAssetGroupsResponse]]: + 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 "mutate_asset_groups" not in self._stubs: + self._stubs["mutate_asset_groups"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetGroupService/MutateAssetGroups", + request_serializer=asset_group_service.MutateAssetGroupsRequest.serialize, + response_deserializer=asset_group_service.MutateAssetGroupsResponse.deserialize, + ) + ) + return self._stubs["mutate_asset_groups"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_asset_groups: self._wrap_method( + self.mutate_asset_groups, + 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" + + +__all__ = ("AssetGroupServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_group_signal_service/__init__.py b/google/ads/googleads/v24/services/services/asset_group_signal_service/__init__.py new file mode 100644 index 000000000..a611e4703 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_signal_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AssetGroupSignalServiceClient +from .async_client import AssetGroupSignalServiceAsyncClient + +__all__ = ( + "AssetGroupSignalServiceClient", + "AssetGroupSignalServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/asset_group_signal_service/async_client.py b/google/ads/googleads/v24/services/services/asset_group_signal_service/async_client.py new file mode 100644 index 000000000..3b9210d56 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_signal_service/async_client.py @@ -0,0 +1,435 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import asset_group_signal_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AssetGroupSignalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import AssetGroupSignalServiceClient + +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 AssetGroupSignalServiceAsyncClient: + """Service to manage asset group signal.""" + + _client: AssetGroupSignalServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AssetGroupSignalServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AssetGroupSignalServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AssetGroupSignalServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AssetGroupSignalServiceClient._DEFAULT_UNIVERSE + + asset_group_path = staticmethod( + AssetGroupSignalServiceClient.asset_group_path + ) + parse_asset_group_path = staticmethod( + AssetGroupSignalServiceClient.parse_asset_group_path + ) + asset_group_signal_path = staticmethod( + AssetGroupSignalServiceClient.asset_group_signal_path + ) + parse_asset_group_signal_path = staticmethod( + AssetGroupSignalServiceClient.parse_asset_group_signal_path + ) + common_billing_account_path = staticmethod( + AssetGroupSignalServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AssetGroupSignalServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AssetGroupSignalServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AssetGroupSignalServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AssetGroupSignalServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AssetGroupSignalServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AssetGroupSignalServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AssetGroupSignalServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AssetGroupSignalServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AssetGroupSignalServiceClient.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: + AssetGroupSignalServiceAsyncClient: The constructed client. + """ + return AssetGroupSignalServiceClient.from_service_account_info.__func__(AssetGroupSignalServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AssetGroupSignalServiceAsyncClient: The constructed client. + """ + return AssetGroupSignalServiceClient.from_service_account_file.__func__(AssetGroupSignalServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AssetGroupSignalServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AssetGroupSignalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetGroupSignalServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AssetGroupSignalServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AssetGroupSignalServiceTransport, + Callable[..., AssetGroupSignalServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset group signal 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,AssetGroupSignalServiceTransport,Callable[..., AssetGroupSignalServiceTransport]]]): + 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 AssetGroupSignalServiceTransport 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 = AssetGroupSignalServiceClient( + 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.ads.googleads.v24.services.AssetGroupSignalServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetGroupSignalService", + "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.ads.googleads.v24.services.AssetGroupSignalService", + "credentialsType": None, + } + ), + ) + + async def mutate_asset_group_signals( + self, + request: Optional[ + Union[ + asset_group_signal_service.MutateAssetGroupSignalsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + asset_group_signal_service.AssetGroupSignalOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_group_signal_service.MutateAssetGroupSignalsResponse: + r"""Creates or removes asset group signals. Operation + statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAssetGroupSignalsRequest, dict]]): + The request object. Request message for + [AssetGroupSignalService.MutateAssetGroupSignals][google.ads.googleads.v24.services.AssetGroupSignalService.MutateAssetGroupSignals]. + customer_id (:class:`str`): + Required. The ID of the customer + whose asset group signals are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AssetGroupSignalOperation]`): + Required. The list of operations to + perform on individual asset group + signals. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAssetGroupSignalsResponse: + Response message for an asset group + signal mutate. + + """ + # 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 = [customer_id, operations] + 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, asset_group_signal_service.MutateAssetGroupSignalsRequest + ): + request = asset_group_signal_service.MutateAssetGroupSignalsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_asset_group_signals + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AssetGroupSignalServiceAsyncClient": + 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__ = ("AssetGroupSignalServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/asset_group_signal_service/client.py b/google/ads/googleads/v24/services/services/asset_group_signal_service/client.py new file mode 100644 index 000000000..987c0259b --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_signal_service/client.py @@ -0,0 +1,929 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import asset_group_signal_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AssetGroupSignalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AssetGroupSignalServiceGrpcTransport +from .transports.grpc_asyncio import AssetGroupSignalServiceGrpcAsyncIOTransport + + +class AssetGroupSignalServiceClientMeta(type): + """Metaclass for the AssetGroupSignalService 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[AssetGroupSignalServiceTransport]] + _transport_registry["grpc"] = AssetGroupSignalServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AssetGroupSignalServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AssetGroupSignalServiceTransport]: + """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 AssetGroupSignalServiceClient( + metaclass=AssetGroupSignalServiceClientMeta +): + """Service to manage asset group signal.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AssetGroupSignalServiceClient: 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: + AssetGroupSignalServiceClient: 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) -> AssetGroupSignalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetGroupSignalServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def asset_group_path( + customer_id: str, + asset_group_id: str, + ) -> str: + """Returns a fully-qualified asset_group string.""" + return "customers/{customer_id}/assetGroups/{asset_group_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + ) + + @staticmethod + def parse_asset_group_path(path: str) -> Dict[str, str]: + """Parses a asset_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_signal_path( + customer_id: str, + asset_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified asset_group_signal string.""" + return "customers/{customer_id}/assetGroupSignals/{asset_group_id}~{criterion_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_asset_group_signal_path(path: str) -> Dict[str, str]: + """Parses a asset_group_signal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroupSignals/(?P.+?)~(?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 = ( + AssetGroupSignalServiceClient._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 = ( + AssetGroupSignalServiceClient._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 + ): + """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 = AssetGroupSignalServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AssetGroupSignalServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AssetGroupSignalServiceClient._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 = AssetGroupSignalServiceClient._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): + """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, + AssetGroupSignalServiceTransport, + Callable[..., AssetGroupSignalServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset group signal 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,AssetGroupSignalServiceTransport,Callable[..., AssetGroupSignalServiceTransport]]]): + 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 AssetGroupSignalServiceTransport 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, + ) = AssetGroupSignalServiceClient._read_environment_variables() + self._client_cert_source = ( + AssetGroupSignalServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + AssetGroupSignalServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AssetGroupSignalServiceTransport + ) + if transport_provided: + # transport is a AssetGroupSignalServiceTransport 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(AssetGroupSignalServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AssetGroupSignalServiceClient._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[AssetGroupSignalServiceTransport], + Callable[..., AssetGroupSignalServiceTransport], + ] = ( + AssetGroupSignalServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AssetGroupSignalServiceTransport], 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.ads.googleads.v24.services.AssetGroupSignalServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetGroupSignalService", + "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.ads.googleads.v24.services.AssetGroupSignalService", + "credentialsType": None, + } + ), + ) + + def mutate_asset_group_signals( + self, + request: Optional[ + Union[ + asset_group_signal_service.MutateAssetGroupSignalsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + asset_group_signal_service.AssetGroupSignalOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_group_signal_service.MutateAssetGroupSignalsResponse: + r"""Creates or removes asset group signals. Operation + statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAssetGroupSignalsRequest, dict]): + The request object. Request message for + [AssetGroupSignalService.MutateAssetGroupSignals][google.ads.googleads.v24.services.AssetGroupSignalService.MutateAssetGroupSignals]. + customer_id (str): + Required. The ID of the customer + whose asset group signals are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AssetGroupSignalOperation]): + Required. The list of operations to + perform on individual asset group + signals. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAssetGroupSignalsResponse: + Response message for an asset group + signal mutate. + + """ + # 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 = [customer_id, operations] + 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, asset_group_signal_service.MutateAssetGroupSignalsRequest + ): + request = asset_group_signal_service.MutateAssetGroupSignalsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_asset_group_signals + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AssetGroupSignalServiceClient": + 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() + + +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__ = ("AssetGroupSignalServiceClient",) diff --git a/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/README.rst b/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/README.rst new file mode 100644 index 000000000..5c48ae9be --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AssetGroupSignalServiceTransport` is the ABC for all transports. +- public child `AssetGroupSignalServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AssetGroupSignalServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAssetGroupSignalServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AssetGroupSignalServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/__init__.py b/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/__init__.py new file mode 100644 index 000000000..7fdbf900c --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AssetGroupSignalServiceTransport +from .grpc import AssetGroupSignalServiceGrpcTransport +from .grpc_asyncio import AssetGroupSignalServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetGroupSignalServiceTransport]] +_transport_registry["grpc"] = AssetGroupSignalServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + AssetGroupSignalServiceGrpcAsyncIOTransport +) + +__all__ = ( + "AssetGroupSignalServiceTransport", + "AssetGroupSignalServiceGrpcTransport", + "AssetGroupSignalServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/base.py b/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/base.py new file mode 100644 index 000000000..76e3adf5d --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import asset_group_signal_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 AssetGroupSignalServiceTransport(abc.ABC): + """Abstract transport class for AssetGroupSignalService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_asset_group_signals: gapic_v1.method.wrap_method( + self.mutate_asset_group_signals, + 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 mutate_asset_group_signals( + self, + ) -> Callable[ + [asset_group_signal_service.MutateAssetGroupSignalsRequest], + Union[ + asset_group_signal_service.MutateAssetGroupSignalsResponse, + Awaitable[ + asset_group_signal_service.MutateAssetGroupSignalsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AssetGroupSignalServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/grpc.py b/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/grpc.py new file mode 100644 index 000000000..194faa9fd --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/grpc.py @@ -0,0 +1,384 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import asset_group_signal_service +from .base import AssetGroupSignalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AssetGroupSignalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetGroupSignalService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetGroupSignalServiceGrpcTransport(AssetGroupSignalServiceTransport): + """gRPC backend transport for AssetGroupSignalService. + + Service to manage asset group signal. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_asset_group_signals( + self, + ) -> Callable[ + [asset_group_signal_service.MutateAssetGroupSignalsRequest], + asset_group_signal_service.MutateAssetGroupSignalsResponse, + ]: + r"""Return a callable for the mutate asset group signals method over gRPC. + + Creates or removes asset group signals. Operation + statuses are returned. + + Returns: + Callable[[~.MutateAssetGroupSignalsRequest], + ~.MutateAssetGroupSignalsResponse]: + 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 "mutate_asset_group_signals" not in self._stubs: + self._stubs["mutate_asset_group_signals"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetGroupSignalService/MutateAssetGroupSignals", + request_serializer=asset_group_signal_service.MutateAssetGroupSignalsRequest.serialize, + response_deserializer=asset_group_signal_service.MutateAssetGroupSignalsResponse.deserialize, + ) + ) + return self._stubs["mutate_asset_group_signals"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AssetGroupSignalServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..8e6cc4335 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_group_signal_service/transports/grpc_asyncio.py @@ -0,0 +1,407 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import asset_group_signal_service +from .base import AssetGroupSignalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AssetGroupSignalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetGroupSignalService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetGroupSignalServiceGrpcAsyncIOTransport( + AssetGroupSignalServiceTransport +): + """gRPC AsyncIO backend transport for AssetGroupSignalService. + + Service to manage asset group signal. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_asset_group_signals( + self, + ) -> Callable[ + [asset_group_signal_service.MutateAssetGroupSignalsRequest], + Awaitable[asset_group_signal_service.MutateAssetGroupSignalsResponse], + ]: + r"""Return a callable for the mutate asset group signals method over gRPC. + + Creates or removes asset group signals. Operation + statuses are returned. + + Returns: + Callable[[~.MutateAssetGroupSignalsRequest], + Awaitable[~.MutateAssetGroupSignalsResponse]]: + 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 "mutate_asset_group_signals" not in self._stubs: + self._stubs["mutate_asset_group_signals"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetGroupSignalService/MutateAssetGroupSignals", + request_serializer=asset_group_signal_service.MutateAssetGroupSignalsRequest.serialize, + response_deserializer=asset_group_signal_service.MutateAssetGroupSignalsResponse.deserialize, + ) + ) + return self._stubs["mutate_asset_group_signals"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_asset_group_signals: self._wrap_method( + self.mutate_asset_group_signals, + 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" + + +__all__ = ("AssetGroupSignalServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_service/__init__.py b/google/ads/googleads/v24/services/services/asset_service/__init__.py new file mode 100644 index 000000000..782226438 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AssetServiceClient +from .async_client import AssetServiceAsyncClient + +__all__ = ( + "AssetServiceClient", + "AssetServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/asset_service/async_client.py b/google/ads/googleads/v24/services/services/asset_service/async_client.py new file mode 100644 index 000000000..1c40dcde3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_service/async_client.py @@ -0,0 +1,421 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import asset_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AssetServiceTransport, DEFAULT_CLIENT_INFO +from .client import AssetServiceClient + +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 AssetServiceAsyncClient: + """Service to manage assets. Asset types can be created with + AssetService are YoutubeVideoAsset, MediaBundleAsset and + ImageAsset. TextAsset should be created with Ad inline. + """ + + _client: AssetServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AssetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AssetServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = AssetServiceClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = AssetServiceClient._DEFAULT_UNIVERSE + + asset_path = staticmethod(AssetServiceClient.asset_path) + parse_asset_path = staticmethod(AssetServiceClient.parse_asset_path) + conversion_action_path = staticmethod( + AssetServiceClient.conversion_action_path + ) + parse_conversion_action_path = staticmethod( + AssetServiceClient.parse_conversion_action_path + ) + common_billing_account_path = staticmethod( + AssetServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AssetServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(AssetServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + AssetServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AssetServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AssetServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod(AssetServiceClient.common_project_path) + parse_common_project_path = staticmethod( + AssetServiceClient.parse_common_project_path + ) + common_location_path = staticmethod(AssetServiceClient.common_location_path) + parse_common_location_path = staticmethod( + AssetServiceClient.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: + AssetServiceAsyncClient: The constructed client. + """ + return AssetServiceClient.from_service_account_info.__func__(AssetServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AssetServiceAsyncClient: The constructed client. + """ + return AssetServiceClient.from_service_account_file.__func__(AssetServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AssetServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AssetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AssetServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, AssetServiceTransport, Callable[..., AssetServiceTransport] + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset 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,AssetServiceTransport,Callable[..., AssetServiceTransport]]]): + 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 AssetServiceTransport 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 = AssetServiceClient( + 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.ads.googleads.v24.services.AssetServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetService", + "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.ads.googleads.v24.services.AssetService", + "credentialsType": None, + } + ), + ) + + async def mutate_assets( + self, + request: Optional[ + Union[asset_service.MutateAssetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[asset_service.AssetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_service.MutateAssetsResponse: + r"""Creates assets. Operation statuses are returned. + + List of thrown errors: `AssetError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CollectionSizeError <>`__ `CurrencyCodeError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MediaUploadError <>`__ `MutateError <>`__ + `NotAllowlistedError <>`__ `NotEmptyError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ `YoutubeVideoRegistrationError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAssetsRequest, dict]]): + The request object. Request message for + [AssetService.MutateAssets][google.ads.googleads.v24.services.AssetService.MutateAssets] + customer_id (:class:`str`): + Required. The ID of the customer + whose assets are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AssetOperation]`): + Required. The list of operations to + perform on individual assets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAssetsResponse: + Response message for an asset mutate. + """ + # 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 = [customer_id, operations] + 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, asset_service.MutateAssetsRequest): + request = asset_service.MutateAssetsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AssetServiceAsyncClient": + 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__ = ("AssetServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/asset_service/client.py b/google/ads/googleads/v24/services/services/asset_service/client.py new file mode 100644 index 000000000..4fcf4f3aa --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_service/client.py @@ -0,0 +1,904 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import asset_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AssetServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import AssetServiceGrpcTransport +from .transports.grpc_asyncio import AssetServiceGrpcAsyncIOTransport + + +class AssetServiceClientMeta(type): + """Metaclass for the AssetService 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[AssetServiceTransport]] + _transport_registry["grpc"] = AssetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = AssetServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AssetServiceTransport]: + """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 AssetServiceClient(metaclass=AssetServiceClientMeta): + """Service to manage assets. Asset types can be created with + AssetService are YoutubeVideoAsset, MediaBundleAsset and + ImageAsset. TextAsset should be created with Ad inline. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AssetServiceClient: 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: + AssetServiceClient: 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) -> AssetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def asset_path( + customer_id: str, + asset_id: str, + ) -> str: + """Returns a fully-qualified asset string.""" + return "customers/{customer_id}/assets/{asset_id}".format( + customer_id=customer_id, + asset_id=asset_id, + ) + + @staticmethod + def parse_asset_path(path: str) -> Dict[str, str]: + """Parses a asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assets/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_action_path( + customer_id: str, + conversion_action_id: str, + ) -> str: + """Returns a fully-qualified conversion_action string.""" + return "customers/{customer_id}/conversionActions/{conversion_action_id}".format( + customer_id=customer_id, + conversion_action_id=conversion_action_id, + ) + + @staticmethod + def parse_conversion_action_path(path: str) -> Dict[str, str]: + """Parses a conversion_action path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionActions/(?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 = AssetServiceClient._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 = AssetServiceClient._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 + ): + """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 = AssetServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AssetServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = AssetServiceClient._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 = AssetServiceClient._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): + """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, AssetServiceTransport, Callable[..., AssetServiceTransport] + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset 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,AssetServiceTransport,Callable[..., AssetServiceTransport]]]): + 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 AssetServiceTransport 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, + ) = AssetServiceClient._read_environment_variables() + self._client_cert_source = AssetServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = AssetServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AssetServiceTransport) + if transport_provided: + # transport is a AssetServiceTransport 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(AssetServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AssetServiceClient._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[AssetServiceTransport], + Callable[..., AssetServiceTransport], + ] = ( + AssetServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., AssetServiceTransport], 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.ads.googleads.v24.services.AssetServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetService", + "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.ads.googleads.v24.services.AssetService", + "credentialsType": None, + } + ), + ) + + def mutate_assets( + self, + request: Optional[ + Union[asset_service.MutateAssetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[asset_service.AssetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_service.MutateAssetsResponse: + r"""Creates assets. Operation statuses are returned. + + List of thrown errors: `AssetError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CollectionSizeError <>`__ `CurrencyCodeError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MediaUploadError <>`__ `MutateError <>`__ + `NotAllowlistedError <>`__ `NotEmptyError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ `YoutubeVideoRegistrationError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAssetsRequest, dict]): + The request object. Request message for + [AssetService.MutateAssets][google.ads.googleads.v24.services.AssetService.MutateAssets] + customer_id (str): + Required. The ID of the customer + whose assets are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AssetOperation]): + Required. The list of operations to + perform on individual assets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAssetsResponse: + Response message for an asset mutate. + """ + # 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 = [customer_id, operations] + 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, asset_service.MutateAssetsRequest): + request = asset_service.MutateAssetsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.mutate_assets] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AssetServiceClient": + 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() + + +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__ = ("AssetServiceClient",) diff --git a/google/ads/googleads/v24/services/services/asset_service/transports/README.rst b/google/ads/googleads/v24/services/services/asset_service/transports/README.rst new file mode 100644 index 000000000..f0467812e --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AssetServiceTransport` is the ABC for all transports. +- public child `AssetServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AssetServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAssetServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AssetServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/asset_service/transports/__init__.py b/google/ads/googleads/v24/services/services/asset_service/transports/__init__.py new file mode 100644 index 000000000..0e0866bca --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AssetServiceTransport +from .grpc import AssetServiceGrpcTransport +from .grpc_asyncio import AssetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetServiceTransport]] +_transport_registry["grpc"] = AssetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AssetServiceGrpcAsyncIOTransport + +__all__ = ( + "AssetServiceTransport", + "AssetServiceGrpcTransport", + "AssetServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/asset_service/transports/base.py b/google/ads/googleads/v24/services/services/asset_service/transports/base.py new file mode 100644 index 000000000..32bae85f7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import asset_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 AssetServiceTransport(abc.ABC): + """Abstract transport class for AssetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_assets: gapic_v1.method.wrap_method( + self.mutate_assets, + 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 mutate_assets( + self, + ) -> Callable[ + [asset_service.MutateAssetsRequest], + Union[ + asset_service.MutateAssetsResponse, + Awaitable[asset_service.MutateAssetsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AssetServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_service/transports/grpc.py b/google/ads/googleads/v24/services/services/asset_service/transports/grpc.py new file mode 100644 index 000000000..4818c1bf4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_service/transports/grpc.py @@ -0,0 +1,395 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import asset_service +from .base import AssetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AssetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetServiceGrpcTransport(AssetServiceTransport): + """gRPC backend transport for AssetService. + + Service to manage assets. Asset types can be created with + AssetService are YoutubeVideoAsset, MediaBundleAsset and + ImageAsset. TextAsset should be created with Ad inline. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_assets( + self, + ) -> Callable[ + [asset_service.MutateAssetsRequest], asset_service.MutateAssetsResponse + ]: + r"""Return a callable for the mutate assets method over gRPC. + + Creates assets. Operation statuses are returned. + + List of thrown errors: `AssetError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CollectionSizeError <>`__ `CurrencyCodeError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MediaUploadError <>`__ `MutateError <>`__ + `NotAllowlistedError <>`__ `NotEmptyError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ `YoutubeVideoRegistrationError <>`__ + + Returns: + Callable[[~.MutateAssetsRequest], + ~.MutateAssetsResponse]: + 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 "mutate_assets" not in self._stubs: + self._stubs["mutate_assets"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetService/MutateAssets", + request_serializer=asset_service.MutateAssetsRequest.serialize, + response_deserializer=asset_service.MutateAssetsResponse.deserialize, + ) + return self._stubs["mutate_assets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AssetServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/asset_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..8f1181c92 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_service/transports/grpc_asyncio.py @@ -0,0 +1,417 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import asset_service +from .base import AssetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AssetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetServiceGrpcAsyncIOTransport(AssetServiceTransport): + """gRPC AsyncIO backend transport for AssetService. + + Service to manage assets. Asset types can be created with + AssetService are YoutubeVideoAsset, MediaBundleAsset and + ImageAsset. TextAsset should be created with Ad inline. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_assets( + self, + ) -> Callable[ + [asset_service.MutateAssetsRequest], + Awaitable[asset_service.MutateAssetsResponse], + ]: + r"""Return a callable for the mutate assets method over gRPC. + + Creates assets. Operation statuses are returned. + + List of thrown errors: `AssetError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CollectionSizeError <>`__ `CurrencyCodeError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DistinctError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MediaUploadError <>`__ `MutateError <>`__ + `NotAllowlistedError <>`__ `NotEmptyError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ `YoutubeVideoRegistrationError <>`__ + + Returns: + Callable[[~.MutateAssetsRequest], + Awaitable[~.MutateAssetsResponse]]: + 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 "mutate_assets" not in self._stubs: + self._stubs["mutate_assets"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetService/MutateAssets", + request_serializer=asset_service.MutateAssetsRequest.serialize, + response_deserializer=asset_service.MutateAssetsResponse.deserialize, + ) + return self._stubs["mutate_assets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_assets: self._wrap_method( + self.mutate_assets, + 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" + + +__all__ = ("AssetServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_set_asset_service/__init__.py b/google/ads/googleads/v24/services/services/asset_set_asset_service/__init__.py new file mode 100644 index 000000000..dc73f4dcc --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_asset_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AssetSetAssetServiceClient +from .async_client import AssetSetAssetServiceAsyncClient + +__all__ = ( + "AssetSetAssetServiceClient", + "AssetSetAssetServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/asset_set_asset_service/async_client.py b/google/ads/googleads/v24/services/services/asset_set_asset_service/async_client.py new file mode 100644 index 000000000..d1e491dc7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_asset_service/async_client.py @@ -0,0 +1,427 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import asset_set_asset_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AssetSetAssetServiceTransport, DEFAULT_CLIENT_INFO +from .client import AssetSetAssetServiceClient + +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 AssetSetAssetServiceAsyncClient: + """Service to manage asset set asset.""" + + _client: AssetSetAssetServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AssetSetAssetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AssetSetAssetServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AssetSetAssetServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AssetSetAssetServiceClient._DEFAULT_UNIVERSE + + asset_path = staticmethod(AssetSetAssetServiceClient.asset_path) + parse_asset_path = staticmethod(AssetSetAssetServiceClient.parse_asset_path) + asset_set_path = staticmethod(AssetSetAssetServiceClient.asset_set_path) + parse_asset_set_path = staticmethod( + AssetSetAssetServiceClient.parse_asset_set_path + ) + asset_set_asset_path = staticmethod( + AssetSetAssetServiceClient.asset_set_asset_path + ) + parse_asset_set_asset_path = staticmethod( + AssetSetAssetServiceClient.parse_asset_set_asset_path + ) + common_billing_account_path = staticmethod( + AssetSetAssetServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AssetSetAssetServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AssetSetAssetServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AssetSetAssetServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AssetSetAssetServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AssetSetAssetServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AssetSetAssetServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AssetSetAssetServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AssetSetAssetServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AssetSetAssetServiceClient.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: + AssetSetAssetServiceAsyncClient: The constructed client. + """ + return AssetSetAssetServiceClient.from_service_account_info.__func__(AssetSetAssetServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AssetSetAssetServiceAsyncClient: The constructed client. + """ + return AssetSetAssetServiceClient.from_service_account_file.__func__(AssetSetAssetServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AssetSetAssetServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AssetSetAssetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetSetAssetServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AssetSetAssetServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AssetSetAssetServiceTransport, + Callable[..., AssetSetAssetServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset set asset 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,AssetSetAssetServiceTransport,Callable[..., AssetSetAssetServiceTransport]]]): + 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 AssetSetAssetServiceTransport 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 = AssetSetAssetServiceClient( + 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.ads.googleads.v24.services.AssetSetAssetServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetSetAssetService", + "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.ads.googleads.v24.services.AssetSetAssetService", + "credentialsType": None, + } + ), + ) + + async def mutate_asset_set_assets( + self, + request: Optional[ + Union[asset_set_asset_service.MutateAssetSetAssetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[asset_set_asset_service.AssetSetAssetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_set_asset_service.MutateAssetSetAssetsResponse: + r"""Creates, updates or removes asset set assets. + Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAssetSetAssetsRequest, dict]]): + The request object. Request message for + [AssetSetAssetService.MutateAssetSetAssets][google.ads.googleads.v24.services.AssetSetAssetService.MutateAssetSetAssets]. + customer_id (:class:`str`): + Required. The ID of the customer + whose asset set assets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AssetSetAssetOperation]`): + Required. The list of operations to + perform on individual asset set assets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAssetSetAssetsResponse: + Response message for an asset set + asset mutate. + + """ + # 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 = [customer_id, operations] + 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, asset_set_asset_service.MutateAssetSetAssetsRequest + ): + request = asset_set_asset_service.MutateAssetSetAssetsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_asset_set_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AssetSetAssetServiceAsyncClient": + 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__ = ("AssetSetAssetServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/asset_set_asset_service/client.py b/google/ads/googleads/v24/services/services/asset_set_asset_service/client.py new file mode 100644 index 000000000..4344ec727 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_asset_service/client.py @@ -0,0 +1,936 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import asset_set_asset_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AssetSetAssetServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import AssetSetAssetServiceGrpcTransport +from .transports.grpc_asyncio import AssetSetAssetServiceGrpcAsyncIOTransport + + +class AssetSetAssetServiceClientMeta(type): + """Metaclass for the AssetSetAssetService 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[AssetSetAssetServiceTransport]] + _transport_registry["grpc"] = AssetSetAssetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AssetSetAssetServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AssetSetAssetServiceTransport]: + """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 AssetSetAssetServiceClient(metaclass=AssetSetAssetServiceClientMeta): + """Service to manage asset set asset.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AssetSetAssetServiceClient: 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: + AssetSetAssetServiceClient: 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) -> AssetSetAssetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetSetAssetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def asset_path( + customer_id: str, + asset_id: str, + ) -> str: + """Returns a fully-qualified asset string.""" + return "customers/{customer_id}/assets/{asset_id}".format( + customer_id=customer_id, + asset_id=asset_id, + ) + + @staticmethod + def parse_asset_path(path: str) -> Dict[str, str]: + """Parses a asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assets/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_set_path( + customer_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified asset_set string.""" + return "customers/{customer_id}/assetSets/{asset_set_id}".format( + customer_id=customer_id, + asset_set_id=asset_set_id, + ) + + @staticmethod + def parse_asset_set_path(path: str) -> Dict[str, str]: + """Parses a asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetSets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_set_asset_path( + customer_id: str, + asset_set_id: str, + asset_id: str, + ) -> str: + """Returns a fully-qualified asset_set_asset string.""" + return "customers/{customer_id}/assetSetAssets/{asset_set_id}~{asset_id}".format( + customer_id=customer_id, + asset_set_id=asset_set_id, + asset_id=asset_id, + ) + + @staticmethod + def parse_asset_set_asset_path(path: str) -> Dict[str, str]: + """Parses a asset_set_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetSetAssets/(?P.+?)~(?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 = ( + AssetSetAssetServiceClient._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 = ( + AssetSetAssetServiceClient._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 + ): + """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 = AssetSetAssetServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AssetSetAssetServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AssetSetAssetServiceClient._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 = AssetSetAssetServiceClient._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): + """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, + AssetSetAssetServiceTransport, + Callable[..., AssetSetAssetServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset set asset 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,AssetSetAssetServiceTransport,Callable[..., AssetSetAssetServiceTransport]]]): + 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 AssetSetAssetServiceTransport 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, + ) = AssetSetAssetServiceClient._read_environment_variables() + self._client_cert_source = ( + AssetSetAssetServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = AssetSetAssetServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AssetSetAssetServiceTransport + ) + if transport_provided: + # transport is a AssetSetAssetServiceTransport 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(AssetSetAssetServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AssetSetAssetServiceClient._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[AssetSetAssetServiceTransport], + Callable[..., AssetSetAssetServiceTransport], + ] = ( + AssetSetAssetServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AssetSetAssetServiceTransport], 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.ads.googleads.v24.services.AssetSetAssetServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetSetAssetService", + "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.ads.googleads.v24.services.AssetSetAssetService", + "credentialsType": None, + } + ), + ) + + def mutate_asset_set_assets( + self, + request: Optional[ + Union[asset_set_asset_service.MutateAssetSetAssetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[asset_set_asset_service.AssetSetAssetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_set_asset_service.MutateAssetSetAssetsResponse: + r"""Creates, updates or removes asset set assets. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAssetSetAssetsRequest, dict]): + The request object. Request message for + [AssetSetAssetService.MutateAssetSetAssets][google.ads.googleads.v24.services.AssetSetAssetService.MutateAssetSetAssets]. + customer_id (str): + Required. The ID of the customer + whose asset set assets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AssetSetAssetOperation]): + Required. The list of operations to + perform on individual asset set assets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAssetSetAssetsResponse: + Response message for an asset set + asset mutate. + + """ + # 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 = [customer_id, operations] + 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, asset_set_asset_service.MutateAssetSetAssetsRequest + ): + request = asset_set_asset_service.MutateAssetSetAssetsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_asset_set_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AssetSetAssetServiceClient": + 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() + + +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__ = ("AssetSetAssetServiceClient",) diff --git a/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/README.rst b/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/README.rst new file mode 100644 index 000000000..9b38ba131 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AssetSetAssetServiceTransport` is the ABC for all transports. +- public child `AssetSetAssetServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AssetSetAssetServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAssetSetAssetServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AssetSetAssetServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/__init__.py b/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/__init__.py new file mode 100644 index 000000000..fb115d95a --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AssetSetAssetServiceTransport +from .grpc import AssetSetAssetServiceGrpcTransport +from .grpc_asyncio import AssetSetAssetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetSetAssetServiceTransport]] +_transport_registry["grpc"] = AssetSetAssetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AssetSetAssetServiceGrpcAsyncIOTransport + +__all__ = ( + "AssetSetAssetServiceTransport", + "AssetSetAssetServiceGrpcTransport", + "AssetSetAssetServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/base.py b/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/base.py new file mode 100644 index 000000000..93c8ca2f3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import asset_set_asset_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 AssetSetAssetServiceTransport(abc.ABC): + """Abstract transport class for AssetSetAssetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_asset_set_assets: gapic_v1.method.wrap_method( + self.mutate_asset_set_assets, + 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 mutate_asset_set_assets( + self, + ) -> Callable[ + [asset_set_asset_service.MutateAssetSetAssetsRequest], + Union[ + asset_set_asset_service.MutateAssetSetAssetsResponse, + Awaitable[asset_set_asset_service.MutateAssetSetAssetsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AssetSetAssetServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/grpc.py b/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/grpc.py new file mode 100644 index 000000000..c179deb07 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/grpc.py @@ -0,0 +1,384 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import asset_set_asset_service +from .base import AssetSetAssetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AssetSetAssetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetSetAssetService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetSetAssetServiceGrpcTransport(AssetSetAssetServiceTransport): + """gRPC backend transport for AssetSetAssetService. + + Service to manage asset set asset. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_asset_set_assets( + self, + ) -> Callable[ + [asset_set_asset_service.MutateAssetSetAssetsRequest], + asset_set_asset_service.MutateAssetSetAssetsResponse, + ]: + r"""Return a callable for the mutate asset set assets method over gRPC. + + Creates, updates or removes asset set assets. + Operation statuses are returned. + + Returns: + Callable[[~.MutateAssetSetAssetsRequest], + ~.MutateAssetSetAssetsResponse]: + 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 "mutate_asset_set_assets" not in self._stubs: + self._stubs["mutate_asset_set_assets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetSetAssetService/MutateAssetSetAssets", + request_serializer=asset_set_asset_service.MutateAssetSetAssetsRequest.serialize, + response_deserializer=asset_set_asset_service.MutateAssetSetAssetsResponse.deserialize, + ) + ) + return self._stubs["mutate_asset_set_assets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AssetSetAssetServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..af9b643cb --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_asset_service/transports/grpc_asyncio.py @@ -0,0 +1,405 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import asset_set_asset_service +from .base import AssetSetAssetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AssetSetAssetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetSetAssetService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetSetAssetServiceGrpcAsyncIOTransport(AssetSetAssetServiceTransport): + """gRPC AsyncIO backend transport for AssetSetAssetService. + + Service to manage asset set asset. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_asset_set_assets( + self, + ) -> Callable[ + [asset_set_asset_service.MutateAssetSetAssetsRequest], + Awaitable[asset_set_asset_service.MutateAssetSetAssetsResponse], + ]: + r"""Return a callable for the mutate asset set assets method over gRPC. + + Creates, updates or removes asset set assets. + Operation statuses are returned. + + Returns: + Callable[[~.MutateAssetSetAssetsRequest], + Awaitable[~.MutateAssetSetAssetsResponse]]: + 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 "mutate_asset_set_assets" not in self._stubs: + self._stubs["mutate_asset_set_assets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetSetAssetService/MutateAssetSetAssets", + request_serializer=asset_set_asset_service.MutateAssetSetAssetsRequest.serialize, + response_deserializer=asset_set_asset_service.MutateAssetSetAssetsResponse.deserialize, + ) + ) + return self._stubs["mutate_asset_set_assets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_asset_set_assets: self._wrap_method( + self.mutate_asset_set_assets, + 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" + + +__all__ = ("AssetSetAssetServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_set_service/__init__.py b/google/ads/googleads/v24/services/services/asset_set_service/__init__.py new file mode 100644 index 000000000..1d62e87bd --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AssetSetServiceClient +from .async_client import AssetSetServiceAsyncClient + +__all__ = ( + "AssetSetServiceClient", + "AssetSetServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/asset_set_service/async_client.py b/google/ads/googleads/v24/services/services/asset_set_service/async_client.py new file mode 100644 index 000000000..af324c23f --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_service/async_client.py @@ -0,0 +1,412 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import asset_set_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AssetSetServiceTransport, DEFAULT_CLIENT_INFO +from .client import AssetSetServiceClient + +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 AssetSetServiceAsyncClient: + """Service to manage asset set""" + + _client: AssetSetServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AssetSetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AssetSetServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AssetSetServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AssetSetServiceClient._DEFAULT_UNIVERSE + + asset_set_path = staticmethod(AssetSetServiceClient.asset_set_path) + parse_asset_set_path = staticmethod( + AssetSetServiceClient.parse_asset_set_path + ) + common_billing_account_path = staticmethod( + AssetSetServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AssetSetServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(AssetSetServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + AssetSetServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AssetSetServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AssetSetServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AssetSetServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AssetSetServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AssetSetServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AssetSetServiceClient.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: + AssetSetServiceAsyncClient: The constructed client. + """ + return AssetSetServiceClient.from_service_account_info.__func__(AssetSetServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AssetSetServiceAsyncClient: The constructed client. + """ + return AssetSetServiceClient.from_service_account_file.__func__(AssetSetServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AssetSetServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AssetSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetSetServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AssetSetServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AssetSetServiceTransport, + Callable[..., AssetSetServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset set 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,AssetSetServiceTransport,Callable[..., AssetSetServiceTransport]]]): + 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 AssetSetServiceTransport 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 = AssetSetServiceClient( + 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.ads.googleads.v24.services.AssetSetServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetSetService", + "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.ads.googleads.v24.services.AssetSetService", + "credentialsType": None, + } + ), + ) + + async def mutate_asset_sets( + self, + request: Optional[ + Union[asset_set_service.MutateAssetSetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[asset_set_service.AssetSetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_set_service.MutateAssetSetsResponse: + r"""Creates, updates or removes asset sets. Operation + statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAssetSetsRequest, dict]]): + The request object. Request message for + [AssetSetService.MutateAssetSets][google.ads.googleads.v24.services.AssetSetService.MutateAssetSets]. + customer_id (:class:`str`): + Required. The ID of the customer + whose asset sets are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AssetSetOperation]`): + Required. The list of operations to + perform on individual asset sets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAssetSetsResponse: + Response message for an asset set + mutate. + + """ + # 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 = [customer_id, operations] + 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, asset_set_service.MutateAssetSetsRequest): + request = asset_set_service.MutateAssetSetsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_asset_sets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AssetSetServiceAsyncClient": + 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__ = ("AssetSetServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/asset_set_service/client.py b/google/ads/googleads/v24/services/services/asset_set_service/client.py new file mode 100644 index 000000000..0525be06e --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_service/client.py @@ -0,0 +1,880 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import asset_set_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AssetSetServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import AssetSetServiceGrpcTransport +from .transports.grpc_asyncio import AssetSetServiceGrpcAsyncIOTransport + + +class AssetSetServiceClientMeta(type): + """Metaclass for the AssetSetService 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[AssetSetServiceTransport]] + _transport_registry["grpc"] = AssetSetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = AssetSetServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AssetSetServiceTransport]: + """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 AssetSetServiceClient(metaclass=AssetSetServiceClientMeta): + """Service to manage asset set""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AssetSetServiceClient: 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: + AssetSetServiceClient: 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) -> AssetSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssetSetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def asset_set_path( + customer_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified asset_set string.""" + return "customers/{customer_id}/assetSets/{asset_set_id}".format( + customer_id=customer_id, + asset_set_id=asset_set_id, + ) + + @staticmethod + def parse_asset_set_path(path: str) -> Dict[str, str]: + """Parses a asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetSets/(?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 = AssetSetServiceClient._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 = AssetSetServiceClient._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 + ): + """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 = AssetSetServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AssetSetServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AssetSetServiceClient._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 = AssetSetServiceClient._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): + """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, + AssetSetServiceTransport, + Callable[..., AssetSetServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the asset set 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,AssetSetServiceTransport,Callable[..., AssetSetServiceTransport]]]): + 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 AssetSetServiceTransport 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, + ) = AssetSetServiceClient._read_environment_variables() + self._client_cert_source = ( + AssetSetServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = AssetSetServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AssetSetServiceTransport) + if transport_provided: + # transport is a AssetSetServiceTransport 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(AssetSetServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AssetSetServiceClient._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[AssetSetServiceTransport], + Callable[..., AssetSetServiceTransport], + ] = ( + AssetSetServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., AssetSetServiceTransport], 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.ads.googleads.v24.services.AssetSetServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AssetSetService", + "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.ads.googleads.v24.services.AssetSetService", + "credentialsType": None, + } + ), + ) + + def mutate_asset_sets( + self, + request: Optional[ + Union[asset_set_service.MutateAssetSetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[asset_set_service.AssetSetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> asset_set_service.MutateAssetSetsResponse: + r"""Creates, updates or removes asset sets. Operation + statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAssetSetsRequest, dict]): + The request object. Request message for + [AssetSetService.MutateAssetSets][google.ads.googleads.v24.services.AssetSetService.MutateAssetSets]. + customer_id (str): + Required. The ID of the customer + whose asset sets are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AssetSetOperation]): + Required. The list of operations to + perform on individual asset sets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAssetSetsResponse: + Response message for an asset set + mutate. + + """ + # 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 = [customer_id, operations] + 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, asset_set_service.MutateAssetSetsRequest): + request = asset_set_service.MutateAssetSetsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_asset_sets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AssetSetServiceClient": + 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() + + +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__ = ("AssetSetServiceClient",) diff --git a/google/ads/googleads/v24/services/services/asset_set_service/transports/README.rst b/google/ads/googleads/v24/services/services/asset_set_service/transports/README.rst new file mode 100644 index 000000000..161d26427 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AssetSetServiceTransport` is the ABC for all transports. +- public child `AssetSetServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AssetSetServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAssetSetServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AssetSetServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/asset_set_service/transports/__init__.py b/google/ads/googleads/v24/services/services/asset_set_service/transports/__init__.py new file mode 100644 index 000000000..b5b69c7e1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AssetSetServiceTransport +from .grpc import AssetSetServiceGrpcTransport +from .grpc_asyncio import AssetSetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetSetServiceTransport]] +_transport_registry["grpc"] = AssetSetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AssetSetServiceGrpcAsyncIOTransport + +__all__ = ( + "AssetSetServiceTransport", + "AssetSetServiceGrpcTransport", + "AssetSetServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/asset_set_service/transports/base.py b/google/ads/googleads/v24/services/services/asset_set_service/transports/base.py new file mode 100644 index 000000000..d5ec6aca3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import asset_set_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 AssetSetServiceTransport(abc.ABC): + """Abstract transport class for AssetSetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_asset_sets: gapic_v1.method.wrap_method( + self.mutate_asset_sets, + 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 mutate_asset_sets( + self, + ) -> Callable[ + [asset_set_service.MutateAssetSetsRequest], + Union[ + asset_set_service.MutateAssetSetsResponse, + Awaitable[asset_set_service.MutateAssetSetsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AssetSetServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_set_service/transports/grpc.py b/google/ads/googleads/v24/services/services/asset_set_service/transports/grpc.py new file mode 100644 index 000000000..3e23459f2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_service/transports/grpc.py @@ -0,0 +1,382 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import asset_set_service +from .base import AssetSetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AssetSetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetSetService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetSetServiceGrpcTransport(AssetSetServiceTransport): + """gRPC backend transport for AssetSetService. + + Service to manage asset set + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_asset_sets( + self, + ) -> Callable[ + [asset_set_service.MutateAssetSetsRequest], + asset_set_service.MutateAssetSetsResponse, + ]: + r"""Return a callable for the mutate asset sets method over gRPC. + + Creates, updates or removes asset sets. Operation + statuses are returned. + + Returns: + Callable[[~.MutateAssetSetsRequest], + ~.MutateAssetSetsResponse]: + 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 "mutate_asset_sets" not in self._stubs: + self._stubs["mutate_asset_sets"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetSetService/MutateAssetSets", + request_serializer=asset_set_service.MutateAssetSetsRequest.serialize, + response_deserializer=asset_set_service.MutateAssetSetsResponse.deserialize, + ) + return self._stubs["mutate_asset_sets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AssetSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/asset_set_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/asset_set_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..c483e87b5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/asset_set_service/transports/grpc_asyncio.py @@ -0,0 +1,403 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import asset_set_service +from .base import AssetSetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AssetSetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AssetSetService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AssetSetServiceGrpcAsyncIOTransport(AssetSetServiceTransport): + """gRPC AsyncIO backend transport for AssetSetService. + + Service to manage asset set + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_asset_sets( + self, + ) -> Callable[ + [asset_set_service.MutateAssetSetsRequest], + Awaitable[asset_set_service.MutateAssetSetsResponse], + ]: + r"""Return a callable for the mutate asset sets method over gRPC. + + Creates, updates or removes asset sets. Operation + statuses are returned. + + Returns: + Callable[[~.MutateAssetSetsRequest], + Awaitable[~.MutateAssetSetsResponse]]: + 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 "mutate_asset_sets" not in self._stubs: + self._stubs["mutate_asset_sets"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AssetSetService/MutateAssetSets", + request_serializer=asset_set_service.MutateAssetSetsRequest.serialize, + response_deserializer=asset_set_service.MutateAssetSetsResponse.deserialize, + ) + return self._stubs["mutate_asset_sets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_asset_sets: self._wrap_method( + self.mutate_asset_sets, + 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" + + +__all__ = ("AssetSetServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/audience_insights_service/__init__.py b/google/ads/googleads/v24/services/services/audience_insights_service/__init__.py new file mode 100644 index 000000000..a67ad6435 --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_insights_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AudienceInsightsServiceClient +from .async_client import AudienceInsightsServiceAsyncClient + +__all__ = ( + "AudienceInsightsServiceClient", + "AudienceInsightsServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/audience_insights_service/async_client.py b/google/ads/googleads/v24/services/services/audience_insights_service/async_client.py new file mode 100644 index 000000000..ed38f96dd --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_insights_service/async_client.py @@ -0,0 +1,1247 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.common.types import audience_insights_attribute +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.enums.types import audience_insights_dimension +from google.ads.googleads.v24.services.types import audience_insights_service +from .transports.base import ( + AudienceInsightsServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import AudienceInsightsServiceClient + +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 AudienceInsightsServiceAsyncClient: + """Audience Insights Service helps users find information about + groups of people and how they can be reached with Google Ads. + Accessible to allowlisted customers only. + """ + + _client: AudienceInsightsServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AudienceInsightsServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AudienceInsightsServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AudienceInsightsServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AudienceInsightsServiceClient._DEFAULT_UNIVERSE + + common_billing_account_path = staticmethod( + AudienceInsightsServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AudienceInsightsServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AudienceInsightsServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AudienceInsightsServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AudienceInsightsServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AudienceInsightsServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AudienceInsightsServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AudienceInsightsServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AudienceInsightsServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AudienceInsightsServiceClient.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: + AudienceInsightsServiceAsyncClient: The constructed client. + """ + return AudienceInsightsServiceClient.from_service_account_info.__func__(AudienceInsightsServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AudienceInsightsServiceAsyncClient: The constructed client. + """ + return AudienceInsightsServiceClient.from_service_account_file.__func__(AudienceInsightsServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AudienceInsightsServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AudienceInsightsServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AudienceInsightsServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AudienceInsightsServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AudienceInsightsServiceTransport, + Callable[..., AudienceInsightsServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the audience insights 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,AudienceInsightsServiceTransport,Callable[..., AudienceInsightsServiceTransport]]]): + 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 AudienceInsightsServiceTransport 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 = AudienceInsightsServiceClient( + 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.ads.googleads.v24.services.AudienceInsightsServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AudienceInsightsService", + "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.ads.googleads.v24.services.AudienceInsightsService", + "credentialsType": None, + } + ), + ) + + async def generate_insights_finder_report( + self, + request: Optional[ + Union[ + audience_insights_service.GenerateInsightsFinderReportRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + baseline_audience: Optional[ + audience_insights_service.InsightsAudience + ] = None, + specific_audience: Optional[ + audience_insights_service.InsightsAudience + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_insights_service.GenerateInsightsFinderReportResponse: + r"""Creates a saved report that can be viewed in the Insights Finder + tool. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateInsightsFinderReportRequest, dict]]): + The request object. Request message for + [AudienceInsightsService.GenerateInsightsFinderReport][google.ads.googleads.v24.services.AudienceInsightsService.GenerateInsightsFinderReport]. + customer_id (:class:`str`): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + baseline_audience (:class:`google.ads.googleads.v24.services.types.InsightsAudience`): + Required. A baseline audience for + this report, typically all people in a + region. + + This corresponds to the ``baseline_audience`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + specific_audience (:class:`google.ads.googleads.v24.services.types.InsightsAudience`): + Required. The specific audience of + interest for this report. The insights + in the report will be based on + attributes more prevalent in this + audience than in the report's baseline + audience. + + This corresponds to the ``specific_audience`` 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.ads.googleads.v24.services.types.GenerateInsightsFinderReportResponse: + The response message for + [AudienceInsightsService.GenerateInsightsFinderReport][google.ads.googleads.v24.services.AudienceInsightsService.GenerateInsightsFinderReport], + containing the shareable URL for the report. + + """ + # 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 = [customer_id, baseline_audience, specific_audience] + 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, + audience_insights_service.GenerateInsightsFinderReportRequest, + ): + request = ( + audience_insights_service.GenerateInsightsFinderReportRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if baseline_audience is not None: + request.baseline_audience = baseline_audience + if specific_audience is not None: + request.specific_audience = specific_audience + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_insights_finder_report + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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_audience_insights_attributes( + self, + request: Optional[ + Union[ + audience_insights_service.ListAudienceInsightsAttributesRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + dimensions: Optional[ + MutableSequence[ + audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension + ] + ] = None, + query_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]]] = (), + ) -> audience_insights_service.ListAudienceInsightsAttributesResponse: + r"""Searches for audience attributes that can be used to generate + insights. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListAudienceInsightsAttributesRequest, dict]]): + The request object. Request message for + [AudienceInsightsService.ListAudienceInsightsAttributes][google.ads.googleads.v24.services.AudienceInsightsService.ListAudienceInsightsAttributes]. + customer_id (:class:`str`): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + dimensions (:class:`MutableSequence[google.ads.googleads.v24.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension]`): + Required. The types of attributes to be returned. + Supported dimensions are CATEGORY, KNOWLEDGE_GRAPH, + DEVICE, GEO_TARGET_COUNTRY, SUB_COUNTRY_LOCATION, + YOUTUBE_LINEUP, AFFINITY_USER_INTEREST, + IN_MARKET_USER_INTEREST, LIFE_EVENT_USER_INTEREST, + PARENTAL_STATUS, INCOME_RANGE, AGE_RANGE, and GENDER. + + This corresponds to the ``dimensions`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + query_text (:class:`str`): + Required. A free text query. If the requested dimensions + include Attributes CATEGORY or KNOWLEDGE_GRAPH, then the + attributes returned for those dimensions will match or + be related to this string. For other dimensions, this + field is ignored and all available attributes are + returned. + + This corresponds to the ``query_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.ads.googleads.v24.services.types.ListAudienceInsightsAttributesResponse: + Response message for + [AudienceInsightsService.ListAudienceInsightsAttributes][google.ads.googleads.v24.services.AudienceInsightsService.ListAudienceInsightsAttributes]. + + """ + # 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 = [customer_id, dimensions, query_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, + audience_insights_service.ListAudienceInsightsAttributesRequest, + ): + request = ( + audience_insights_service.ListAudienceInsightsAttributesRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if query_text is not None: + request.query_text = query_text + if dimensions: + request.dimensions.extend(dimensions) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_audience_insights_attributes + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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_insights_eligible_dates( + self, + request: Optional[ + Union[ + audience_insights_service.ListInsightsEligibleDatesRequest, dict + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_insights_service.ListInsightsEligibleDatesResponse: + r"""Lists date ranges for which audience insights data can be + requested. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListInsightsEligibleDatesRequest, dict]]): + The request object. Request message for + [AudienceInsightsService.ListInsightsEligibleDates][google.ads.googleads.v24.services.AudienceInsightsService.ListInsightsEligibleDates]. + 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.googleads.v24.services.types.ListInsightsEligibleDatesResponse: + Response message for + [AudienceInsightsService.ListInsightsEligibleDates][google.ads.googleads.v24.services.AudienceInsightsService.ListInsightsEligibleDates]. + + """ + # 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, audience_insights_service.ListInsightsEligibleDatesRequest + ): + request = ( + audience_insights_service.ListInsightsEligibleDatesRequest( + request + ) + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_insights_eligible_dates + ] + + # 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 generate_audience_composition_insights( + self, + request: Optional[ + Union[ + audience_insights_service.GenerateAudienceCompositionInsightsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + audience: Optional[audience_insights_service.InsightsAudience] = None, + dimensions: Optional[ + MutableSequence[ + audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_insights_service.GenerateAudienceCompositionInsightsResponse: + r"""Returns a collection of attributes that are represented in an + audience of interest, with metrics that compare each attribute's + share of the audience with its share of a baseline audience. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateAudienceCompositionInsightsRequest, dict]]): + The request object. Request message for + [AudienceInsightsService.GenerateAudienceCompositionInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceCompositionInsights]. + customer_id (:class:`str`): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + audience (:class:`google.ads.googleads.v24.services.types.InsightsAudience`): + Required. The audience of interest + for which insights are being requested. + + This corresponds to the ``audience`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + dimensions (:class:`MutableSequence[google.ads.googleads.v24.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension]`): + Required. The audience dimensions for which composition + insights should be returned. Supported dimensions are + KNOWLEDGE_GRAPH, GEO_TARGET_COUNTRY, + SUB_COUNTRY_LOCATION, YOUTUBE_CHANNEL, YOUTUBE_LINEUP, + AFFINITY_USER_INTEREST, IN_MARKET_USER_INTEREST, + LIFE_EVENT_USER_INTEREST, PARENTAL_STATUS, INCOME_RANGE, + AGE_RANGE, and GENDER. + + This corresponds to the ``dimensions`` 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.ads.googleads.v24.services.types.GenerateAudienceCompositionInsightsResponse: + Response message for + [AudienceInsightsService.GenerateAudienceCompositionInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceCompositionInsights]. + + """ + # 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 = [customer_id, audience, dimensions] + 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, + audience_insights_service.GenerateAudienceCompositionInsightsRequest, + ): + request = audience_insights_service.GenerateAudienceCompositionInsightsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if audience is not None: + request.audience = audience + if dimensions: + request.dimensions.extend(dimensions) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_audience_composition_insights + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_audience_definition( + self, + request: Optional[ + Union[ + audience_insights_service.GenerateAudienceDefinitionRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + audience_description: Optional[ + audience_insights_service.InsightsAudienceDescription + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_insights_service.GenerateAudienceDefinitionResponse: + r"""Returns a collection of audience attributes using generative AI + based on the provided audience description. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateAudienceDefinitionRequest, dict]]): + The request object. Request message for + [AudienceInsightsService.GenerateAudienceDefinition][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceDefinition]. + customer_id (:class:`str`): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + audience_description (:class:`google.ads.googleads.v24.services.types.InsightsAudienceDescription`): + Required. Provide a text description of an audience to + get AI-generated structured suggestions. This can take + around 5 or more seconds to complete Supported marketing + objectives are: AWARENESS, CONSIDERATION and RESEARCH. + Supported dimensions are: AGE_RANGE, GENDER, + PARENTAL_STATUS, AFFINITY_USER_INTEREST, + IN_MARKET_USER_INTEREST, LIFE_EVENT_USER_INTEREST, + CATEGORY and KNOWLEDGE_GRAPH. + + This corresponds to the ``audience_description`` 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.ads.googleads.v24.services.types.GenerateAudienceDefinitionResponse: + Response message for + [AudienceInsightsService.GenerateAudienceDefinition][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceDefinition]. + + """ + # 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 = [customer_id, audience_description] + 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, audience_insights_service.GenerateAudienceDefinitionRequest + ): + request = ( + audience_insights_service.GenerateAudienceDefinitionRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if audience_description is not None: + request.audience_description = audience_description + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_audience_definition + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_suggested_targeting_insights( + self, + request: Optional[ + Union[ + audience_insights_service.GenerateSuggestedTargetingInsightsRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_insights_service.GenerateSuggestedTargetingInsightsResponse: + r"""Returns a collection of targeting insights (e.g. targetable + audiences) that are relevant to the requested audience. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateSuggestedTargetingInsightsRequest, dict]]): + The request object. Request message for + [AudienceInsightsService.GenerateSuggestedTargetingInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateSuggestedTargetingInsights]. + 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.googleads.v24.services.types.GenerateSuggestedTargetingInsightsResponse: + Response message for + [AudienceInsightsService.GenerateSuggestedTargetingInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateSuggestedTargetingInsights]. + + """ + # 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, + audience_insights_service.GenerateSuggestedTargetingInsightsRequest, + ): + request = audience_insights_service.GenerateSuggestedTargetingInsightsRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_suggested_targeting_insights + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_audience_overlap_insights( + self, + request: Optional[ + Union[ + audience_insights_service.GenerateAudienceOverlapInsightsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + country_location: Optional[criteria.LocationInfo] = None, + primary_attribute: Optional[ + audience_insights_attribute.AudienceInsightsAttribute + ] = None, + dimensions: Optional[ + MutableSequence[ + audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_insights_service.GenerateAudienceOverlapInsightsResponse: + r"""Returns a collection of audience attributes along with estimates + of the overlap between their potential YouTube reach and that of + a given input attribute. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateAudienceOverlapInsightsRequest, dict]]): + The request object. Request message for + [AudienceInsightsService.GenerateAudienceOverlapInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceOverlapInsights]. + customer_id (:class:`str`): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + country_location (:class:`google.ads.googleads.v24.common.types.LocationInfo`): + Required. The country in which to + calculate the sizes and overlaps of + audiences. + + This corresponds to the ``country_location`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + primary_attribute (:class:`google.ads.googleads.v24.common.types.AudienceInsightsAttribute`): + Required. The audience attribute that + should be intersected with all other + eligible audiences. This must be an + Affinity or In-Market UserInterest, an + AgeRange or a Gender. + + This corresponds to the ``primary_attribute`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + dimensions (:class:`MutableSequence[google.ads.googleads.v24.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension]`): + Required. The types of attributes of which to calculate + the overlap with the primary_attribute. The values must + be a subset of AFFINITY_USER_INTEREST, + IN_MARKET_USER_INTEREST, AGE_RANGE and GENDER. + + This corresponds to the ``dimensions`` 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.ads.googleads.v24.services.types.GenerateAudienceOverlapInsightsResponse: + Response message for + [AudienceInsightsService.GenerateAudienceOverlapInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceOverlapInsights]. + + """ + # 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 = [ + customer_id, + country_location, + primary_attribute, + dimensions, + ] + 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, + audience_insights_service.GenerateAudienceOverlapInsightsRequest, + ): + request = audience_insights_service.GenerateAudienceOverlapInsightsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if country_location is not None: + request.country_location = country_location + if primary_attribute is not None: + request.primary_attribute = primary_attribute + if dimensions: + request.dimensions.extend(dimensions) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_audience_overlap_insights + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_targeting_suggestion_metrics( + self, + request: Optional[ + Union[ + audience_insights_service.GenerateTargetingSuggestionMetricsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + audiences: Optional[ + MutableSequence[audience_insights_service.InsightsAudience] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_insights_service.GenerateTargetingSuggestionMetricsResponse: + r"""Returns potential reach metrics for targetable audiences. + + This method helps answer questions like "How many Men aged 18+ + interested in Camping can be reached on YouTube?" + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateTargetingSuggestionMetricsRequest, dict]]): + The request object. Request message for + [AudienceInsightsService.GenerateTargetingSuggestionMetrics][google.ads.googleads.v24.services.AudienceInsightsService.GenerateTargetingSuggestionMetrics]. + customer_id (:class:`str`): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + audiences (:class:`MutableSequence[google.ads.googleads.v24.services.types.InsightsAudience]`): + Required. Audiences to request + metrics for. + + This corresponds to the ``audiences`` 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.ads.googleads.v24.services.types.GenerateTargetingSuggestionMetricsResponse: + Response message for + [AudienceInsightsService.GenerateTargetingSuggestionMetrics][google.ads.googleads.v24.services.AudienceInsightsService.GenerateTargetingSuggestionMetrics]. + + """ + # 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 = [customer_id, audiences] + 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, + audience_insights_service.GenerateTargetingSuggestionMetricsRequest, + ): + request = audience_insights_service.GenerateTargetingSuggestionMetricsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if audiences: + request.audiences.extend(audiences) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_targeting_suggestion_metrics + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AudienceInsightsServiceAsyncClient": + 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__ = ("AudienceInsightsServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/audience_insights_service/client.py b/google/ads/googleads/v24/services/services/audience_insights_service/client.py new file mode 100644 index 000000000..f5d6d78c6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_insights_service/client.py @@ -0,0 +1,1706 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.common.types import audience_insights_attribute +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.enums.types import audience_insights_dimension +from google.ads.googleads.v24.services.types import audience_insights_service +from .transports.base import ( + AudienceInsightsServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AudienceInsightsServiceGrpcTransport +from .transports.grpc_asyncio import AudienceInsightsServiceGrpcAsyncIOTransport + + +class AudienceInsightsServiceClientMeta(type): + """Metaclass for the AudienceInsightsService 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[AudienceInsightsServiceTransport]] + _transport_registry["grpc"] = AudienceInsightsServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + AudienceInsightsServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AudienceInsightsServiceTransport]: + """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 AudienceInsightsServiceClient( + metaclass=AudienceInsightsServiceClientMeta +): + """Audience Insights Service helps users find information about + groups of people and how they can be reached with Google Ads. + Accessible to allowlisted customers only. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AudienceInsightsServiceClient: 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: + AudienceInsightsServiceClient: 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) -> AudienceInsightsServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AudienceInsightsServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @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 = ( + AudienceInsightsServiceClient._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 = ( + AudienceInsightsServiceClient._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 + ): + """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 = AudienceInsightsServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AudienceInsightsServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AudienceInsightsServiceClient._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 = AudienceInsightsServiceClient._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): + """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, + AudienceInsightsServiceTransport, + Callable[..., AudienceInsightsServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the audience insights 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,AudienceInsightsServiceTransport,Callable[..., AudienceInsightsServiceTransport]]]): + 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 AudienceInsightsServiceTransport 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, + ) = AudienceInsightsServiceClient._read_environment_variables() + self._client_cert_source = ( + AudienceInsightsServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + AudienceInsightsServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AudienceInsightsServiceTransport + ) + if transport_provided: + # transport is a AudienceInsightsServiceTransport 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(AudienceInsightsServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AudienceInsightsServiceClient._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[AudienceInsightsServiceTransport], + Callable[..., AudienceInsightsServiceTransport], + ] = ( + AudienceInsightsServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., AudienceInsightsServiceTransport], 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.ads.googleads.v24.services.AudienceInsightsServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AudienceInsightsService", + "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.ads.googleads.v24.services.AudienceInsightsService", + "credentialsType": None, + } + ), + ) + + def generate_insights_finder_report( + self, + request: Optional[ + Union[ + audience_insights_service.GenerateInsightsFinderReportRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + baseline_audience: Optional[ + audience_insights_service.InsightsAudience + ] = None, + specific_audience: Optional[ + audience_insights_service.InsightsAudience + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_insights_service.GenerateInsightsFinderReportResponse: + r"""Creates a saved report that can be viewed in the Insights Finder + tool. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateInsightsFinderReportRequest, dict]): + The request object. Request message for + [AudienceInsightsService.GenerateInsightsFinderReport][google.ads.googleads.v24.services.AudienceInsightsService.GenerateInsightsFinderReport]. + customer_id (str): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + baseline_audience (google.ads.googleads.v24.services.types.InsightsAudience): + Required. A baseline audience for + this report, typically all people in a + region. + + This corresponds to the ``baseline_audience`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + specific_audience (google.ads.googleads.v24.services.types.InsightsAudience): + Required. The specific audience of + interest for this report. The insights + in the report will be based on + attributes more prevalent in this + audience than in the report's baseline + audience. + + This corresponds to the ``specific_audience`` 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.ads.googleads.v24.services.types.GenerateInsightsFinderReportResponse: + The response message for + [AudienceInsightsService.GenerateInsightsFinderReport][google.ads.googleads.v24.services.AudienceInsightsService.GenerateInsightsFinderReport], + containing the shareable URL for the report. + + """ + # 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 = [customer_id, baseline_audience, specific_audience] + 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, + audience_insights_service.GenerateInsightsFinderReportRequest, + ): + request = ( + audience_insights_service.GenerateInsightsFinderReportRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if baseline_audience is not None: + request.baseline_audience = baseline_audience + if specific_audience is not None: + request.specific_audience = specific_audience + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_insights_finder_report + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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_audience_insights_attributes( + self, + request: Optional[ + Union[ + audience_insights_service.ListAudienceInsightsAttributesRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + dimensions: Optional[ + MutableSequence[ + audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension + ] + ] = None, + query_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]]] = (), + ) -> audience_insights_service.ListAudienceInsightsAttributesResponse: + r"""Searches for audience attributes that can be used to generate + insights. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListAudienceInsightsAttributesRequest, dict]): + The request object. Request message for + [AudienceInsightsService.ListAudienceInsightsAttributes][google.ads.googleads.v24.services.AudienceInsightsService.ListAudienceInsightsAttributes]. + customer_id (str): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + dimensions (MutableSequence[google.ads.googleads.v24.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension]): + Required. The types of attributes to be returned. + Supported dimensions are CATEGORY, KNOWLEDGE_GRAPH, + DEVICE, GEO_TARGET_COUNTRY, SUB_COUNTRY_LOCATION, + YOUTUBE_LINEUP, AFFINITY_USER_INTEREST, + IN_MARKET_USER_INTEREST, LIFE_EVENT_USER_INTEREST, + PARENTAL_STATUS, INCOME_RANGE, AGE_RANGE, and GENDER. + + This corresponds to the ``dimensions`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + query_text (str): + Required. A free text query. If the requested dimensions + include Attributes CATEGORY or KNOWLEDGE_GRAPH, then the + attributes returned for those dimensions will match or + be related to this string. For other dimensions, this + field is ignored and all available attributes are + returned. + + This corresponds to the ``query_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.ads.googleads.v24.services.types.ListAudienceInsightsAttributesResponse: + Response message for + [AudienceInsightsService.ListAudienceInsightsAttributes][google.ads.googleads.v24.services.AudienceInsightsService.ListAudienceInsightsAttributes]. + + """ + # 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 = [customer_id, dimensions, query_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, + audience_insights_service.ListAudienceInsightsAttributesRequest, + ): + request = ( + audience_insights_service.ListAudienceInsightsAttributesRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if dimensions is not None: + request.dimensions = dimensions + if query_text is not None: + request.query_text = query_text + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_audience_insights_attributes + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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_insights_eligible_dates( + self, + request: Optional[ + Union[ + audience_insights_service.ListInsightsEligibleDatesRequest, dict + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_insights_service.ListInsightsEligibleDatesResponse: + r"""Lists date ranges for which audience insights data can be + requested. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListInsightsEligibleDatesRequest, dict]): + The request object. Request message for + [AudienceInsightsService.ListInsightsEligibleDates][google.ads.googleads.v24.services.AudienceInsightsService.ListInsightsEligibleDates]. + 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.googleads.v24.services.types.ListInsightsEligibleDatesResponse: + Response message for + [AudienceInsightsService.ListInsightsEligibleDates][google.ads.googleads.v24.services.AudienceInsightsService.ListInsightsEligibleDates]. + + """ + # 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, audience_insights_service.ListInsightsEligibleDatesRequest + ): + request = ( + audience_insights_service.ListInsightsEligibleDatesRequest( + request + ) + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_insights_eligible_dates + ] + + # 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 generate_audience_composition_insights( + self, + request: Optional[ + Union[ + audience_insights_service.GenerateAudienceCompositionInsightsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + audience: Optional[audience_insights_service.InsightsAudience] = None, + dimensions: Optional[ + MutableSequence[ + audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_insights_service.GenerateAudienceCompositionInsightsResponse: + r"""Returns a collection of attributes that are represented in an + audience of interest, with metrics that compare each attribute's + share of the audience with its share of a baseline audience. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateAudienceCompositionInsightsRequest, dict]): + The request object. Request message for + [AudienceInsightsService.GenerateAudienceCompositionInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceCompositionInsights]. + customer_id (str): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + audience (google.ads.googleads.v24.services.types.InsightsAudience): + Required. The audience of interest + for which insights are being requested. + + This corresponds to the ``audience`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + dimensions (MutableSequence[google.ads.googleads.v24.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension]): + Required. The audience dimensions for which composition + insights should be returned. Supported dimensions are + KNOWLEDGE_GRAPH, GEO_TARGET_COUNTRY, + SUB_COUNTRY_LOCATION, YOUTUBE_CHANNEL, YOUTUBE_LINEUP, + AFFINITY_USER_INTEREST, IN_MARKET_USER_INTEREST, + LIFE_EVENT_USER_INTEREST, PARENTAL_STATUS, INCOME_RANGE, + AGE_RANGE, and GENDER. + + This corresponds to the ``dimensions`` 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.ads.googleads.v24.services.types.GenerateAudienceCompositionInsightsResponse: + Response message for + [AudienceInsightsService.GenerateAudienceCompositionInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceCompositionInsights]. + + """ + # 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 = [customer_id, audience, dimensions] + 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, + audience_insights_service.GenerateAudienceCompositionInsightsRequest, + ): + request = audience_insights_service.GenerateAudienceCompositionInsightsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if audience is not None: + request.audience = audience + if dimensions is not None: + request.dimensions = dimensions + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_audience_composition_insights + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_audience_definition( + self, + request: Optional[ + Union[ + audience_insights_service.GenerateAudienceDefinitionRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + audience_description: Optional[ + audience_insights_service.InsightsAudienceDescription + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_insights_service.GenerateAudienceDefinitionResponse: + r"""Returns a collection of audience attributes using generative AI + based on the provided audience description. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateAudienceDefinitionRequest, dict]): + The request object. Request message for + [AudienceInsightsService.GenerateAudienceDefinition][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceDefinition]. + customer_id (str): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + audience_description (google.ads.googleads.v24.services.types.InsightsAudienceDescription): + Required. Provide a text description of an audience to + get AI-generated structured suggestions. This can take + around 5 or more seconds to complete Supported marketing + objectives are: AWARENESS, CONSIDERATION and RESEARCH. + Supported dimensions are: AGE_RANGE, GENDER, + PARENTAL_STATUS, AFFINITY_USER_INTEREST, + IN_MARKET_USER_INTEREST, LIFE_EVENT_USER_INTEREST, + CATEGORY and KNOWLEDGE_GRAPH. + + This corresponds to the ``audience_description`` 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.ads.googleads.v24.services.types.GenerateAudienceDefinitionResponse: + Response message for + [AudienceInsightsService.GenerateAudienceDefinition][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceDefinition]. + + """ + # 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 = [customer_id, audience_description] + 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, audience_insights_service.GenerateAudienceDefinitionRequest + ): + request = ( + audience_insights_service.GenerateAudienceDefinitionRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if audience_description is not None: + request.audience_description = audience_description + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_audience_definition + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_suggested_targeting_insights( + self, + request: Optional[ + Union[ + audience_insights_service.GenerateSuggestedTargetingInsightsRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_insights_service.GenerateSuggestedTargetingInsightsResponse: + r"""Returns a collection of targeting insights (e.g. targetable + audiences) that are relevant to the requested audience. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateSuggestedTargetingInsightsRequest, dict]): + The request object. Request message for + [AudienceInsightsService.GenerateSuggestedTargetingInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateSuggestedTargetingInsights]. + 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.googleads.v24.services.types.GenerateSuggestedTargetingInsightsResponse: + Response message for + [AudienceInsightsService.GenerateSuggestedTargetingInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateSuggestedTargetingInsights]. + + """ + # 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, + audience_insights_service.GenerateSuggestedTargetingInsightsRequest, + ): + request = audience_insights_service.GenerateSuggestedTargetingInsightsRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_suggested_targeting_insights + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_audience_overlap_insights( + self, + request: Optional[ + Union[ + audience_insights_service.GenerateAudienceOverlapInsightsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + country_location: Optional[criteria.LocationInfo] = None, + primary_attribute: Optional[ + audience_insights_attribute.AudienceInsightsAttribute + ] = None, + dimensions: Optional[ + MutableSequence[ + audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_insights_service.GenerateAudienceOverlapInsightsResponse: + r"""Returns a collection of audience attributes along with estimates + of the overlap between their potential YouTube reach and that of + a given input attribute. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateAudienceOverlapInsightsRequest, dict]): + The request object. Request message for + [AudienceInsightsService.GenerateAudienceOverlapInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceOverlapInsights]. + customer_id (str): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + country_location (google.ads.googleads.v24.common.types.LocationInfo): + Required. The country in which to + calculate the sizes and overlaps of + audiences. + + This corresponds to the ``country_location`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + primary_attribute (google.ads.googleads.v24.common.types.AudienceInsightsAttribute): + Required. The audience attribute that + should be intersected with all other + eligible audiences. This must be an + Affinity or In-Market UserInterest, an + AgeRange or a Gender. + + This corresponds to the ``primary_attribute`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + dimensions (MutableSequence[google.ads.googleads.v24.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension]): + Required. The types of attributes of which to calculate + the overlap with the primary_attribute. The values must + be a subset of AFFINITY_USER_INTEREST, + IN_MARKET_USER_INTEREST, AGE_RANGE and GENDER. + + This corresponds to the ``dimensions`` 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.ads.googleads.v24.services.types.GenerateAudienceOverlapInsightsResponse: + Response message for + [AudienceInsightsService.GenerateAudienceOverlapInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceOverlapInsights]. + + """ + # 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 = [ + customer_id, + country_location, + primary_attribute, + dimensions, + ] + 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, + audience_insights_service.GenerateAudienceOverlapInsightsRequest, + ): + request = audience_insights_service.GenerateAudienceOverlapInsightsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if country_location is not None: + request.country_location = country_location + if primary_attribute is not None: + request.primary_attribute = primary_attribute + if dimensions is not None: + request.dimensions = dimensions + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_audience_overlap_insights + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_targeting_suggestion_metrics( + self, + request: Optional[ + Union[ + audience_insights_service.GenerateTargetingSuggestionMetricsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + audiences: Optional[ + MutableSequence[audience_insights_service.InsightsAudience] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_insights_service.GenerateTargetingSuggestionMetricsResponse: + r"""Returns potential reach metrics for targetable audiences. + + This method helps answer questions like "How many Men aged 18+ + interested in Camping can be reached on YouTube?" + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateTargetingSuggestionMetricsRequest, dict]): + The request object. Request message for + [AudienceInsightsService.GenerateTargetingSuggestionMetrics][google.ads.googleads.v24.services.AudienceInsightsService.GenerateTargetingSuggestionMetrics]. + customer_id (str): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + audiences (MutableSequence[google.ads.googleads.v24.services.types.InsightsAudience]): + Required. Audiences to request + metrics for. + + This corresponds to the ``audiences`` 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.ads.googleads.v24.services.types.GenerateTargetingSuggestionMetricsResponse: + Response message for + [AudienceInsightsService.GenerateTargetingSuggestionMetrics][google.ads.googleads.v24.services.AudienceInsightsService.GenerateTargetingSuggestionMetrics]. + + """ + # 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 = [customer_id, audiences] + 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, + audience_insights_service.GenerateTargetingSuggestionMetricsRequest, + ): + request = audience_insights_service.GenerateTargetingSuggestionMetricsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if audiences is not None: + request.audiences = audiences + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_targeting_suggestion_metrics + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AudienceInsightsServiceClient": + 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() + + +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__ = ("AudienceInsightsServiceClient",) diff --git a/google/ads/googleads/v24/services/services/audience_insights_service/transports/README.rst b/google/ads/googleads/v24/services/services/audience_insights_service/transports/README.rst new file mode 100644 index 000000000..b7ae724e3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_insights_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AudienceInsightsServiceTransport` is the ABC for all transports. +- public child `AudienceInsightsServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AudienceInsightsServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAudienceInsightsServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AudienceInsightsServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/audience_insights_service/transports/__init__.py b/google/ads/googleads/v24/services/services/audience_insights_service/transports/__init__.py new file mode 100644 index 000000000..951b08b13 --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_insights_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AudienceInsightsServiceTransport +from .grpc import AudienceInsightsServiceGrpcTransport +from .grpc_asyncio import AudienceInsightsServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AudienceInsightsServiceTransport]] +_transport_registry["grpc"] = AudienceInsightsServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + AudienceInsightsServiceGrpcAsyncIOTransport +) + +__all__ = ( + "AudienceInsightsServiceTransport", + "AudienceInsightsServiceGrpcTransport", + "AudienceInsightsServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/audience_insights_service/transports/base.py b/google/ads/googleads/v24/services/services/audience_insights_service/transports/base.py new file mode 100644 index 000000000..556c3852e --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_insights_service/transports/base.py @@ -0,0 +1,308 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import audience_insights_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 AudienceInsightsServiceTransport(abc.ABC): + """Abstract transport class for AudienceInsightsService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.generate_insights_finder_report: gapic_v1.method.wrap_method( + self.generate_insights_finder_report, + default_timeout=None, + client_info=client_info, + ), + self.list_audience_insights_attributes: gapic_v1.method.wrap_method( + self.list_audience_insights_attributes, + default_timeout=None, + client_info=client_info, + ), + self.list_insights_eligible_dates: gapic_v1.method.wrap_method( + self.list_insights_eligible_dates, + default_timeout=None, + client_info=client_info, + ), + self.generate_audience_composition_insights: gapic_v1.method.wrap_method( + self.generate_audience_composition_insights, + default_timeout=None, + client_info=client_info, + ), + self.generate_audience_definition: gapic_v1.method.wrap_method( + self.generate_audience_definition, + default_timeout=None, + client_info=client_info, + ), + self.generate_suggested_targeting_insights: gapic_v1.method.wrap_method( + self.generate_suggested_targeting_insights, + default_timeout=None, + client_info=client_info, + ), + self.generate_audience_overlap_insights: gapic_v1.method.wrap_method( + self.generate_audience_overlap_insights, + default_timeout=None, + client_info=client_info, + ), + self.generate_targeting_suggestion_metrics: gapic_v1.method.wrap_method( + self.generate_targeting_suggestion_metrics, + 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 generate_insights_finder_report( + self, + ) -> Callable[ + [audience_insights_service.GenerateInsightsFinderReportRequest], + Union[ + audience_insights_service.GenerateInsightsFinderReportResponse, + Awaitable[ + audience_insights_service.GenerateInsightsFinderReportResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def list_audience_insights_attributes( + self, + ) -> Callable[ + [audience_insights_service.ListAudienceInsightsAttributesRequest], + Union[ + audience_insights_service.ListAudienceInsightsAttributesResponse, + Awaitable[ + audience_insights_service.ListAudienceInsightsAttributesResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def list_insights_eligible_dates( + self, + ) -> Callable[ + [audience_insights_service.ListInsightsEligibleDatesRequest], + Union[ + audience_insights_service.ListInsightsEligibleDatesResponse, + Awaitable[ + audience_insights_service.ListInsightsEligibleDatesResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def generate_audience_composition_insights( + self, + ) -> Callable[ + [audience_insights_service.GenerateAudienceCompositionInsightsRequest], + Union[ + audience_insights_service.GenerateAudienceCompositionInsightsResponse, + Awaitable[ + audience_insights_service.GenerateAudienceCompositionInsightsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def generate_audience_definition( + self, + ) -> Callable[ + [audience_insights_service.GenerateAudienceDefinitionRequest], + Union[ + audience_insights_service.GenerateAudienceDefinitionResponse, + Awaitable[ + audience_insights_service.GenerateAudienceDefinitionResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def generate_suggested_targeting_insights( + self, + ) -> Callable[ + [audience_insights_service.GenerateSuggestedTargetingInsightsRequest], + Union[ + audience_insights_service.GenerateSuggestedTargetingInsightsResponse, + Awaitable[ + audience_insights_service.GenerateSuggestedTargetingInsightsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def generate_audience_overlap_insights( + self, + ) -> Callable[ + [audience_insights_service.GenerateAudienceOverlapInsightsRequest], + Union[ + audience_insights_service.GenerateAudienceOverlapInsightsResponse, + Awaitable[ + audience_insights_service.GenerateAudienceOverlapInsightsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def generate_targeting_suggestion_metrics( + self, + ) -> Callable[ + [audience_insights_service.GenerateTargetingSuggestionMetricsRequest], + Union[ + audience_insights_service.GenerateTargetingSuggestionMetricsResponse, + Awaitable[ + audience_insights_service.GenerateTargetingSuggestionMetricsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AudienceInsightsServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/audience_insights_service/transports/grpc.py b/google/ads/googleads/v24/services/services/audience_insights_service/transports/grpc.py new file mode 100644 index 000000000..fd1769d0c --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_insights_service/transports/grpc.py @@ -0,0 +1,660 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import audience_insights_service +from .base import AudienceInsightsServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AudienceInsightsService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AudienceInsightsService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AudienceInsightsServiceGrpcTransport(AudienceInsightsServiceTransport): + """gRPC backend transport for AudienceInsightsService. + + Audience Insights Service helps users find information about + groups of people and how they can be reached with Google Ads. + Accessible to allowlisted customers only. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 generate_insights_finder_report( + self, + ) -> Callable[ + [audience_insights_service.GenerateInsightsFinderReportRequest], + audience_insights_service.GenerateInsightsFinderReportResponse, + ]: + r"""Return a callable for the generate insights finder + report method over gRPC. + + Creates a saved report that can be viewed in the Insights Finder + tool. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateInsightsFinderReportRequest], + ~.GenerateInsightsFinderReportResponse]: + 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 "generate_insights_finder_report" not in self._stubs: + self._stubs["generate_insights_finder_report"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/GenerateInsightsFinderReport", + request_serializer=audience_insights_service.GenerateInsightsFinderReportRequest.serialize, + response_deserializer=audience_insights_service.GenerateInsightsFinderReportResponse.deserialize, + ) + ) + return self._stubs["generate_insights_finder_report"] + + @property + def list_audience_insights_attributes( + self, + ) -> Callable[ + [audience_insights_service.ListAudienceInsightsAttributesRequest], + audience_insights_service.ListAudienceInsightsAttributesResponse, + ]: + r"""Return a callable for the list audience insights + attributes method over gRPC. + + Searches for audience attributes that can be used to generate + insights. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.ListAudienceInsightsAttributesRequest], + ~.ListAudienceInsightsAttributesResponse]: + 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_audience_insights_attributes" not in self._stubs: + self._stubs["list_audience_insights_attributes"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/ListAudienceInsightsAttributes", + request_serializer=audience_insights_service.ListAudienceInsightsAttributesRequest.serialize, + response_deserializer=audience_insights_service.ListAudienceInsightsAttributesResponse.deserialize, + ) + ) + return self._stubs["list_audience_insights_attributes"] + + @property + def list_insights_eligible_dates( + self, + ) -> Callable[ + [audience_insights_service.ListInsightsEligibleDatesRequest], + audience_insights_service.ListInsightsEligibleDatesResponse, + ]: + r"""Return a callable for the list insights eligible dates method over gRPC. + + Lists date ranges for which audience insights data can be + requested. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.ListInsightsEligibleDatesRequest], + ~.ListInsightsEligibleDatesResponse]: + 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_insights_eligible_dates" not in self._stubs: + self._stubs["list_insights_eligible_dates"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/ListInsightsEligibleDates", + request_serializer=audience_insights_service.ListInsightsEligibleDatesRequest.serialize, + response_deserializer=audience_insights_service.ListInsightsEligibleDatesResponse.deserialize, + ) + ) + return self._stubs["list_insights_eligible_dates"] + + @property + def generate_audience_composition_insights( + self, + ) -> Callable[ + [audience_insights_service.GenerateAudienceCompositionInsightsRequest], + audience_insights_service.GenerateAudienceCompositionInsightsResponse, + ]: + r"""Return a callable for the generate audience composition + insights method over gRPC. + + Returns a collection of attributes that are represented in an + audience of interest, with metrics that compare each attribute's + share of the audience with its share of a baseline audience. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateAudienceCompositionInsightsRequest], + ~.GenerateAudienceCompositionInsightsResponse]: + 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 "generate_audience_composition_insights" not in self._stubs: + self._stubs["generate_audience_composition_insights"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/GenerateAudienceCompositionInsights", + request_serializer=audience_insights_service.GenerateAudienceCompositionInsightsRequest.serialize, + response_deserializer=audience_insights_service.GenerateAudienceCompositionInsightsResponse.deserialize, + ) + ) + return self._stubs["generate_audience_composition_insights"] + + @property + def generate_audience_definition( + self, + ) -> Callable[ + [audience_insights_service.GenerateAudienceDefinitionRequest], + audience_insights_service.GenerateAudienceDefinitionResponse, + ]: + r"""Return a callable for the generate audience definition method over gRPC. + + Returns a collection of audience attributes using generative AI + based on the provided audience description. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateAudienceDefinitionRequest], + ~.GenerateAudienceDefinitionResponse]: + 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 "generate_audience_definition" not in self._stubs: + self._stubs["generate_audience_definition"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/GenerateAudienceDefinition", + request_serializer=audience_insights_service.GenerateAudienceDefinitionRequest.serialize, + response_deserializer=audience_insights_service.GenerateAudienceDefinitionResponse.deserialize, + ) + ) + return self._stubs["generate_audience_definition"] + + @property + def generate_suggested_targeting_insights( + self, + ) -> Callable[ + [audience_insights_service.GenerateSuggestedTargetingInsightsRequest], + audience_insights_service.GenerateSuggestedTargetingInsightsResponse, + ]: + r"""Return a callable for the generate suggested targeting + insights method over gRPC. + + Returns a collection of targeting insights (e.g. targetable + audiences) that are relevant to the requested audience. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateSuggestedTargetingInsightsRequest], + ~.GenerateSuggestedTargetingInsightsResponse]: + 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 "generate_suggested_targeting_insights" not in self._stubs: + self._stubs["generate_suggested_targeting_insights"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/GenerateSuggestedTargetingInsights", + request_serializer=audience_insights_service.GenerateSuggestedTargetingInsightsRequest.serialize, + response_deserializer=audience_insights_service.GenerateSuggestedTargetingInsightsResponse.deserialize, + ) + ) + return self._stubs["generate_suggested_targeting_insights"] + + @property + def generate_audience_overlap_insights( + self, + ) -> Callable[ + [audience_insights_service.GenerateAudienceOverlapInsightsRequest], + audience_insights_service.GenerateAudienceOverlapInsightsResponse, + ]: + r"""Return a callable for the generate audience overlap + insights method over gRPC. + + Returns a collection of audience attributes along with estimates + of the overlap between their potential YouTube reach and that of + a given input attribute. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateAudienceOverlapInsightsRequest], + ~.GenerateAudienceOverlapInsightsResponse]: + 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 "generate_audience_overlap_insights" not in self._stubs: + self._stubs["generate_audience_overlap_insights"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/GenerateAudienceOverlapInsights", + request_serializer=audience_insights_service.GenerateAudienceOverlapInsightsRequest.serialize, + response_deserializer=audience_insights_service.GenerateAudienceOverlapInsightsResponse.deserialize, + ) + ) + return self._stubs["generate_audience_overlap_insights"] + + @property + def generate_targeting_suggestion_metrics( + self, + ) -> Callable[ + [audience_insights_service.GenerateTargetingSuggestionMetricsRequest], + audience_insights_service.GenerateTargetingSuggestionMetricsResponse, + ]: + r"""Return a callable for the generate targeting suggestion + metrics method over gRPC. + + Returns potential reach metrics for targetable audiences. + + This method helps answer questions like "How many Men aged 18+ + interested in Camping can be reached on YouTube?" + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateTargetingSuggestionMetricsRequest], + ~.GenerateTargetingSuggestionMetricsResponse]: + 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 "generate_targeting_suggestion_metrics" not in self._stubs: + self._stubs["generate_targeting_suggestion_metrics"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/GenerateTargetingSuggestionMetrics", + request_serializer=audience_insights_service.GenerateTargetingSuggestionMetricsRequest.serialize, + response_deserializer=audience_insights_service.GenerateTargetingSuggestionMetricsResponse.deserialize, + ) + ) + return self._stubs["generate_targeting_suggestion_metrics"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AudienceInsightsServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/audience_insights_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/audience_insights_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..e0c712ed4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_insights_service/transports/grpc_asyncio.py @@ -0,0 +1,730 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import audience_insights_service +from .base import AudienceInsightsServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AudienceInsightsService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AudienceInsightsService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AudienceInsightsServiceGrpcAsyncIOTransport( + AudienceInsightsServiceTransport +): + """gRPC AsyncIO backend transport for AudienceInsightsService. + + Audience Insights Service helps users find information about + groups of people and how they can be reached with Google Ads. + Accessible to allowlisted customers only. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 generate_insights_finder_report( + self, + ) -> Callable[ + [audience_insights_service.GenerateInsightsFinderReportRequest], + Awaitable[ + audience_insights_service.GenerateInsightsFinderReportResponse + ], + ]: + r"""Return a callable for the generate insights finder + report method over gRPC. + + Creates a saved report that can be viewed in the Insights Finder + tool. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateInsightsFinderReportRequest], + Awaitable[~.GenerateInsightsFinderReportResponse]]: + 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 "generate_insights_finder_report" not in self._stubs: + self._stubs["generate_insights_finder_report"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/GenerateInsightsFinderReport", + request_serializer=audience_insights_service.GenerateInsightsFinderReportRequest.serialize, + response_deserializer=audience_insights_service.GenerateInsightsFinderReportResponse.deserialize, + ) + ) + return self._stubs["generate_insights_finder_report"] + + @property + def list_audience_insights_attributes( + self, + ) -> Callable[ + [audience_insights_service.ListAudienceInsightsAttributesRequest], + Awaitable[ + audience_insights_service.ListAudienceInsightsAttributesResponse + ], + ]: + r"""Return a callable for the list audience insights + attributes method over gRPC. + + Searches for audience attributes that can be used to generate + insights. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.ListAudienceInsightsAttributesRequest], + Awaitable[~.ListAudienceInsightsAttributesResponse]]: + 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_audience_insights_attributes" not in self._stubs: + self._stubs["list_audience_insights_attributes"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/ListAudienceInsightsAttributes", + request_serializer=audience_insights_service.ListAudienceInsightsAttributesRequest.serialize, + response_deserializer=audience_insights_service.ListAudienceInsightsAttributesResponse.deserialize, + ) + ) + return self._stubs["list_audience_insights_attributes"] + + @property + def list_insights_eligible_dates( + self, + ) -> Callable[ + [audience_insights_service.ListInsightsEligibleDatesRequest], + Awaitable[audience_insights_service.ListInsightsEligibleDatesResponse], + ]: + r"""Return a callable for the list insights eligible dates method over gRPC. + + Lists date ranges for which audience insights data can be + requested. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.ListInsightsEligibleDatesRequest], + Awaitable[~.ListInsightsEligibleDatesResponse]]: + 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_insights_eligible_dates" not in self._stubs: + self._stubs["list_insights_eligible_dates"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/ListInsightsEligibleDates", + request_serializer=audience_insights_service.ListInsightsEligibleDatesRequest.serialize, + response_deserializer=audience_insights_service.ListInsightsEligibleDatesResponse.deserialize, + ) + ) + return self._stubs["list_insights_eligible_dates"] + + @property + def generate_audience_composition_insights( + self, + ) -> Callable[ + [audience_insights_service.GenerateAudienceCompositionInsightsRequest], + Awaitable[ + audience_insights_service.GenerateAudienceCompositionInsightsResponse + ], + ]: + r"""Return a callable for the generate audience composition + insights method over gRPC. + + Returns a collection of attributes that are represented in an + audience of interest, with metrics that compare each attribute's + share of the audience with its share of a baseline audience. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateAudienceCompositionInsightsRequest], + Awaitable[~.GenerateAudienceCompositionInsightsResponse]]: + 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 "generate_audience_composition_insights" not in self._stubs: + self._stubs["generate_audience_composition_insights"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/GenerateAudienceCompositionInsights", + request_serializer=audience_insights_service.GenerateAudienceCompositionInsightsRequest.serialize, + response_deserializer=audience_insights_service.GenerateAudienceCompositionInsightsResponse.deserialize, + ) + ) + return self._stubs["generate_audience_composition_insights"] + + @property + def generate_audience_definition( + self, + ) -> Callable[ + [audience_insights_service.GenerateAudienceDefinitionRequest], + Awaitable[audience_insights_service.GenerateAudienceDefinitionResponse], + ]: + r"""Return a callable for the generate audience definition method over gRPC. + + Returns a collection of audience attributes using generative AI + based on the provided audience description. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateAudienceDefinitionRequest], + Awaitable[~.GenerateAudienceDefinitionResponse]]: + 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 "generate_audience_definition" not in self._stubs: + self._stubs["generate_audience_definition"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/GenerateAudienceDefinition", + request_serializer=audience_insights_service.GenerateAudienceDefinitionRequest.serialize, + response_deserializer=audience_insights_service.GenerateAudienceDefinitionResponse.deserialize, + ) + ) + return self._stubs["generate_audience_definition"] + + @property + def generate_suggested_targeting_insights( + self, + ) -> Callable[ + [audience_insights_service.GenerateSuggestedTargetingInsightsRequest], + Awaitable[ + audience_insights_service.GenerateSuggestedTargetingInsightsResponse + ], + ]: + r"""Return a callable for the generate suggested targeting + insights method over gRPC. + + Returns a collection of targeting insights (e.g. targetable + audiences) that are relevant to the requested audience. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateSuggestedTargetingInsightsRequest], + Awaitable[~.GenerateSuggestedTargetingInsightsResponse]]: + 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 "generate_suggested_targeting_insights" not in self._stubs: + self._stubs["generate_suggested_targeting_insights"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/GenerateSuggestedTargetingInsights", + request_serializer=audience_insights_service.GenerateSuggestedTargetingInsightsRequest.serialize, + response_deserializer=audience_insights_service.GenerateSuggestedTargetingInsightsResponse.deserialize, + ) + ) + return self._stubs["generate_suggested_targeting_insights"] + + @property + def generate_audience_overlap_insights( + self, + ) -> Callable[ + [audience_insights_service.GenerateAudienceOverlapInsightsRequest], + Awaitable[ + audience_insights_service.GenerateAudienceOverlapInsightsResponse + ], + ]: + r"""Return a callable for the generate audience overlap + insights method over gRPC. + + Returns a collection of audience attributes along with estimates + of the overlap between their potential YouTube reach and that of + a given input attribute. + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateAudienceOverlapInsightsRequest], + Awaitable[~.GenerateAudienceOverlapInsightsResponse]]: + 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 "generate_audience_overlap_insights" not in self._stubs: + self._stubs["generate_audience_overlap_insights"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/GenerateAudienceOverlapInsights", + request_serializer=audience_insights_service.GenerateAudienceOverlapInsightsRequest.serialize, + response_deserializer=audience_insights_service.GenerateAudienceOverlapInsightsResponse.deserialize, + ) + ) + return self._stubs["generate_audience_overlap_insights"] + + @property + def generate_targeting_suggestion_metrics( + self, + ) -> Callable[ + [audience_insights_service.GenerateTargetingSuggestionMetricsRequest], + Awaitable[ + audience_insights_service.GenerateTargetingSuggestionMetricsResponse + ], + ]: + r"""Return a callable for the generate targeting suggestion + metrics method over gRPC. + + Returns potential reach metrics for targetable audiences. + + This method helps answer questions like "How many Men aged 18+ + interested in Camping can be reached on YouTube?" + + List of thrown errors: `AudienceInsightsError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateTargetingSuggestionMetricsRequest], + Awaitable[~.GenerateTargetingSuggestionMetricsResponse]]: + 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 "generate_targeting_suggestion_metrics" not in self._stubs: + self._stubs["generate_targeting_suggestion_metrics"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceInsightsService/GenerateTargetingSuggestionMetrics", + request_serializer=audience_insights_service.GenerateTargetingSuggestionMetricsRequest.serialize, + response_deserializer=audience_insights_service.GenerateTargetingSuggestionMetricsResponse.deserialize, + ) + ) + return self._stubs["generate_targeting_suggestion_metrics"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.generate_insights_finder_report: self._wrap_method( + self.generate_insights_finder_report, + default_timeout=None, + client_info=client_info, + ), + self.list_audience_insights_attributes: self._wrap_method( + self.list_audience_insights_attributes, + default_timeout=None, + client_info=client_info, + ), + self.list_insights_eligible_dates: self._wrap_method( + self.list_insights_eligible_dates, + default_timeout=None, + client_info=client_info, + ), + self.generate_audience_composition_insights: self._wrap_method( + self.generate_audience_composition_insights, + default_timeout=None, + client_info=client_info, + ), + self.generate_audience_definition: self._wrap_method( + self.generate_audience_definition, + default_timeout=None, + client_info=client_info, + ), + self.generate_suggested_targeting_insights: self._wrap_method( + self.generate_suggested_targeting_insights, + default_timeout=None, + client_info=client_info, + ), + self.generate_audience_overlap_insights: self._wrap_method( + self.generate_audience_overlap_insights, + default_timeout=None, + client_info=client_info, + ), + self.generate_targeting_suggestion_metrics: self._wrap_method( + self.generate_targeting_suggestion_metrics, + 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" + + +__all__ = ("AudienceInsightsServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/audience_service/__init__.py b/google/ads/googleads/v24/services/services/audience_service/__init__.py new file mode 100644 index 000000000..ab1137cfc --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AudienceServiceClient +from .async_client import AudienceServiceAsyncClient + +__all__ = ( + "AudienceServiceClient", + "AudienceServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/audience_service/async_client.py b/google/ads/googleads/v24/services/services/audience_service/async_client.py new file mode 100644 index 000000000..2289d9822 --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_service/async_client.py @@ -0,0 +1,427 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import audience_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AudienceServiceTransport, DEFAULT_CLIENT_INFO +from .client import AudienceServiceClient + +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 AudienceServiceAsyncClient: + """Service to manage audiences.""" + + _client: AudienceServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AudienceServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AudienceServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + AudienceServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = AudienceServiceClient._DEFAULT_UNIVERSE + + asset_group_path = staticmethod(AudienceServiceClient.asset_group_path) + parse_asset_group_path = staticmethod( + AudienceServiceClient.parse_asset_group_path + ) + audience_path = staticmethod(AudienceServiceClient.audience_path) + parse_audience_path = staticmethod( + AudienceServiceClient.parse_audience_path + ) + detailed_demographic_path = staticmethod( + AudienceServiceClient.detailed_demographic_path + ) + parse_detailed_demographic_path = staticmethod( + AudienceServiceClient.parse_detailed_demographic_path + ) + life_event_path = staticmethod(AudienceServiceClient.life_event_path) + parse_life_event_path = staticmethod( + AudienceServiceClient.parse_life_event_path + ) + common_billing_account_path = staticmethod( + AudienceServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AudienceServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(AudienceServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + AudienceServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AudienceServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AudienceServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AudienceServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AudienceServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AudienceServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AudienceServiceClient.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: + AudienceServiceAsyncClient: The constructed client. + """ + return AudienceServiceClient.from_service_account_info.__func__(AudienceServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AudienceServiceAsyncClient: The constructed client. + """ + return AudienceServiceClient.from_service_account_file.__func__(AudienceServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AudienceServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AudienceServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AudienceServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = AudienceServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AudienceServiceTransport, + Callable[..., AudienceServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the audience 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,AudienceServiceTransport,Callable[..., AudienceServiceTransport]]]): + 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 AudienceServiceTransport 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 = AudienceServiceClient( + 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.ads.googleads.v24.services.AudienceServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AudienceService", + "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.ads.googleads.v24.services.AudienceService", + "credentialsType": None, + } + ), + ) + + async def mutate_audiences( + self, + request: Optional[ + Union[audience_service.MutateAudiencesRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[audience_service.AudienceOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_service.MutateAudiencesResponse: + r"""Creates audiences. Operation statuses are returned. + + List of thrown errors: `AudienceError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateAudiencesRequest, dict]]): + The request object. Request message for + [AudienceService.MutateAudiences][google.ads.googleads.v24.services.AudienceService.MutateAudiences]. + customer_id (:class:`str`): + Required. The ID of the customer + whose audiences are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.AudienceOperation]`): + Required. The list of operations to + perform on individual audiences. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAudiencesResponse: + Response message for an audience + mutate. + + """ + # 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 = [customer_id, operations] + 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, audience_service.MutateAudiencesRequest): + request = audience_service.MutateAudiencesRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_audiences + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "AudienceServiceAsyncClient": + 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__ = ("AudienceServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/audience_service/client.py b/google/ads/googleads/v24/services/services/audience_service/client.py new file mode 100644 index 000000000..703f1eb85 --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_service/client.py @@ -0,0 +1,939 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import audience_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AudienceServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import AudienceServiceGrpcTransport +from .transports.grpc_asyncio import AudienceServiceGrpcAsyncIOTransport + + +class AudienceServiceClientMeta(type): + """Metaclass for the AudienceService 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[AudienceServiceTransport]] + _transport_registry["grpc"] = AudienceServiceGrpcTransport + _transport_registry["grpc_asyncio"] = AudienceServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AudienceServiceTransport]: + """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 AudienceServiceClient(metaclass=AudienceServiceClientMeta): + """Service to manage audiences.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AudienceServiceClient: 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: + AudienceServiceClient: 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) -> AudienceServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AudienceServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def asset_group_path( + customer_id: str, + asset_group_id: str, + ) -> str: + """Returns a fully-qualified asset_group string.""" + return "customers/{customer_id}/assetGroups/{asset_group_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + ) + + @staticmethod + def parse_asset_group_path(path: str) -> Dict[str, str]: + """Parses a asset_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def audience_path( + customer_id: str, + audience_id: str, + ) -> str: + """Returns a fully-qualified audience string.""" + return "customers/{customer_id}/audiences/{audience_id}".format( + customer_id=customer_id, + audience_id=audience_id, + ) + + @staticmethod + def parse_audience_path(path: str) -> Dict[str, str]: + """Parses a audience path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/audiences/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def detailed_demographic_path( + customer_id: str, + detailed_demographic_id: str, + ) -> str: + """Returns a fully-qualified detailed_demographic string.""" + return "customers/{customer_id}/detailedDemographics/{detailed_demographic_id}".format( + customer_id=customer_id, + detailed_demographic_id=detailed_demographic_id, + ) + + @staticmethod + def parse_detailed_demographic_path(path: str) -> Dict[str, str]: + """Parses a detailed_demographic path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/detailedDemographics/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def life_event_path( + customer_id: str, + life_event_id: str, + ) -> str: + """Returns a fully-qualified life_event string.""" + return "customers/{customer_id}/lifeEvents/{life_event_id}".format( + customer_id=customer_id, + life_event_id=life_event_id, + ) + + @staticmethod + def parse_life_event_path(path: str) -> Dict[str, str]: + """Parses a life_event path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/lifeEvents/(?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 = AudienceServiceClient._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 = AudienceServiceClient._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 + ): + """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 = AudienceServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AudienceServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + AudienceServiceClient._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 = AudienceServiceClient._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): + """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, + AudienceServiceTransport, + Callable[..., AudienceServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the audience 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,AudienceServiceTransport,Callable[..., AudienceServiceTransport]]]): + 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 AudienceServiceTransport 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, + ) = AudienceServiceClient._read_environment_variables() + self._client_cert_source = ( + AudienceServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = AudienceServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AudienceServiceTransport) + if transport_provided: + # transport is a AudienceServiceTransport 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(AudienceServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AudienceServiceClient._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[AudienceServiceTransport], + Callable[..., AudienceServiceTransport], + ] = ( + AudienceServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., AudienceServiceTransport], 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.ads.googleads.v24.services.AudienceServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AudienceService", + "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.ads.googleads.v24.services.AudienceService", + "credentialsType": None, + } + ), + ) + + def mutate_audiences( + self, + request: Optional[ + Union[audience_service.MutateAudiencesRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[audience_service.AudienceOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> audience_service.MutateAudiencesResponse: + r"""Creates audiences. Operation statuses are returned. + + List of thrown errors: `AudienceError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateAudiencesRequest, dict]): + The request object. Request message for + [AudienceService.MutateAudiences][google.ads.googleads.v24.services.AudienceService.MutateAudiences]. + customer_id (str): + Required. The ID of the customer + whose audiences are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.AudienceOperation]): + Required. The list of operations to + perform on individual audiences. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateAudiencesResponse: + Response message for an audience + mutate. + + """ + # 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 = [customer_id, operations] + 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, audience_service.MutateAudiencesRequest): + request = audience_service.MutateAudiencesRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.mutate_audiences] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AudienceServiceClient": + 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() + + +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__ = ("AudienceServiceClient",) diff --git a/google/ads/googleads/v24/services/services/audience_service/transports/README.rst b/google/ads/googleads/v24/services/services/audience_service/transports/README.rst new file mode 100644 index 000000000..5d2e49020 --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AudienceServiceTransport` is the ABC for all transports. +- public child `AudienceServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AudienceServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAudienceServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AudienceServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/audience_service/transports/__init__.py b/google/ads/googleads/v24/services/services/audience_service/transports/__init__.py new file mode 100644 index 000000000..d908c22b5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AudienceServiceTransport +from .grpc import AudienceServiceGrpcTransport +from .grpc_asyncio import AudienceServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AudienceServiceTransport]] +_transport_registry["grpc"] = AudienceServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AudienceServiceGrpcAsyncIOTransport + +__all__ = ( + "AudienceServiceTransport", + "AudienceServiceGrpcTransport", + "AudienceServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/audience_service/transports/base.py b/google/ads/googleads/v24/services/services/audience_service/transports/base.py new file mode 100644 index 000000000..d6be9aa7f --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import audience_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 AudienceServiceTransport(abc.ABC): + """Abstract transport class for AudienceService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_audiences: gapic_v1.method.wrap_method( + self.mutate_audiences, + 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 mutate_audiences( + self, + ) -> Callable[ + [audience_service.MutateAudiencesRequest], + Union[ + audience_service.MutateAudiencesResponse, + Awaitable[audience_service.MutateAudiencesResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AudienceServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/audience_service/transports/grpc.py b/google/ads/googleads/v24/services/services/audience_service/transports/grpc.py new file mode 100644 index 000000000..d1fcf4193 --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_service/transports/grpc.py @@ -0,0 +1,383 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import audience_service +from .base import AudienceServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AudienceService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AudienceService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AudienceServiceGrpcTransport(AudienceServiceTransport): + """gRPC backend transport for AudienceService. + + Service to manage audiences. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_audiences( + self, + ) -> Callable[ + [audience_service.MutateAudiencesRequest], + audience_service.MutateAudiencesResponse, + ]: + r"""Return a callable for the mutate audiences method over gRPC. + + Creates audiences. Operation statuses are returned. + + List of thrown errors: `AudienceError <>`__ + + Returns: + Callable[[~.MutateAudiencesRequest], + ~.MutateAudiencesResponse]: + 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 "mutate_audiences" not in self._stubs: + self._stubs["mutate_audiences"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceService/MutateAudiences", + request_serializer=audience_service.MutateAudiencesRequest.serialize, + response_deserializer=audience_service.MutateAudiencesResponse.deserialize, + ) + return self._stubs["mutate_audiences"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AudienceServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/audience_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/audience_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..9f90d99af --- /dev/null +++ b/google/ads/googleads/v24/services/services/audience_service/transports/grpc_asyncio.py @@ -0,0 +1,404 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import audience_service +from .base import AudienceServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.AudienceService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AudienceService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AudienceServiceGrpcAsyncIOTransport(AudienceServiceTransport): + """gRPC AsyncIO backend transport for AudienceService. + + Service to manage audiences. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_audiences( + self, + ) -> Callable[ + [audience_service.MutateAudiencesRequest], + Awaitable[audience_service.MutateAudiencesResponse], + ]: + r"""Return a callable for the mutate audiences method over gRPC. + + Creates audiences. Operation statuses are returned. + + List of thrown errors: `AudienceError <>`__ + + Returns: + Callable[[~.MutateAudiencesRequest], + Awaitable[~.MutateAudiencesResponse]]: + 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 "mutate_audiences" not in self._stubs: + self._stubs["mutate_audiences"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AudienceService/MutateAudiences", + request_serializer=audience_service.MutateAudiencesRequest.serialize, + response_deserializer=audience_service.MutateAudiencesResponse.deserialize, + ) + return self._stubs["mutate_audiences"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_audiences: self._wrap_method( + self.mutate_audiences, + 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" + + +__all__ = ("AudienceServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/__init__.py b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/__init__.py new file mode 100644 index 000000000..458f3456e --- /dev/null +++ b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import AutomaticallyCreatedAssetRemovalServiceClient +from .async_client import AutomaticallyCreatedAssetRemovalServiceAsyncClient + +__all__ = ( + "AutomaticallyCreatedAssetRemovalServiceClient", + "AutomaticallyCreatedAssetRemovalServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/async_client.py b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/async_client.py new file mode 100644 index 000000000..11366fd67 --- /dev/null +++ b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/async_client.py @@ -0,0 +1,453 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + automatically_created_asset_removal_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AutomaticallyCreatedAssetRemovalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import AutomaticallyCreatedAssetRemovalServiceClient + +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 AutomaticallyCreatedAssetRemovalServiceAsyncClient: + """Service to remove automatically created assets.""" + + _client: AutomaticallyCreatedAssetRemovalServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ( + AutomaticallyCreatedAssetRemovalServiceClient.DEFAULT_ENDPOINT + ) + DEFAULT_MTLS_ENDPOINT = ( + AutomaticallyCreatedAssetRemovalServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + AutomaticallyCreatedAssetRemovalServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ( + AutomaticallyCreatedAssetRemovalServiceClient._DEFAULT_UNIVERSE + ) + + common_billing_account_path = staticmethod( + AutomaticallyCreatedAssetRemovalServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AutomaticallyCreatedAssetRemovalServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + AutomaticallyCreatedAssetRemovalServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + AutomaticallyCreatedAssetRemovalServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AutomaticallyCreatedAssetRemovalServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AutomaticallyCreatedAssetRemovalServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + AutomaticallyCreatedAssetRemovalServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + AutomaticallyCreatedAssetRemovalServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + AutomaticallyCreatedAssetRemovalServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + AutomaticallyCreatedAssetRemovalServiceClient.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: + AutomaticallyCreatedAssetRemovalServiceAsyncClient: The constructed client. + """ + return AutomaticallyCreatedAssetRemovalServiceClient.from_service_account_info.__func__(AutomaticallyCreatedAssetRemovalServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + AutomaticallyCreatedAssetRemovalServiceAsyncClient: The constructed client. + """ + return AutomaticallyCreatedAssetRemovalServiceClient.from_service_account_file.__func__(AutomaticallyCreatedAssetRemovalServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return AutomaticallyCreatedAssetRemovalServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AutomaticallyCreatedAssetRemovalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AutomaticallyCreatedAssetRemovalServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + AutomaticallyCreatedAssetRemovalServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + AutomaticallyCreatedAssetRemovalServiceTransport, + Callable[..., AutomaticallyCreatedAssetRemovalServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the automatically created asset removal 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,AutomaticallyCreatedAssetRemovalServiceTransport,Callable[..., AutomaticallyCreatedAssetRemovalServiceTransport]]]): + 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 AutomaticallyCreatedAssetRemovalServiceTransport 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 = AutomaticallyCreatedAssetRemovalServiceClient( + 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.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService", + "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.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService", + "credentialsType": None, + } + ), + ) + + async def remove_campaign_automatically_created_asset( + self, + request: Optional[ + Union[ + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetOperation + ] + ] = None, + partial_failure: Optional[bool] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetResponse + ): + r"""Removes automatically created assets from a campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ContextError <>`__ `FieldError <>`__ + `InternalError <>`__ `MutateError <>`__ + `PartialFailureError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.RemoveCampaignAutomaticallyCreatedAssetRequest, dict]]): + The request object. Request message for + [AutomaticallyCreatedAssetRemovalService.RemoveCampaignAutomaticallyCreatedAsset][google.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService.RemoveCampaignAutomaticallyCreatedAsset]. + customer_id (:class:`str`): + Required. The ID of the customer + whose assets are being removed. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.RemoveCampaignAutomaticallyCreatedAssetOperation]`): + Required. The list of operations. + This corresponds to the ``operations`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + partial_failure (:class:`bool`): + Required. If true, successful + operations will be carried out and + invalid operations will return errors. + If false, all operations will be carried + out in one transaction if and only if + they are all valid. + + This corresponds to the ``partial_failure`` 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.ads.googleads.v24.services.types.RemoveCampaignAutomaticallyCreatedAssetResponse: + Response message for + [AutomaticallyCreatedAssetRemovalService.RemoveCampaignAutomaticallyCreatedAsset][google.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService.RemoveCampaignAutomaticallyCreatedAsset]. + + """ + # 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 = [customer_id, operations, partial_failure] + 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, + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetRequest, + ): + request = automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if partial_failure is not None: + request.partial_failure = partial_failure + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.remove_campaign_automatically_created_asset + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__( + self, + ) -> "AutomaticallyCreatedAssetRemovalServiceAsyncClient": + 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__ = ("AutomaticallyCreatedAssetRemovalServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/client.py b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/client.py new file mode 100644 index 000000000..34bdb4821 --- /dev/null +++ b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/client.py @@ -0,0 +1,924 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + automatically_created_asset_removal_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AutomaticallyCreatedAssetRemovalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ( + AutomaticallyCreatedAssetRemovalServiceGrpcTransport, +) +from .transports.grpc_asyncio import ( + AutomaticallyCreatedAssetRemovalServiceGrpcAsyncIOTransport, +) + + +class AutomaticallyCreatedAssetRemovalServiceClientMeta(type): + """Metaclass for the AutomaticallyCreatedAssetRemovalService 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[AutomaticallyCreatedAssetRemovalServiceTransport]] + _transport_registry["grpc"] = ( + AutomaticallyCreatedAssetRemovalServiceGrpcTransport + ) + _transport_registry["grpc_asyncio"] = ( + AutomaticallyCreatedAssetRemovalServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AutomaticallyCreatedAssetRemovalServiceTransport]: + """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 AutomaticallyCreatedAssetRemovalServiceClient( + metaclass=AutomaticallyCreatedAssetRemovalServiceClientMeta +): + """Service to remove automatically created assets.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + AutomaticallyCreatedAssetRemovalServiceClient: 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: + AutomaticallyCreatedAssetRemovalServiceClient: 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) -> AutomaticallyCreatedAssetRemovalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AutomaticallyCreatedAssetRemovalServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @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 = ( + AutomaticallyCreatedAssetRemovalServiceClient._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 = ( + AutomaticallyCreatedAssetRemovalServiceClient._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 + ): + """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 = ( + AutomaticallyCreatedAssetRemovalServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + AutomaticallyCreatedAssetRemovalServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = AutomaticallyCreatedAssetRemovalServiceClient._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 = ( + AutomaticallyCreatedAssetRemovalServiceClient._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): + """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, + AutomaticallyCreatedAssetRemovalServiceTransport, + Callable[..., AutomaticallyCreatedAssetRemovalServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the automatically created asset removal 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,AutomaticallyCreatedAssetRemovalServiceTransport,Callable[..., AutomaticallyCreatedAssetRemovalServiceTransport]]]): + 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 AutomaticallyCreatedAssetRemovalServiceTransport 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, + ) = ( + AutomaticallyCreatedAssetRemovalServiceClient._read_environment_variables() + ) + self._client_cert_source = AutomaticallyCreatedAssetRemovalServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = ( + AutomaticallyCreatedAssetRemovalServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, AutomaticallyCreatedAssetRemovalServiceTransport + ) + if transport_provided: + # transport is a AutomaticallyCreatedAssetRemovalServiceTransport 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( + AutomaticallyCreatedAssetRemovalServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AutomaticallyCreatedAssetRemovalServiceClient._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[AutomaticallyCreatedAssetRemovalServiceTransport], + Callable[..., AutomaticallyCreatedAssetRemovalServiceTransport], + ] = ( + AutomaticallyCreatedAssetRemovalServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[ + ..., AutomaticallyCreatedAssetRemovalServiceTransport + ], + 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.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService", + "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.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService", + "credentialsType": None, + } + ), + ) + + def remove_campaign_automatically_created_asset( + self, + request: Optional[ + Union[ + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetOperation + ] + ] = None, + partial_failure: Optional[bool] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetResponse + ): + r"""Removes automatically created assets from a campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ContextError <>`__ `FieldError <>`__ + `InternalError <>`__ `MutateError <>`__ + `PartialFailureError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.RemoveCampaignAutomaticallyCreatedAssetRequest, dict]): + The request object. Request message for + [AutomaticallyCreatedAssetRemovalService.RemoveCampaignAutomaticallyCreatedAsset][google.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService.RemoveCampaignAutomaticallyCreatedAsset]. + customer_id (str): + Required. The ID of the customer + whose assets are being removed. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.RemoveCampaignAutomaticallyCreatedAssetOperation]): + Required. The list of operations. + This corresponds to the ``operations`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + partial_failure (bool): + Required. If true, successful + operations will be carried out and + invalid operations will return errors. + If false, all operations will be carried + out in one transaction if and only if + they are all valid. + + This corresponds to the ``partial_failure`` 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.ads.googleads.v24.services.types.RemoveCampaignAutomaticallyCreatedAssetResponse: + Response message for + [AutomaticallyCreatedAssetRemovalService.RemoveCampaignAutomaticallyCreatedAsset][google.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService.RemoveCampaignAutomaticallyCreatedAsset]. + + """ + # 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 = [customer_id, operations, partial_failure] + 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, + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetRequest, + ): + request = automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + if partial_failure is not None: + request.partial_failure = partial_failure + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.remove_campaign_automatically_created_asset + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "AutomaticallyCreatedAssetRemovalServiceClient": + 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() + + +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__ = ("AutomaticallyCreatedAssetRemovalServiceClient",) diff --git a/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/README.rst b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/README.rst new file mode 100644 index 000000000..8dc7dd5fc --- /dev/null +++ b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`AutomaticallyCreatedAssetRemovalServiceTransport` is the ABC for all transports. +- public child `AutomaticallyCreatedAssetRemovalServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `AutomaticallyCreatedAssetRemovalServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseAutomaticallyCreatedAssetRemovalServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `AutomaticallyCreatedAssetRemovalServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/__init__.py b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/__init__.py new file mode 100644 index 000000000..0bbd6fc51 --- /dev/null +++ b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/__init__.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import AutomaticallyCreatedAssetRemovalServiceTransport +from .grpc import AutomaticallyCreatedAssetRemovalServiceGrpcTransport +from .grpc_asyncio import ( + AutomaticallyCreatedAssetRemovalServiceGrpcAsyncIOTransport, +) + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AutomaticallyCreatedAssetRemovalServiceTransport]] +_transport_registry["grpc"] = ( + AutomaticallyCreatedAssetRemovalServiceGrpcTransport +) +_transport_registry["grpc_asyncio"] = ( + AutomaticallyCreatedAssetRemovalServiceGrpcAsyncIOTransport +) + +__all__ = ( + "AutomaticallyCreatedAssetRemovalServiceTransport", + "AutomaticallyCreatedAssetRemovalServiceGrpcTransport", + "AutomaticallyCreatedAssetRemovalServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/base.py b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/base.py new file mode 100644 index 000000000..68dddcb3b --- /dev/null +++ b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + automatically_created_asset_removal_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 AutomaticallyCreatedAssetRemovalServiceTransport(abc.ABC): + """Abstract transport class for AutomaticallyCreatedAssetRemovalService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.remove_campaign_automatically_created_asset: gapic_v1.method.wrap_method( + self.remove_campaign_automatically_created_asset, + 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 remove_campaign_automatically_created_asset( + self, + ) -> Callable[ + [ + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetRequest + ], + Union[ + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetResponse, + Awaitable[ + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AutomaticallyCreatedAssetRemovalServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/grpc.py b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/grpc.py new file mode 100644 index 000000000..2607b4690 --- /dev/null +++ b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/grpc.py @@ -0,0 +1,398 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + automatically_created_asset_removal_service, +) +from .base import ( + AutomaticallyCreatedAssetRemovalServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AutomaticallyCreatedAssetRemovalServiceGrpcTransport( + AutomaticallyCreatedAssetRemovalServiceTransport +): + """gRPC backend transport for AutomaticallyCreatedAssetRemovalService. + + Service to remove automatically created assets. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 remove_campaign_automatically_created_asset( + self, + ) -> Callable[ + [ + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetRequest + ], + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetResponse, + ]: + r"""Return a callable for the remove campaign automatically + created asset method over gRPC. + + Removes automatically created assets from a campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ContextError <>`__ `FieldError <>`__ + `InternalError <>`__ `MutateError <>`__ + `PartialFailureError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.RemoveCampaignAutomaticallyCreatedAssetRequest], + ~.RemoveCampaignAutomaticallyCreatedAssetResponse]: + 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 "remove_campaign_automatically_created_asset" not in self._stubs: + self._stubs["remove_campaign_automatically_created_asset"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService/RemoveCampaignAutomaticallyCreatedAsset", + request_serializer=automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetRequest.serialize, + response_deserializer=automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetResponse.deserialize, + ) + ) + return self._stubs["remove_campaign_automatically_created_asset"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("AutomaticallyCreatedAssetRemovalServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..185958fde --- /dev/null +++ b/google/ads/googleads/v24/services/services/automatically_created_asset_removal_service/transports/grpc_asyncio.py @@ -0,0 +1,421 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + automatically_created_asset_removal_service, +) +from .base import ( + AutomaticallyCreatedAssetRemovalServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AutomaticallyCreatedAssetRemovalServiceGrpcAsyncIOTransport( + AutomaticallyCreatedAssetRemovalServiceTransport +): + """gRPC AsyncIO backend transport for AutomaticallyCreatedAssetRemovalService. + + Service to remove automatically created assets. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 remove_campaign_automatically_created_asset( + self, + ) -> Callable[ + [ + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetRequest + ], + Awaitable[ + automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetResponse + ], + ]: + r"""Return a callable for the remove campaign automatically + created asset method over gRPC. + + Removes automatically created assets from a campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ContextError <>`__ `FieldError <>`__ + `InternalError <>`__ `MutateError <>`__ + `PartialFailureError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.RemoveCampaignAutomaticallyCreatedAssetRequest], + Awaitable[~.RemoveCampaignAutomaticallyCreatedAssetResponse]]: + 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 "remove_campaign_automatically_created_asset" not in self._stubs: + self._stubs["remove_campaign_automatically_created_asset"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService/RemoveCampaignAutomaticallyCreatedAsset", + request_serializer=automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetRequest.serialize, + response_deserializer=automatically_created_asset_removal_service.RemoveCampaignAutomaticallyCreatedAssetResponse.deserialize, + ) + ) + return self._stubs["remove_campaign_automatically_created_asset"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.remove_campaign_automatically_created_asset: self._wrap_method( + self.remove_campaign_automatically_created_asset, + 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" + + +__all__ = ("AutomaticallyCreatedAssetRemovalServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/batch_job_service/__init__.py b/google/ads/googleads/v24/services/services/batch_job_service/__init__.py new file mode 100644 index 000000000..fa7675532 --- /dev/null +++ b/google/ads/googleads/v24/services/services/batch_job_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import BatchJobServiceClient +from .async_client import BatchJobServiceAsyncClient + +__all__ = ( + "BatchJobServiceClient", + "BatchJobServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/batch_job_service/async_client.py b/google/ads/googleads/v24/services/services/batch_job_service/async_client.py new file mode 100644 index 000000000..0e026570f --- /dev/null +++ b/google/ads/googleads/v24/services/services/batch_job_service/async_client.py @@ -0,0 +1,1192 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.resources.types import batch_job +from google.ads.googleads.v24.services.services.batch_job_service import pagers +from google.ads.googleads.v24.services.types import batch_job_service +from google.ads.googleads.v24.services.types import google_ads_service +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore +from google.protobuf import empty_pb2 # type: ignore +from .transports.base import BatchJobServiceTransport, DEFAULT_CLIENT_INFO +from .client import BatchJobServiceClient + +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 BatchJobServiceAsyncClient: + """Service to manage batch jobs.""" + + _client: BatchJobServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = BatchJobServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = BatchJobServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + BatchJobServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = BatchJobServiceClient._DEFAULT_UNIVERSE + + accessible_bidding_strategy_path = staticmethod( + BatchJobServiceClient.accessible_bidding_strategy_path + ) + parse_accessible_bidding_strategy_path = staticmethod( + BatchJobServiceClient.parse_accessible_bidding_strategy_path + ) + ad_path = staticmethod(BatchJobServiceClient.ad_path) + parse_ad_path = staticmethod(BatchJobServiceClient.parse_ad_path) + ad_group_path = staticmethod(BatchJobServiceClient.ad_group_path) + parse_ad_group_path = staticmethod( + BatchJobServiceClient.parse_ad_group_path + ) + ad_group_ad_path = staticmethod(BatchJobServiceClient.ad_group_ad_path) + parse_ad_group_ad_path = staticmethod( + BatchJobServiceClient.parse_ad_group_ad_path + ) + ad_group_ad_label_path = staticmethod( + BatchJobServiceClient.ad_group_ad_label_path + ) + parse_ad_group_ad_label_path = staticmethod( + BatchJobServiceClient.parse_ad_group_ad_label_path + ) + ad_group_asset_path = staticmethod( + BatchJobServiceClient.ad_group_asset_path + ) + parse_ad_group_asset_path = staticmethod( + BatchJobServiceClient.parse_ad_group_asset_path + ) + ad_group_bid_modifier_path = staticmethod( + BatchJobServiceClient.ad_group_bid_modifier_path + ) + parse_ad_group_bid_modifier_path = staticmethod( + BatchJobServiceClient.parse_ad_group_bid_modifier_path + ) + ad_group_criterion_path = staticmethod( + BatchJobServiceClient.ad_group_criterion_path + ) + parse_ad_group_criterion_path = staticmethod( + BatchJobServiceClient.parse_ad_group_criterion_path + ) + ad_group_criterion_customizer_path = staticmethod( + BatchJobServiceClient.ad_group_criterion_customizer_path + ) + parse_ad_group_criterion_customizer_path = staticmethod( + BatchJobServiceClient.parse_ad_group_criterion_customizer_path + ) + ad_group_criterion_label_path = staticmethod( + BatchJobServiceClient.ad_group_criterion_label_path + ) + parse_ad_group_criterion_label_path = staticmethod( + BatchJobServiceClient.parse_ad_group_criterion_label_path + ) + ad_group_customizer_path = staticmethod( + BatchJobServiceClient.ad_group_customizer_path + ) + parse_ad_group_customizer_path = staticmethod( + BatchJobServiceClient.parse_ad_group_customizer_path + ) + ad_group_label_path = staticmethod( + BatchJobServiceClient.ad_group_label_path + ) + parse_ad_group_label_path = staticmethod( + BatchJobServiceClient.parse_ad_group_label_path + ) + ad_parameter_path = staticmethod(BatchJobServiceClient.ad_parameter_path) + parse_ad_parameter_path = staticmethod( + BatchJobServiceClient.parse_ad_parameter_path + ) + asset_path = staticmethod(BatchJobServiceClient.asset_path) + parse_asset_path = staticmethod(BatchJobServiceClient.parse_asset_path) + asset_group_path = staticmethod(BatchJobServiceClient.asset_group_path) + parse_asset_group_path = staticmethod( + BatchJobServiceClient.parse_asset_group_path + ) + asset_group_asset_path = staticmethod( + BatchJobServiceClient.asset_group_asset_path + ) + parse_asset_group_asset_path = staticmethod( + BatchJobServiceClient.parse_asset_group_asset_path + ) + asset_group_listing_group_filter_path = staticmethod( + BatchJobServiceClient.asset_group_listing_group_filter_path + ) + parse_asset_group_listing_group_filter_path = staticmethod( + BatchJobServiceClient.parse_asset_group_listing_group_filter_path + ) + asset_group_signal_path = staticmethod( + BatchJobServiceClient.asset_group_signal_path + ) + parse_asset_group_signal_path = staticmethod( + BatchJobServiceClient.parse_asset_group_signal_path + ) + asset_set_path = staticmethod(BatchJobServiceClient.asset_set_path) + parse_asset_set_path = staticmethod( + BatchJobServiceClient.parse_asset_set_path + ) + asset_set_asset_path = staticmethod( + BatchJobServiceClient.asset_set_asset_path + ) + parse_asset_set_asset_path = staticmethod( + BatchJobServiceClient.parse_asset_set_asset_path + ) + audience_path = staticmethod(BatchJobServiceClient.audience_path) + parse_audience_path = staticmethod( + BatchJobServiceClient.parse_audience_path + ) + batch_job_path = staticmethod(BatchJobServiceClient.batch_job_path) + parse_batch_job_path = staticmethod( + BatchJobServiceClient.parse_batch_job_path + ) + bidding_data_exclusion_path = staticmethod( + BatchJobServiceClient.bidding_data_exclusion_path + ) + parse_bidding_data_exclusion_path = staticmethod( + BatchJobServiceClient.parse_bidding_data_exclusion_path + ) + bidding_seasonality_adjustment_path = staticmethod( + BatchJobServiceClient.bidding_seasonality_adjustment_path + ) + parse_bidding_seasonality_adjustment_path = staticmethod( + BatchJobServiceClient.parse_bidding_seasonality_adjustment_path + ) + bidding_strategy_path = staticmethod( + BatchJobServiceClient.bidding_strategy_path + ) + parse_bidding_strategy_path = staticmethod( + BatchJobServiceClient.parse_bidding_strategy_path + ) + campaign_path = staticmethod(BatchJobServiceClient.campaign_path) + parse_campaign_path = staticmethod( + BatchJobServiceClient.parse_campaign_path + ) + campaign_asset_path = staticmethod( + BatchJobServiceClient.campaign_asset_path + ) + parse_campaign_asset_path = staticmethod( + BatchJobServiceClient.parse_campaign_asset_path + ) + campaign_asset_set_path = staticmethod( + BatchJobServiceClient.campaign_asset_set_path + ) + parse_campaign_asset_set_path = staticmethod( + BatchJobServiceClient.parse_campaign_asset_set_path + ) + campaign_bid_modifier_path = staticmethod( + BatchJobServiceClient.campaign_bid_modifier_path + ) + parse_campaign_bid_modifier_path = staticmethod( + BatchJobServiceClient.parse_campaign_bid_modifier_path + ) + campaign_budget_path = staticmethod( + BatchJobServiceClient.campaign_budget_path + ) + parse_campaign_budget_path = staticmethod( + BatchJobServiceClient.parse_campaign_budget_path + ) + campaign_conversion_goal_path = staticmethod( + BatchJobServiceClient.campaign_conversion_goal_path + ) + parse_campaign_conversion_goal_path = staticmethod( + BatchJobServiceClient.parse_campaign_conversion_goal_path + ) + campaign_criterion_path = staticmethod( + BatchJobServiceClient.campaign_criterion_path + ) + parse_campaign_criterion_path = staticmethod( + BatchJobServiceClient.parse_campaign_criterion_path + ) + campaign_customizer_path = staticmethod( + BatchJobServiceClient.campaign_customizer_path + ) + parse_campaign_customizer_path = staticmethod( + BatchJobServiceClient.parse_campaign_customizer_path + ) + campaign_draft_path = staticmethod( + BatchJobServiceClient.campaign_draft_path + ) + parse_campaign_draft_path = staticmethod( + BatchJobServiceClient.parse_campaign_draft_path + ) + campaign_group_path = staticmethod( + BatchJobServiceClient.campaign_group_path + ) + parse_campaign_group_path = staticmethod( + BatchJobServiceClient.parse_campaign_group_path + ) + campaign_label_path = staticmethod( + BatchJobServiceClient.campaign_label_path + ) + parse_campaign_label_path = staticmethod( + BatchJobServiceClient.parse_campaign_label_path + ) + campaign_shared_set_path = staticmethod( + BatchJobServiceClient.campaign_shared_set_path + ) + parse_campaign_shared_set_path = staticmethod( + BatchJobServiceClient.parse_campaign_shared_set_path + ) + carrier_constant_path = staticmethod( + BatchJobServiceClient.carrier_constant_path + ) + parse_carrier_constant_path = staticmethod( + BatchJobServiceClient.parse_carrier_constant_path + ) + combined_audience_path = staticmethod( + BatchJobServiceClient.combined_audience_path + ) + parse_combined_audience_path = staticmethod( + BatchJobServiceClient.parse_combined_audience_path + ) + conversion_action_path = staticmethod( + BatchJobServiceClient.conversion_action_path + ) + parse_conversion_action_path = staticmethod( + BatchJobServiceClient.parse_conversion_action_path + ) + conversion_custom_variable_path = staticmethod( + BatchJobServiceClient.conversion_custom_variable_path + ) + parse_conversion_custom_variable_path = staticmethod( + BatchJobServiceClient.parse_conversion_custom_variable_path + ) + conversion_goal_campaign_config_path = staticmethod( + BatchJobServiceClient.conversion_goal_campaign_config_path + ) + parse_conversion_goal_campaign_config_path = staticmethod( + BatchJobServiceClient.parse_conversion_goal_campaign_config_path + ) + conversion_value_rule_path = staticmethod( + BatchJobServiceClient.conversion_value_rule_path + ) + parse_conversion_value_rule_path = staticmethod( + BatchJobServiceClient.parse_conversion_value_rule_path + ) + conversion_value_rule_set_path = staticmethod( + BatchJobServiceClient.conversion_value_rule_set_path + ) + parse_conversion_value_rule_set_path = staticmethod( + BatchJobServiceClient.parse_conversion_value_rule_set_path + ) + custom_conversion_goal_path = staticmethod( + BatchJobServiceClient.custom_conversion_goal_path + ) + parse_custom_conversion_goal_path = staticmethod( + BatchJobServiceClient.parse_custom_conversion_goal_path + ) + customer_path = staticmethod(BatchJobServiceClient.customer_path) + parse_customer_path = staticmethod( + BatchJobServiceClient.parse_customer_path + ) + customer_asset_path = staticmethod( + BatchJobServiceClient.customer_asset_path + ) + parse_customer_asset_path = staticmethod( + BatchJobServiceClient.parse_customer_asset_path + ) + customer_conversion_goal_path = staticmethod( + BatchJobServiceClient.customer_conversion_goal_path + ) + parse_customer_conversion_goal_path = staticmethod( + BatchJobServiceClient.parse_customer_conversion_goal_path + ) + customer_customizer_path = staticmethod( + BatchJobServiceClient.customer_customizer_path + ) + parse_customer_customizer_path = staticmethod( + BatchJobServiceClient.parse_customer_customizer_path + ) + customer_label_path = staticmethod( + BatchJobServiceClient.customer_label_path + ) + parse_customer_label_path = staticmethod( + BatchJobServiceClient.parse_customer_label_path + ) + customer_negative_criterion_path = staticmethod( + BatchJobServiceClient.customer_negative_criterion_path + ) + parse_customer_negative_criterion_path = staticmethod( + BatchJobServiceClient.parse_customer_negative_criterion_path + ) + customizer_attribute_path = staticmethod( + BatchJobServiceClient.customizer_attribute_path + ) + parse_customizer_attribute_path = staticmethod( + BatchJobServiceClient.parse_customizer_attribute_path + ) + detailed_demographic_path = staticmethod( + BatchJobServiceClient.detailed_demographic_path + ) + parse_detailed_demographic_path = staticmethod( + BatchJobServiceClient.parse_detailed_demographic_path + ) + experiment_path = staticmethod(BatchJobServiceClient.experiment_path) + parse_experiment_path = staticmethod( + BatchJobServiceClient.parse_experiment_path + ) + experiment_arm_path = staticmethod( + BatchJobServiceClient.experiment_arm_path + ) + parse_experiment_arm_path = staticmethod( + BatchJobServiceClient.parse_experiment_arm_path + ) + geo_target_constant_path = staticmethod( + BatchJobServiceClient.geo_target_constant_path + ) + parse_geo_target_constant_path = staticmethod( + BatchJobServiceClient.parse_geo_target_constant_path + ) + keyword_plan_path = staticmethod(BatchJobServiceClient.keyword_plan_path) + parse_keyword_plan_path = staticmethod( + BatchJobServiceClient.parse_keyword_plan_path + ) + keyword_plan_ad_group_path = staticmethod( + BatchJobServiceClient.keyword_plan_ad_group_path + ) + parse_keyword_plan_ad_group_path = staticmethod( + BatchJobServiceClient.parse_keyword_plan_ad_group_path + ) + keyword_plan_ad_group_keyword_path = staticmethod( + BatchJobServiceClient.keyword_plan_ad_group_keyword_path + ) + parse_keyword_plan_ad_group_keyword_path = staticmethod( + BatchJobServiceClient.parse_keyword_plan_ad_group_keyword_path + ) + keyword_plan_campaign_path = staticmethod( + BatchJobServiceClient.keyword_plan_campaign_path + ) + parse_keyword_plan_campaign_path = staticmethod( + BatchJobServiceClient.parse_keyword_plan_campaign_path + ) + keyword_plan_campaign_keyword_path = staticmethod( + BatchJobServiceClient.keyword_plan_campaign_keyword_path + ) + parse_keyword_plan_campaign_keyword_path = staticmethod( + BatchJobServiceClient.parse_keyword_plan_campaign_keyword_path + ) + keyword_theme_constant_path = staticmethod( + BatchJobServiceClient.keyword_theme_constant_path + ) + parse_keyword_theme_constant_path = staticmethod( + BatchJobServiceClient.parse_keyword_theme_constant_path + ) + label_path = staticmethod(BatchJobServiceClient.label_path) + parse_label_path = staticmethod(BatchJobServiceClient.parse_label_path) + language_constant_path = staticmethod( + BatchJobServiceClient.language_constant_path + ) + parse_language_constant_path = staticmethod( + BatchJobServiceClient.parse_language_constant_path + ) + life_event_path = staticmethod(BatchJobServiceClient.life_event_path) + parse_life_event_path = staticmethod( + BatchJobServiceClient.parse_life_event_path + ) + mobile_app_category_constant_path = staticmethod( + BatchJobServiceClient.mobile_app_category_constant_path + ) + parse_mobile_app_category_constant_path = staticmethod( + BatchJobServiceClient.parse_mobile_app_category_constant_path + ) + mobile_device_constant_path = staticmethod( + BatchJobServiceClient.mobile_device_constant_path + ) + parse_mobile_device_constant_path = staticmethod( + BatchJobServiceClient.parse_mobile_device_constant_path + ) + operating_system_version_constant_path = staticmethod( + BatchJobServiceClient.operating_system_version_constant_path + ) + parse_operating_system_version_constant_path = staticmethod( + BatchJobServiceClient.parse_operating_system_version_constant_path + ) + recommendation_subscription_path = staticmethod( + BatchJobServiceClient.recommendation_subscription_path + ) + parse_recommendation_subscription_path = staticmethod( + BatchJobServiceClient.parse_recommendation_subscription_path + ) + remarketing_action_path = staticmethod( + BatchJobServiceClient.remarketing_action_path + ) + parse_remarketing_action_path = staticmethod( + BatchJobServiceClient.parse_remarketing_action_path + ) + shared_criterion_path = staticmethod( + BatchJobServiceClient.shared_criterion_path + ) + parse_shared_criterion_path = staticmethod( + BatchJobServiceClient.parse_shared_criterion_path + ) + shared_set_path = staticmethod(BatchJobServiceClient.shared_set_path) + parse_shared_set_path = staticmethod( + BatchJobServiceClient.parse_shared_set_path + ) + smart_campaign_setting_path = staticmethod( + BatchJobServiceClient.smart_campaign_setting_path + ) + parse_smart_campaign_setting_path = staticmethod( + BatchJobServiceClient.parse_smart_campaign_setting_path + ) + topic_constant_path = staticmethod( + BatchJobServiceClient.topic_constant_path + ) + parse_topic_constant_path = staticmethod( + BatchJobServiceClient.parse_topic_constant_path + ) + user_interest_path = staticmethod(BatchJobServiceClient.user_interest_path) + parse_user_interest_path = staticmethod( + BatchJobServiceClient.parse_user_interest_path + ) + user_list_path = staticmethod(BatchJobServiceClient.user_list_path) + parse_user_list_path = staticmethod( + BatchJobServiceClient.parse_user_list_path + ) + common_billing_account_path = staticmethod( + BatchJobServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + BatchJobServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(BatchJobServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + BatchJobServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + BatchJobServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + BatchJobServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + BatchJobServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + BatchJobServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + BatchJobServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + BatchJobServiceClient.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: + BatchJobServiceAsyncClient: The constructed client. + """ + return BatchJobServiceClient.from_service_account_info.__func__(BatchJobServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + BatchJobServiceAsyncClient: The constructed client. + """ + return BatchJobServiceClient.from_service_account_file.__func__(BatchJobServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return BatchJobServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> BatchJobServiceTransport: + """Returns the transport used by the client instance. + + Returns: + BatchJobServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = BatchJobServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + BatchJobServiceTransport, + Callable[..., BatchJobServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the batch job 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,BatchJobServiceTransport,Callable[..., BatchJobServiceTransport]]]): + 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 BatchJobServiceTransport 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 = BatchJobServiceClient( + 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.ads.googleads.v24.services.BatchJobServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.BatchJobService", + "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.ads.googleads.v24.services.BatchJobService", + "credentialsType": None, + } + ), + ) + + async def mutate_batch_job( + self, + request: Optional[ + Union[batch_job_service.MutateBatchJobRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[batch_job_service.BatchJobOperation] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> batch_job_service.MutateBatchJobResponse: + r"""Mutates a batch job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateBatchJobRequest, dict]]): + The request object. Request message for + [BatchJobService.MutateBatchJob][google.ads.googleads.v24.services.BatchJobService.MutateBatchJob]. + customer_id (:class:`str`): + Required. The ID of the customer for + which to create a batch job. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (:class:`google.ads.googleads.v24.services.types.BatchJobOperation`): + Required. The operation to perform on + an individual batch job. + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateBatchJobResponse: + Response message for + [BatchJobService.MutateBatchJob][google.ads.googleads.v24.services.BatchJobService.MutateBatchJob]. + + """ + # 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 = [customer_id, operation] + 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, batch_job_service.MutateBatchJobRequest): + request = batch_job_service.MutateBatchJobRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_batch_job + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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_batch_job_results( + self, + request: Optional[ + Union[batch_job_service.ListBatchJobResultsRequest, dict] + ] = None, + *, + resource_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]]] = (), + ) -> pagers.ListBatchJobResultsAsyncPager: + r"""Returns the results of the batch job. The job must be done. + Supports standard list paging. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BatchJobError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListBatchJobResultsRequest, dict]]): + The request object. Request message for + [BatchJobService.ListBatchJobResults][google.ads.googleads.v24.services.BatchJobService.ListBatchJobResults]. + resource_name (:class:`str`): + Required. The resource name of the + batch job whose results are being + listed. + + This corresponds to the ``resource_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.ads.googleads.v24.services.services.batch_job_service.pagers.ListBatchJobResultsAsyncPager: + Response message for + [BatchJobService.ListBatchJobResults][google.ads.googleads.v24.services.BatchJobService.ListBatchJobResults]. + + 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 = [resource_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, batch_job_service.ListBatchJobResultsRequest + ): + request = batch_job_service.ListBatchJobResultsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_batch_job_results + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_name),) + ), + ) + + # 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.ListBatchJobResultsAsyncPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def run_batch_job( + self, + request: Optional[ + Union[batch_job_service.RunBatchJobRequest, dict] + ] = None, + *, + resource_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]]] = (), + ) -> operation_async.AsyncOperation: + r"""Runs the batch job. + + The Operation.metadata field type is BatchJobMetadata. When + finished, the long running operation will not contain errors or + a response. Instead, use ListBatchJobResults to get the results + of the job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BatchJobError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.RunBatchJobRequest, dict]]): + The request object. Request message for + [BatchJobService.RunBatchJob][google.ads.googleads.v24.services.BatchJobService.RunBatchJob]. + resource_name (:class:`str`): + Required. The resource name of the + BatchJob to run. + + This corresponds to the ``resource_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.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 = [resource_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, batch_job_service.RunBatchJobRequest): + request = batch_job_service.RunBatchJobRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.run_batch_job + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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=batch_job.BatchJob.BatchJobMetadata, + ) + + # Done; return the response. + return response + + async def add_batch_job_operations( + self, + request: Optional[ + Union[batch_job_service.AddBatchJobOperationsRequest, dict] + ] = None, + *, + resource_name: Optional[str] = None, + sequence_token: Optional[str] = None, + mutate_operations: Optional[ + MutableSequence[google_ads_service.MutateOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> batch_job_service.AddBatchJobOperationsResponse: + r"""Add operations to the batch job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BatchJobError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.AddBatchJobOperationsRequest, dict]]): + The request object. Request message for + [BatchJobService.AddBatchJobOperations][google.ads.googleads.v24.services.BatchJobService.AddBatchJobOperations]. + resource_name (:class:`str`): + Required. The resource name of the + batch job. + + This corresponds to the ``resource_name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + sequence_token (:class:`str`): + A token used to enforce sequencing. + + The first AddBatchJobOperations request for a batch job + should not set sequence_token. Subsequent requests must + set sequence_token to the value of next_sequence_token + received in the previous AddBatchJobOperations response. + + This corresponds to the ``sequence_token`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + mutate_operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.MutateOperation]`): + Required. The list of mutates being + added. + Operations can use negative integers as + temp ids to signify dependencies between + entities created in this batch job. For + example, a customer with id = 1234 can + create a campaign and an ad group in + that same campaign by creating a + campaign in the first operation with the + resource name explicitly set to + "customers/1234/campaigns/-1", and + creating an ad group in the second + operation with the campaign field also + set to "customers/1234/campaigns/-1". + + This corresponds to the ``mutate_operations`` 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.ads.googleads.v24.services.types.AddBatchJobOperationsResponse: + Response message for + [BatchJobService.AddBatchJobOperations][google.ads.googleads.v24.services.BatchJobService.AddBatchJobOperations]. + + """ + # 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 = [resource_name, sequence_token, mutate_operations] + 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, batch_job_service.AddBatchJobOperationsRequest + ): + request = batch_job_service.AddBatchJobOperationsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + if sequence_token is not None: + request.sequence_token = sequence_token + if mutate_operations: + request.mutate_operations.extend(mutate_operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.add_batch_job_operations + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_name),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "BatchJobServiceAsyncClient": + 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__ = ("BatchJobServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/batch_job_service/client.py b/google/ads/googleads/v24/services/services/batch_job_service/client.py new file mode 100644 index 000000000..113c47f3f --- /dev/null +++ b/google/ads/googleads/v24/services/services/batch_job_service/client.py @@ -0,0 +1,2785 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.resources.types import batch_job +from google.ads.googleads.v24.services.services.batch_job_service import pagers +from google.ads.googleads.v24.services.types import batch_job_service +from google.ads.googleads.v24.services.types import google_ads_service +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore +from google.protobuf import empty_pb2 # type: ignore +from .transports.base import BatchJobServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import BatchJobServiceGrpcTransport +from .transports.grpc_asyncio import BatchJobServiceGrpcAsyncIOTransport + + +class BatchJobServiceClientMeta(type): + """Metaclass for the BatchJobService 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[BatchJobServiceTransport]] + _transport_registry["grpc"] = BatchJobServiceGrpcTransport + _transport_registry["grpc_asyncio"] = BatchJobServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[BatchJobServiceTransport]: + """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 BatchJobServiceClient(metaclass=BatchJobServiceClientMeta): + """Service to manage batch jobs.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + BatchJobServiceClient: 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: + BatchJobServiceClient: 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) -> BatchJobServiceTransport: + """Returns the transport used by the client instance. + + Returns: + BatchJobServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def accessible_bidding_strategy_path( + customer_id: str, + bidding_strategy_id: str, + ) -> str: + """Returns a fully-qualified accessible_bidding_strategy string.""" + return "customers/{customer_id}/accessibleBiddingStrategies/{bidding_strategy_id}".format( + customer_id=customer_id, + bidding_strategy_id=bidding_strategy_id, + ) + + @staticmethod + def parse_accessible_bidding_strategy_path(path: str) -> Dict[str, str]: + """Parses a accessible_bidding_strategy path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/accessibleBiddingStrategies/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_path( + customer_id: str, + ad_id: str, + ) -> str: + """Returns a fully-qualified ad string.""" + return "customers/{customer_id}/ads/{ad_id}".format( + customer_id=customer_id, + ad_id=ad_id, + ) + + @staticmethod + def parse_ad_path(path: str) -> Dict[str, str]: + """Parses a ad path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/ads/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_path( + customer_id: str, + ad_group_id: str, + ) -> str: + """Returns a fully-qualified ad_group string.""" + return "customers/{customer_id}/adGroups/{ad_group_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ) + + @staticmethod + def parse_ad_group_path(path: str) -> Dict[str, str]: + """Parses a ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_ad_path( + customer_id: str, + ad_group_id: str, + ad_id: str, + ) -> str: + """Returns a fully-qualified ad_group_ad string.""" + return ( + "customers/{customer_id}/adGroupAds/{ad_group_id}~{ad_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ad_id=ad_id, + ) + ) + + @staticmethod + def parse_ad_group_ad_path(path: str) -> Dict[str, str]: + """Parses a ad_group_ad path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAds/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_ad_label_path( + customer_id: str, + ad_group_id: str, + ad_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified ad_group_ad_label string.""" + return "customers/{customer_id}/adGroupAdLabels/{ad_group_id}~{ad_id}~{label_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ad_id=ad_id, + label_id=label_id, + ) + + @staticmethod + def parse_ad_group_ad_label_path(path: str) -> Dict[str, str]: + """Parses a ad_group_ad_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAdLabels/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_asset_path( + customer_id: str, + ad_group_id: str, + asset_id: str, + field_type: str, + ) -> str: + """Returns a fully-qualified ad_group_asset string.""" + return "customers/{customer_id}/adGroupAssets/{ad_group_id}~{asset_id}~{field_type}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + asset_id=asset_id, + field_type=field_type, + ) + + @staticmethod + def parse_ad_group_asset_path(path: str) -> Dict[str, str]: + """Parses a ad_group_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAssets/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_bid_modifier_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified ad_group_bid_modifier string.""" + return "customers/{customer_id}/adGroupBidModifiers/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_ad_group_bid_modifier_path(path: str) -> Dict[str, str]: + """Parses a ad_group_bid_modifier path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupBidModifiers/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_criterion_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified ad_group_criterion string.""" + return "customers/{customer_id}/adGroupCriteria/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_ad_group_criterion_path(path: str) -> Dict[str, str]: + """Parses a ad_group_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCriteria/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_criterion_customizer_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified ad_group_criterion_customizer string.""" + return "customers/{customer_id}/adGroupCriterionCustomizers/{ad_group_id}~{criterion_id}~{customizer_attribute_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_ad_group_criterion_customizer_path(path: str) -> Dict[str, str]: + """Parses a ad_group_criterion_customizer path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCriterionCustomizers/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_criterion_label_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified ad_group_criterion_label string.""" + return "customers/{customer_id}/adGroupCriterionLabels/{ad_group_id}~{criterion_id}~{label_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + label_id=label_id, + ) + + @staticmethod + def parse_ad_group_criterion_label_path(path: str) -> Dict[str, str]: + """Parses a ad_group_criterion_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCriterionLabels/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_customizer_path( + customer_id: str, + ad_group_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified ad_group_customizer string.""" + return "customers/{customer_id}/adGroupCustomizers/{ad_group_id}~{customizer_attribute_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_ad_group_customizer_path(path: str) -> Dict[str, str]: + """Parses a ad_group_customizer path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCustomizers/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_label_path( + customer_id: str, + ad_group_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified ad_group_label string.""" + return "customers/{customer_id}/adGroupLabels/{ad_group_id}~{label_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + label_id=label_id, + ) + + @staticmethod + def parse_ad_group_label_path(path: str) -> Dict[str, str]: + """Parses a ad_group_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupLabels/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_parameter_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + parameter_index: str, + ) -> str: + """Returns a fully-qualified ad_parameter string.""" + return "customers/{customer_id}/adParameters/{ad_group_id}~{criterion_id}~{parameter_index}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + parameter_index=parameter_index, + ) + + @staticmethod + def parse_ad_parameter_path(path: str) -> Dict[str, str]: + """Parses a ad_parameter path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adParameters/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_path( + customer_id: str, + asset_id: str, + ) -> str: + """Returns a fully-qualified asset string.""" + return "customers/{customer_id}/assets/{asset_id}".format( + customer_id=customer_id, + asset_id=asset_id, + ) + + @staticmethod + def parse_asset_path(path: str) -> Dict[str, str]: + """Parses a asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assets/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_path( + customer_id: str, + asset_group_id: str, + ) -> str: + """Returns a fully-qualified asset_group string.""" + return "customers/{customer_id}/assetGroups/{asset_group_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + ) + + @staticmethod + def parse_asset_group_path(path: str) -> Dict[str, str]: + """Parses a asset_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_asset_path( + customer_id: str, + asset_group_id: str, + asset_id: str, + field_type: str, + ) -> str: + """Returns a fully-qualified asset_group_asset string.""" + return "customers/{customer_id}/assetGroupAssets/{asset_group_id}~{asset_id}~{field_type}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + asset_id=asset_id, + field_type=field_type, + ) + + @staticmethod + def parse_asset_group_asset_path(path: str) -> Dict[str, str]: + """Parses a asset_group_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroupAssets/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_listing_group_filter_path( + customer_id: str, + asset_group_id: str, + listing_group_filter_id: str, + ) -> str: + """Returns a fully-qualified asset_group_listing_group_filter string.""" + return "customers/{customer_id}/assetGroupListingGroupFilters/{asset_group_id}~{listing_group_filter_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + listing_group_filter_id=listing_group_filter_id, + ) + + @staticmethod + def parse_asset_group_listing_group_filter_path( + path: str, + ) -> Dict[str, str]: + """Parses a asset_group_listing_group_filter path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroupListingGroupFilters/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_signal_path( + customer_id: str, + asset_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified asset_group_signal string.""" + return "customers/{customer_id}/assetGroupSignals/{asset_group_id}~{criterion_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_asset_group_signal_path(path: str) -> Dict[str, str]: + """Parses a asset_group_signal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroupSignals/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_set_path( + customer_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified asset_set string.""" + return "customers/{customer_id}/assetSets/{asset_set_id}".format( + customer_id=customer_id, + asset_set_id=asset_set_id, + ) + + @staticmethod + def parse_asset_set_path(path: str) -> Dict[str, str]: + """Parses a asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetSets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_set_asset_path( + customer_id: str, + asset_set_id: str, + asset_id: str, + ) -> str: + """Returns a fully-qualified asset_set_asset string.""" + return "customers/{customer_id}/assetSetAssets/{asset_set_id}~{asset_id}".format( + customer_id=customer_id, + asset_set_id=asset_set_id, + asset_id=asset_id, + ) + + @staticmethod + def parse_asset_set_asset_path(path: str) -> Dict[str, str]: + """Parses a asset_set_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetSetAssets/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def audience_path( + customer_id: str, + audience_id: str, + ) -> str: + """Returns a fully-qualified audience string.""" + return "customers/{customer_id}/audiences/{audience_id}".format( + customer_id=customer_id, + audience_id=audience_id, + ) + + @staticmethod + def parse_audience_path(path: str) -> Dict[str, str]: + """Parses a audience path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/audiences/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def batch_job_path( + customer_id: str, + batch_job_id: str, + ) -> str: + """Returns a fully-qualified batch_job string.""" + return "customers/{customer_id}/batchJobs/{batch_job_id}".format( + customer_id=customer_id, + batch_job_id=batch_job_id, + ) + + @staticmethod + def parse_batch_job_path(path: str) -> Dict[str, str]: + """Parses a batch_job path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/batchJobs/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def bidding_data_exclusion_path( + customer_id: str, + seasonality_event_id: str, + ) -> str: + """Returns a fully-qualified bidding_data_exclusion string.""" + return "customers/{customer_id}/biddingDataExclusions/{seasonality_event_id}".format( + customer_id=customer_id, + seasonality_event_id=seasonality_event_id, + ) + + @staticmethod + def parse_bidding_data_exclusion_path(path: str) -> Dict[str, str]: + """Parses a bidding_data_exclusion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/biddingDataExclusions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def bidding_seasonality_adjustment_path( + customer_id: str, + seasonality_event_id: str, + ) -> str: + """Returns a fully-qualified bidding_seasonality_adjustment string.""" + return "customers/{customer_id}/biddingSeasonalityAdjustments/{seasonality_event_id}".format( + customer_id=customer_id, + seasonality_event_id=seasonality_event_id, + ) + + @staticmethod + def parse_bidding_seasonality_adjustment_path(path: str) -> Dict[str, str]: + """Parses a bidding_seasonality_adjustment path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/biddingSeasonalityAdjustments/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def bidding_strategy_path( + customer_id: str, + bidding_strategy_id: str, + ) -> str: + """Returns a fully-qualified bidding_strategy string.""" + return "customers/{customer_id}/biddingStrategies/{bidding_strategy_id}".format( + customer_id=customer_id, + bidding_strategy_id=bidding_strategy_id, + ) + + @staticmethod + def parse_bidding_strategy_path(path: str) -> Dict[str, str]: + """Parses a bidding_strategy path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/biddingStrategies/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_asset_path( + customer_id: str, + campaign_id: str, + asset_id: str, + field_type: str, + ) -> str: + """Returns a fully-qualified campaign_asset string.""" + return "customers/{customer_id}/campaignAssets/{campaign_id}~{asset_id}~{field_type}".format( + customer_id=customer_id, + campaign_id=campaign_id, + asset_id=asset_id, + field_type=field_type, + ) + + @staticmethod + def parse_campaign_asset_path(path: str) -> Dict[str, str]: + """Parses a campaign_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignAssets/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_asset_set_path( + customer_id: str, + campaign_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified campaign_asset_set string.""" + return "customers/{customer_id}/campaignAssetSets/{campaign_id}~{asset_set_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + asset_set_id=asset_set_id, + ) + + @staticmethod + def parse_campaign_asset_set_path(path: str) -> Dict[str, str]: + """Parses a campaign_asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignAssetSets/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_bid_modifier_path( + customer_id: str, + campaign_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified campaign_bid_modifier string.""" + return "customers/{customer_id}/campaignBidModifiers/{campaign_id}~{criterion_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_campaign_bid_modifier_path(path: str) -> Dict[str, str]: + """Parses a campaign_bid_modifier path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignBidModifiers/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_budget_path( + customer_id: str, + campaign_budget_id: str, + ) -> str: + """Returns a fully-qualified campaign_budget string.""" + return "customers/{customer_id}/campaignBudgets/{campaign_budget_id}".format( + customer_id=customer_id, + campaign_budget_id=campaign_budget_id, + ) + + @staticmethod + def parse_campaign_budget_path(path: str) -> Dict[str, str]: + """Parses a campaign_budget path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignBudgets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_conversion_goal_path( + customer_id: str, + campaign_id: str, + category: str, + source: str, + ) -> str: + """Returns a fully-qualified campaign_conversion_goal string.""" + return "customers/{customer_id}/campaignConversionGoals/{campaign_id}~{category}~{source}".format( + customer_id=customer_id, + campaign_id=campaign_id, + category=category, + source=source, + ) + + @staticmethod + def parse_campaign_conversion_goal_path(path: str) -> Dict[str, str]: + """Parses a campaign_conversion_goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignConversionGoals/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_criterion_path( + customer_id: str, + campaign_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified campaign_criterion string.""" + return "customers/{customer_id}/campaignCriteria/{campaign_id}~{criterion_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_campaign_criterion_path(path: str) -> Dict[str, str]: + """Parses a campaign_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignCriteria/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_customizer_path( + customer_id: str, + campaign_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified campaign_customizer string.""" + return "customers/{customer_id}/campaignCustomizers/{campaign_id}~{customizer_attribute_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_campaign_customizer_path(path: str) -> Dict[str, str]: + """Parses a campaign_customizer path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignCustomizers/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_draft_path( + customer_id: str, + base_campaign_id: str, + draft_id: str, + ) -> str: + """Returns a fully-qualified campaign_draft string.""" + return "customers/{customer_id}/campaignDrafts/{base_campaign_id}~{draft_id}".format( + customer_id=customer_id, + base_campaign_id=base_campaign_id, + draft_id=draft_id, + ) + + @staticmethod + def parse_campaign_draft_path(path: str) -> Dict[str, str]: + """Parses a campaign_draft path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignDrafts/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_group_path( + customer_id: str, + campaign_group_id: str, + ) -> str: + """Returns a fully-qualified campaign_group string.""" + return ( + "customers/{customer_id}/campaignGroups/{campaign_group_id}".format( + customer_id=customer_id, + campaign_group_id=campaign_group_id, + ) + ) + + @staticmethod + def parse_campaign_group_path(path: str) -> Dict[str, str]: + """Parses a campaign_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_label_path( + customer_id: str, + campaign_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified campaign_label string.""" + return "customers/{customer_id}/campaignLabels/{campaign_id}~{label_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + label_id=label_id, + ) + + @staticmethod + def parse_campaign_label_path(path: str) -> Dict[str, str]: + """Parses a campaign_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignLabels/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_shared_set_path( + customer_id: str, + campaign_id: str, + shared_set_id: str, + ) -> str: + """Returns a fully-qualified campaign_shared_set string.""" + return "customers/{customer_id}/campaignSharedSets/{campaign_id}~{shared_set_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + shared_set_id=shared_set_id, + ) + + @staticmethod + def parse_campaign_shared_set_path(path: str) -> Dict[str, str]: + """Parses a campaign_shared_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignSharedSets/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def carrier_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified carrier_constant string.""" + return "carrierConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_carrier_constant_path(path: str) -> Dict[str, str]: + """Parses a carrier_constant path into its component segments.""" + m = re.match(r"^carrierConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def combined_audience_path( + customer_id: str, + combined_audience_id: str, + ) -> str: + """Returns a fully-qualified combined_audience string.""" + return "customers/{customer_id}/combinedAudiences/{combined_audience_id}".format( + customer_id=customer_id, + combined_audience_id=combined_audience_id, + ) + + @staticmethod + def parse_combined_audience_path(path: str) -> Dict[str, str]: + """Parses a combined_audience path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/combinedAudiences/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_action_path( + customer_id: str, + conversion_action_id: str, + ) -> str: + """Returns a fully-qualified conversion_action string.""" + return "customers/{customer_id}/conversionActions/{conversion_action_id}".format( + customer_id=customer_id, + conversion_action_id=conversion_action_id, + ) + + @staticmethod + def parse_conversion_action_path(path: str) -> Dict[str, str]: + """Parses a conversion_action path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionActions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_custom_variable_path( + customer_id: str, + conversion_custom_variable_id: str, + ) -> str: + """Returns a fully-qualified conversion_custom_variable string.""" + return "customers/{customer_id}/conversionCustomVariables/{conversion_custom_variable_id}".format( + customer_id=customer_id, + conversion_custom_variable_id=conversion_custom_variable_id, + ) + + @staticmethod + def parse_conversion_custom_variable_path(path: str) -> Dict[str, str]: + """Parses a conversion_custom_variable path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionCustomVariables/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_goal_campaign_config_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified conversion_goal_campaign_config string.""" + return "customers/{customer_id}/conversionGoalCampaignConfigs/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_conversion_goal_campaign_config_path(path: str) -> Dict[str, str]: + """Parses a conversion_goal_campaign_config path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionGoalCampaignConfigs/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_value_rule_path( + customer_id: str, + conversion_value_rule_id: str, + ) -> str: + """Returns a fully-qualified conversion_value_rule string.""" + return "customers/{customer_id}/conversionValueRules/{conversion_value_rule_id}".format( + customer_id=customer_id, + conversion_value_rule_id=conversion_value_rule_id, + ) + + @staticmethod + def parse_conversion_value_rule_path(path: str) -> Dict[str, str]: + """Parses a conversion_value_rule path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionValueRules/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_value_rule_set_path( + customer_id: str, + conversion_value_rule_set_id: str, + ) -> str: + """Returns a fully-qualified conversion_value_rule_set string.""" + return "customers/{customer_id}/conversionValueRuleSets/{conversion_value_rule_set_id}".format( + customer_id=customer_id, + conversion_value_rule_set_id=conversion_value_rule_set_id, + ) + + @staticmethod + def parse_conversion_value_rule_set_path(path: str) -> Dict[str, str]: + """Parses a conversion_value_rule_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionValueRuleSets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def custom_conversion_goal_path( + customer_id: str, + goal_id: str, + ) -> str: + """Returns a fully-qualified custom_conversion_goal string.""" + return "customers/{customer_id}/customConversionGoals/{goal_id}".format( + customer_id=customer_id, + goal_id=goal_id, + ) + + @staticmethod + def parse_custom_conversion_goal_path(path: str) -> Dict[str, str]: + """Parses a custom_conversion_goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customConversionGoals/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def customer_asset_path( + customer_id: str, + asset_id: str, + field_type: str, + ) -> str: + """Returns a fully-qualified customer_asset string.""" + return "customers/{customer_id}/customerAssets/{asset_id}~{field_type}".format( + customer_id=customer_id, + asset_id=asset_id, + field_type=field_type, + ) + + @staticmethod + def parse_customer_asset_path(path: str) -> Dict[str, str]: + """Parses a customer_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerAssets/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_conversion_goal_path( + customer_id: str, + category: str, + source: str, + ) -> str: + """Returns a fully-qualified customer_conversion_goal string.""" + return "customers/{customer_id}/customerConversionGoals/{category}~{source}".format( + customer_id=customer_id, + category=category, + source=source, + ) + + @staticmethod + def parse_customer_conversion_goal_path(path: str) -> Dict[str, str]: + """Parses a customer_conversion_goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerConversionGoals/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_customizer_path( + customer_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified customer_customizer string.""" + return "customers/{customer_id}/customerCustomizers/{customizer_attribute_id}".format( + customer_id=customer_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_customer_customizer_path(path: str) -> Dict[str, str]: + """Parses a customer_customizer path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerCustomizers/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_label_path( + customer_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified customer_label string.""" + return "customers/{customer_id}/customerLabels/{label_id}".format( + customer_id=customer_id, + label_id=label_id, + ) + + @staticmethod + def parse_customer_label_path(path: str) -> Dict[str, str]: + """Parses a customer_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerLabels/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_negative_criterion_path( + customer_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified customer_negative_criterion string.""" + return "customers/{customer_id}/customerNegativeCriteria/{criterion_id}".format( + customer_id=customer_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_customer_negative_criterion_path(path: str) -> Dict[str, str]: + """Parses a customer_negative_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerNegativeCriteria/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customizer_attribute_path( + customer_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified customizer_attribute string.""" + return "customers/{customer_id}/customizerAttributes/{customizer_attribute_id}".format( + customer_id=customer_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_customizer_attribute_path(path: str) -> Dict[str, str]: + """Parses a customizer_attribute path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customizerAttributes/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def detailed_demographic_path( + customer_id: str, + detailed_demographic_id: str, + ) -> str: + """Returns a fully-qualified detailed_demographic string.""" + return "customers/{customer_id}/detailedDemographics/{detailed_demographic_id}".format( + customer_id=customer_id, + detailed_demographic_id=detailed_demographic_id, + ) + + @staticmethod + def parse_detailed_demographic_path(path: str) -> Dict[str, str]: + """Parses a detailed_demographic path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/detailedDemographics/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def experiment_path( + customer_id: str, + trial_id: str, + ) -> str: + """Returns a fully-qualified experiment string.""" + return "customers/{customer_id}/experiments/{trial_id}".format( + customer_id=customer_id, + trial_id=trial_id, + ) + + @staticmethod + def parse_experiment_path(path: str) -> Dict[str, str]: + """Parses a experiment path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/experiments/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def experiment_arm_path( + customer_id: str, + trial_id: str, + trial_arm_id: str, + ) -> str: + """Returns a fully-qualified experiment_arm string.""" + return "customers/{customer_id}/experimentArms/{trial_id}~{trial_arm_id}".format( + customer_id=customer_id, + trial_id=trial_id, + trial_arm_id=trial_arm_id, + ) + + @staticmethod + def parse_experiment_arm_path(path: str) -> Dict[str, str]: + """Parses a experiment_arm path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/experimentArms/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def geo_target_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified geo_target_constant string.""" + return "geoTargetConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_geo_target_constant_path(path: str) -> Dict[str, str]: + """Parses a geo_target_constant path into its component segments.""" + m = re.match(r"^geoTargetConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_path( + customer_id: str, + keyword_plan_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan string.""" + return "customers/{customer_id}/keywordPlans/{keyword_plan_id}".format( + customer_id=customer_id, + keyword_plan_id=keyword_plan_id, + ) + + @staticmethod + def parse_keyword_plan_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlans/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_ad_group_path( + customer_id: str, + keyword_plan_ad_group_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_ad_group string.""" + return "customers/{customer_id}/keywordPlanAdGroups/{keyword_plan_ad_group_id}".format( + customer_id=customer_id, + keyword_plan_ad_group_id=keyword_plan_ad_group_id, + ) + + @staticmethod + def parse_keyword_plan_ad_group_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanAdGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_ad_group_keyword_path( + customer_id: str, + keyword_plan_ad_group_keyword_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_ad_group_keyword string.""" + return "customers/{customer_id}/keywordPlanAdGroupKeywords/{keyword_plan_ad_group_keyword_id}".format( + customer_id=customer_id, + keyword_plan_ad_group_keyword_id=keyword_plan_ad_group_keyword_id, + ) + + @staticmethod + def parse_keyword_plan_ad_group_keyword_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_ad_group_keyword path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanAdGroupKeywords/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_campaign_path( + customer_id: str, + keyword_plan_campaign_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_campaign string.""" + return "customers/{customer_id}/keywordPlanCampaigns/{keyword_plan_campaign_id}".format( + customer_id=customer_id, + keyword_plan_campaign_id=keyword_plan_campaign_id, + ) + + @staticmethod + def parse_keyword_plan_campaign_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanCampaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_campaign_keyword_path( + customer_id: str, + keyword_plan_campaign_keyword_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_campaign_keyword string.""" + return "customers/{customer_id}/keywordPlanCampaignKeywords/{keyword_plan_campaign_keyword_id}".format( + customer_id=customer_id, + keyword_plan_campaign_keyword_id=keyword_plan_campaign_keyword_id, + ) + + @staticmethod + def parse_keyword_plan_campaign_keyword_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_campaign_keyword path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanCampaignKeywords/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_theme_constant_path( + express_category_id: str, + express_sub_category_id: str, + ) -> str: + """Returns a fully-qualified keyword_theme_constant string.""" + return "keywordThemeConstants/{express_category_id}~{express_sub_category_id}".format( + express_category_id=express_category_id, + express_sub_category_id=express_sub_category_id, + ) + + @staticmethod + def parse_keyword_theme_constant_path(path: str) -> Dict[str, str]: + """Parses a keyword_theme_constant path into its component segments.""" + m = re.match( + r"^keywordThemeConstants/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def label_path( + customer_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified label string.""" + return "customers/{customer_id}/labels/{label_id}".format( + customer_id=customer_id, + label_id=label_id, + ) + + @staticmethod + def parse_label_path(path: str) -> Dict[str, str]: + """Parses a label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/labels/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def language_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified language_constant string.""" + return "languageConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_language_constant_path(path: str) -> Dict[str, str]: + """Parses a language_constant path into its component segments.""" + m = re.match(r"^languageConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def life_event_path( + customer_id: str, + life_event_id: str, + ) -> str: + """Returns a fully-qualified life_event string.""" + return "customers/{customer_id}/lifeEvents/{life_event_id}".format( + customer_id=customer_id, + life_event_id=life_event_id, + ) + + @staticmethod + def parse_life_event_path(path: str) -> Dict[str, str]: + """Parses a life_event path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/lifeEvents/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def mobile_app_category_constant_path( + mobile_app_category_id: str, + ) -> str: + """Returns a fully-qualified mobile_app_category_constant string.""" + return "mobileAppCategoryConstants/{mobile_app_category_id}".format( + mobile_app_category_id=mobile_app_category_id, + ) + + @staticmethod + def parse_mobile_app_category_constant_path(path: str) -> Dict[str, str]: + """Parses a mobile_app_category_constant path into its component segments.""" + m = re.match( + r"^mobileAppCategoryConstants/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def mobile_device_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified mobile_device_constant string.""" + return "mobileDeviceConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_mobile_device_constant_path(path: str) -> Dict[str, str]: + """Parses a mobile_device_constant path into its component segments.""" + m = re.match(r"^mobileDeviceConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def operating_system_version_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified operating_system_version_constant string.""" + return "operatingSystemVersionConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_operating_system_version_constant_path( + path: str, + ) -> Dict[str, str]: + """Parses a operating_system_version_constant path into its component segments.""" + m = re.match( + r"^operatingSystemVersionConstants/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def recommendation_subscription_path( + customer_id: str, + recommendation_type: str, + ) -> str: + """Returns a fully-qualified recommendation_subscription string.""" + return "customers/{customer_id}/recommendationSubscriptions/{recommendation_type}".format( + customer_id=customer_id, + recommendation_type=recommendation_type, + ) + + @staticmethod + def parse_recommendation_subscription_path(path: str) -> Dict[str, str]: + """Parses a recommendation_subscription path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/recommendationSubscriptions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def remarketing_action_path( + customer_id: str, + remarketing_action_id: str, + ) -> str: + """Returns a fully-qualified remarketing_action string.""" + return "customers/{customer_id}/remarketingActions/{remarketing_action_id}".format( + customer_id=customer_id, + remarketing_action_id=remarketing_action_id, + ) + + @staticmethod + def parse_remarketing_action_path(path: str) -> Dict[str, str]: + """Parses a remarketing_action path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/remarketingActions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def shared_criterion_path( + customer_id: str, + shared_set_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified shared_criterion string.""" + return "customers/{customer_id}/sharedCriteria/{shared_set_id}~{criterion_id}".format( + customer_id=customer_id, + shared_set_id=shared_set_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_shared_criterion_path(path: str) -> Dict[str, str]: + """Parses a shared_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/sharedCriteria/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def shared_set_path( + customer_id: str, + shared_set_id: str, + ) -> str: + """Returns a fully-qualified shared_set string.""" + return "customers/{customer_id}/sharedSets/{shared_set_id}".format( + customer_id=customer_id, + shared_set_id=shared_set_id, + ) + + @staticmethod + def parse_shared_set_path(path: str) -> Dict[str, str]: + """Parses a shared_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/sharedSets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def smart_campaign_setting_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified smart_campaign_setting string.""" + return "customers/{customer_id}/smartCampaignSettings/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_smart_campaign_setting_path(path: str) -> Dict[str, str]: + """Parses a smart_campaign_setting path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/smartCampaignSettings/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def topic_constant_path( + topic_id: str, + ) -> str: + """Returns a fully-qualified topic_constant string.""" + return "topicConstants/{topic_id}".format( + topic_id=topic_id, + ) + + @staticmethod + def parse_topic_constant_path(path: str) -> Dict[str, str]: + """Parses a topic_constant path into its component segments.""" + m = re.match(r"^topicConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def user_interest_path( + customer_id: str, + user_interest_id: str, + ) -> str: + """Returns a fully-qualified user_interest string.""" + return ( + "customers/{customer_id}/userInterests/{user_interest_id}".format( + customer_id=customer_id, + user_interest_id=user_interest_id, + ) + ) + + @staticmethod + def parse_user_interest_path(path: str) -> Dict[str, str]: + """Parses a user_interest path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/userInterests/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def user_list_path( + customer_id: str, + user_list_id: str, + ) -> str: + """Returns a fully-qualified user_list string.""" + return "customers/{customer_id}/userLists/{user_list_id}".format( + customer_id=customer_id, + user_list_id=user_list_id, + ) + + @staticmethod + def parse_user_list_path(path: str) -> Dict[str, str]: + """Parses a user_list path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/userLists/(?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 = BatchJobServiceClient._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 = BatchJobServiceClient._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 + ): + """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 = BatchJobServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = BatchJobServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + BatchJobServiceClient._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 = BatchJobServiceClient._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): + """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, + BatchJobServiceTransport, + Callable[..., BatchJobServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the batch job 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,BatchJobServiceTransport,Callable[..., BatchJobServiceTransport]]]): + 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 BatchJobServiceTransport 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, + ) = BatchJobServiceClient._read_environment_variables() + self._client_cert_source = ( + BatchJobServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = BatchJobServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, BatchJobServiceTransport) + if transport_provided: + # transport is a BatchJobServiceTransport 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(BatchJobServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or BatchJobServiceClient._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[BatchJobServiceTransport], + Callable[..., BatchJobServiceTransport], + ] = ( + BatchJobServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., BatchJobServiceTransport], 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.ads.googleads.v24.services.BatchJobServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.BatchJobService", + "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.ads.googleads.v24.services.BatchJobService", + "credentialsType": None, + } + ), + ) + + def mutate_batch_job( + self, + request: Optional[ + Union[batch_job_service.MutateBatchJobRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[batch_job_service.BatchJobOperation] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> batch_job_service.MutateBatchJobResponse: + r"""Mutates a batch job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateBatchJobRequest, dict]): + The request object. Request message for + [BatchJobService.MutateBatchJob][google.ads.googleads.v24.services.BatchJobService.MutateBatchJob]. + customer_id (str): + Required. The ID of the customer for + which to create a batch job. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (google.ads.googleads.v24.services.types.BatchJobOperation): + Required. The operation to perform on + an individual batch job. + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateBatchJobResponse: + Response message for + [BatchJobService.MutateBatchJob][google.ads.googleads.v24.services.BatchJobService.MutateBatchJob]. + + """ + # 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 = [customer_id, operation] + 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, batch_job_service.MutateBatchJobRequest): + request = batch_job_service.MutateBatchJobRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.mutate_batch_job] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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_batch_job_results( + self, + request: Optional[ + Union[batch_job_service.ListBatchJobResultsRequest, dict] + ] = None, + *, + resource_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]]] = (), + ) -> pagers.ListBatchJobResultsPager: + r"""Returns the results of the batch job. The job must be done. + Supports standard list paging. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BatchJobError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListBatchJobResultsRequest, dict]): + The request object. Request message for + [BatchJobService.ListBatchJobResults][google.ads.googleads.v24.services.BatchJobService.ListBatchJobResults]. + resource_name (str): + Required. The resource name of the + batch job whose results are being + listed. + + This corresponds to the ``resource_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.ads.googleads.v24.services.services.batch_job_service.pagers.ListBatchJobResultsPager: + Response message for + [BatchJobService.ListBatchJobResults][google.ads.googleads.v24.services.BatchJobService.ListBatchJobResults]. + + 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 = [resource_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, batch_job_service.ListBatchJobResultsRequest + ): + request = batch_job_service.ListBatchJobResultsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_batch_job_results + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_name),) + ), + ) + + # 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.ListBatchJobResultsPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def run_batch_job( + self, + request: Optional[ + Union[batch_job_service.RunBatchJobRequest, dict] + ] = None, + *, + resource_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]]] = (), + ) -> operation.Operation: + r"""Runs the batch job. + + The Operation.metadata field type is BatchJobMetadata. When + finished, the long running operation will not contain errors or + a response. Instead, use ListBatchJobResults to get the results + of the job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BatchJobError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.RunBatchJobRequest, dict]): + The request object. Request message for + [BatchJobService.RunBatchJob][google.ads.googleads.v24.services.BatchJobService.RunBatchJob]. + resource_name (str): + Required. The resource name of the + BatchJob to run. + + This corresponds to the ``resource_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.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 = [resource_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, batch_job_service.RunBatchJobRequest): + request = batch_job_service.RunBatchJobRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.run_batch_job] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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=batch_job.BatchJob.BatchJobMetadata, + ) + + # Done; return the response. + return response + + def add_batch_job_operations( + self, + request: Optional[ + Union[batch_job_service.AddBatchJobOperationsRequest, dict] + ] = None, + *, + resource_name: Optional[str] = None, + sequence_token: Optional[str] = None, + mutate_operations: Optional[ + MutableSequence[google_ads_service.MutateOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> batch_job_service.AddBatchJobOperationsResponse: + r"""Add operations to the batch job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BatchJobError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.AddBatchJobOperationsRequest, dict]): + The request object. Request message for + [BatchJobService.AddBatchJobOperations][google.ads.googleads.v24.services.BatchJobService.AddBatchJobOperations]. + resource_name (str): + Required. The resource name of the + batch job. + + This corresponds to the ``resource_name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + sequence_token (str): + A token used to enforce sequencing. + + The first AddBatchJobOperations request for a batch job + should not set sequence_token. Subsequent requests must + set sequence_token to the value of next_sequence_token + received in the previous AddBatchJobOperations response. + + This corresponds to the ``sequence_token`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + mutate_operations (MutableSequence[google.ads.googleads.v24.services.types.MutateOperation]): + Required. The list of mutates being + added. + Operations can use negative integers as + temp ids to signify dependencies between + entities created in this batch job. For + example, a customer with id = 1234 can + create a campaign and an ad group in + that same campaign by creating a + campaign in the first operation with the + resource name explicitly set to + "customers/1234/campaigns/-1", and + creating an ad group in the second + operation with the campaign field also + set to "customers/1234/campaigns/-1". + + This corresponds to the ``mutate_operations`` 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.ads.googleads.v24.services.types.AddBatchJobOperationsResponse: + Response message for + [BatchJobService.AddBatchJobOperations][google.ads.googleads.v24.services.BatchJobService.AddBatchJobOperations]. + + """ + # 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 = [resource_name, sequence_token, mutate_operations] + 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, batch_job_service.AddBatchJobOperationsRequest + ): + request = batch_job_service.AddBatchJobOperationsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + if sequence_token is not None: + request.sequence_token = sequence_token + if mutate_operations is not None: + request.mutate_operations = mutate_operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.add_batch_job_operations + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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) -> "BatchJobServiceClient": + 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() + + +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__ = ("BatchJobServiceClient",) diff --git a/google/ads/googleads/v24/services/services/batch_job_service/pagers.py b/google/ads/googleads/v24/services/services/batch_job_service/pagers.py new file mode 100644 index 000000000..45b281704 --- /dev/null +++ b/google/ads/googleads/v24/services/services/batch_job_service/pagers.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import retry_async as retries_async +from typing import ( + Any, + AsyncIterator, + Awaitable, + Callable, + Sequence, + Tuple, + Iterator, + Union, +) + +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.ads.googleads.v24.services.types import batch_job_service + + +class ListBatchJobResultsPager: + """A pager for iterating through ``list_batch_job_results`` requests. + + This class thinly wraps an initial + :class:`google.ads.googleads.v24.services.types.ListBatchJobResultsResponse` object, and + provides an ``__iter__`` method to iterate through its + ``results`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``ListBatchJobResults`` requests and continue to iterate + through the ``results`` field on the + corresponding responses. + + All the usual :class:`google.ads.googleads.v24.services.types.ListBatchJobResultsResponse` + 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[..., batch_job_service.ListBatchJobResultsResponse], + request: batch_job_service.ListBatchJobResultsRequest, + response: batch_job_service.ListBatchJobResultsResponse, + *, + 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.ads.googleads.v24.services.types.ListBatchJobResultsRequest): + The initial request object. + response (google.ads.googleads.v24.services.types.ListBatchJobResultsResponse): + 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 = batch_job_service.ListBatchJobResultsRequest(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[batch_job_service.ListBatchJobResultsResponse]: + 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[batch_job_service.BatchJobResult]: + for page in self.pages: + yield from page.results + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListBatchJobResultsAsyncPager: + """A pager for iterating through ``list_batch_job_results`` requests. + + This class thinly wraps an initial + :class:`google.ads.googleads.v24.services.types.ListBatchJobResultsResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``results`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``ListBatchJobResults`` requests and continue to iterate + through the ``results`` field on the + corresponding responses. + + All the usual :class:`google.ads.googleads.v24.services.types.ListBatchJobResultsResponse` + 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[batch_job_service.ListBatchJobResultsResponse] + ], + request: batch_job_service.ListBatchJobResultsRequest, + response: batch_job_service.ListBatchJobResultsResponse, + *, + 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.ads.googleads.v24.services.types.ListBatchJobResultsRequest): + The initial request object. + response (google.ads.googleads.v24.services.types.ListBatchJobResultsResponse): + 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 = batch_job_service.ListBatchJobResultsRequest(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[batch_job_service.ListBatchJobResultsResponse]: + 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[batch_job_service.BatchJobResult]: + async def async_generator(): + async for page in self.pages: + for response in page.results: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/google/ads/googleads/v24/services/services/batch_job_service/transports/README.rst b/google/ads/googleads/v24/services/services/batch_job_service/transports/README.rst new file mode 100644 index 000000000..4db611252 --- /dev/null +++ b/google/ads/googleads/v24/services/services/batch_job_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`BatchJobServiceTransport` is the ABC for all transports. +- public child `BatchJobServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `BatchJobServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseBatchJobServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `BatchJobServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/batch_job_service/transports/__init__.py b/google/ads/googleads/v24/services/services/batch_job_service/transports/__init__.py new file mode 100644 index 000000000..dea15c115 --- /dev/null +++ b/google/ads/googleads/v24/services/services/batch_job_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import BatchJobServiceTransport +from .grpc import BatchJobServiceGrpcTransport +from .grpc_asyncio import BatchJobServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[BatchJobServiceTransport]] +_transport_registry["grpc"] = BatchJobServiceGrpcTransport +_transport_registry["grpc_asyncio"] = BatchJobServiceGrpcAsyncIOTransport + +__all__ = ( + "BatchJobServiceTransport", + "BatchJobServiceGrpcTransport", + "BatchJobServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/batch_job_service/transports/base.py b/google/ads/googleads/v24/services/services/batch_job_service/transports/base.py new file mode 100644 index 000000000..3a4fd7a51 --- /dev/null +++ b/google/ads/googleads/v24/services/services/batch_job_service/transports/base.py @@ -0,0 +1,227 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import batch_job_service +from google.longrunning import operations_pb2 # type: ignore + +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 BatchJobServiceTransport(abc.ABC): + """Abstract transport class for BatchJobService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_batch_job: gapic_v1.method.wrap_method( + self.mutate_batch_job, + default_timeout=None, + client_info=client_info, + ), + self.list_batch_job_results: gapic_v1.method.wrap_method( + self.list_batch_job_results, + default_timeout=None, + client_info=client_info, + ), + self.run_batch_job: gapic_v1.method.wrap_method( + self.run_batch_job, + default_timeout=None, + client_info=client_info, + ), + self.add_batch_job_operations: gapic_v1.method.wrap_method( + self.add_batch_job_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 operations_client(self): + """Return the client designed to process long-running operations.""" + raise NotImplementedError() + + @property + def mutate_batch_job( + self, + ) -> Callable[ + [batch_job_service.MutateBatchJobRequest], + Union[ + batch_job_service.MutateBatchJobResponse, + Awaitable[batch_job_service.MutateBatchJobResponse], + ], + ]: + raise NotImplementedError() + + @property + def list_batch_job_results( + self, + ) -> Callable[ + [batch_job_service.ListBatchJobResultsRequest], + Union[ + batch_job_service.ListBatchJobResultsResponse, + Awaitable[batch_job_service.ListBatchJobResultsResponse], + ], + ]: + raise NotImplementedError() + + @property + def run_batch_job( + self, + ) -> Callable[ + [batch_job_service.RunBatchJobRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def add_batch_job_operations( + self, + ) -> Callable[ + [batch_job_service.AddBatchJobOperationsRequest], + Union[ + batch_job_service.AddBatchJobOperationsResponse, + Awaitable[batch_job_service.AddBatchJobOperationsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("BatchJobServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/batch_job_service/transports/grpc.py b/google/ads/googleads/v24/services/services/batch_job_service/transports/grpc.py new file mode 100644 index 000000000..e079acb10 --- /dev/null +++ b/google/ads/googleads/v24/services/services/batch_job_service/transports/grpc.py @@ -0,0 +1,516 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import batch_job_service +from google.longrunning import operations_pb2 # type: ignore +from .base import BatchJobServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.BatchJobService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.BatchJobService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class BatchJobServiceGrpcTransport(BatchJobServiceTransport): + """gRPC backend transport for BatchJobService. + + Service to manage batch jobs. + + 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 = "googleads.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: 'googleads.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. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client: Optional[operations_v1.OperationsClient] = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if 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 = "googleads.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 operations_client(self) -> operations_v1.OperationsClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Quick check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsClient( + self._logged_channel + ) + + # Return the client from cache. + return self._operations_client + + @property + def mutate_batch_job( + self, + ) -> Callable[ + [batch_job_service.MutateBatchJobRequest], + batch_job_service.MutateBatchJobResponse, + ]: + r"""Return a callable for the mutate batch job method over gRPC. + + Mutates a batch job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Returns: + Callable[[~.MutateBatchJobRequest], + ~.MutateBatchJobResponse]: + 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 "mutate_batch_job" not in self._stubs: + self._stubs["mutate_batch_job"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BatchJobService/MutateBatchJob", + request_serializer=batch_job_service.MutateBatchJobRequest.serialize, + response_deserializer=batch_job_service.MutateBatchJobResponse.deserialize, + ) + return self._stubs["mutate_batch_job"] + + @property + def list_batch_job_results( + self, + ) -> Callable[ + [batch_job_service.ListBatchJobResultsRequest], + batch_job_service.ListBatchJobResultsResponse, + ]: + r"""Return a callable for the list batch job results method over gRPC. + + Returns the results of the batch job. The job must be done. + Supports standard list paging. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BatchJobError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.ListBatchJobResultsRequest], + ~.ListBatchJobResultsResponse]: + 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_batch_job_results" not in self._stubs: + self._stubs["list_batch_job_results"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BatchJobService/ListBatchJobResults", + request_serializer=batch_job_service.ListBatchJobResultsRequest.serialize, + response_deserializer=batch_job_service.ListBatchJobResultsResponse.deserialize, + ) + ) + return self._stubs["list_batch_job_results"] + + @property + def run_batch_job( + self, + ) -> Callable[ + [batch_job_service.RunBatchJobRequest], operations_pb2.Operation + ]: + r"""Return a callable for the run batch job method over gRPC. + + Runs the batch job. + + The Operation.metadata field type is BatchJobMetadata. When + finished, the long running operation will not contain errors or + a response. Instead, use ListBatchJobResults to get the results + of the job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BatchJobError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.RunBatchJobRequest], + ~.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 "run_batch_job" not in self._stubs: + self._stubs["run_batch_job"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BatchJobService/RunBatchJob", + request_serializer=batch_job_service.RunBatchJobRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["run_batch_job"] + + @property + def add_batch_job_operations( + self, + ) -> Callable[ + [batch_job_service.AddBatchJobOperationsRequest], + batch_job_service.AddBatchJobOperationsResponse, + ]: + r"""Return a callable for the add batch job operations method over gRPC. + + Add operations to the batch job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BatchJobError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + + Returns: + Callable[[~.AddBatchJobOperationsRequest], + ~.AddBatchJobOperationsResponse]: + 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 "add_batch_job_operations" not in self._stubs: + self._stubs["add_batch_job_operations"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BatchJobService/AddBatchJobOperations", + request_serializer=batch_job_service.AddBatchJobOperationsRequest.serialize, + response_deserializer=batch_job_service.AddBatchJobOperationsResponse.deserialize, + ) + ) + return self._stubs["add_batch_job_operations"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("BatchJobServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/batch_job_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/batch_job_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..f5a62451f --- /dev/null +++ b/google/ads/googleads/v24/services/services/batch_job_service/transports/grpc_asyncio.py @@ -0,0 +1,555 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import batch_job_service +from google.longrunning import operations_pb2 # type: ignore +from .base import BatchJobServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.BatchJobService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.BatchJobService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class BatchJobServiceGrpcAsyncIOTransport(BatchJobServiceTransport): + """gRPC AsyncIO backend transport for BatchJobService. + + Service to manage batch jobs. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client: Optional[ + operations_v1.OperationsAsyncClient + ] = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if 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 operations_client(self) -> operations_v1.OperationsAsyncClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Quick check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsAsyncClient( + self._logged_channel + ) + + # Return the client from cache. + return self._operations_client + + @property + def mutate_batch_job( + self, + ) -> Callable[ + [batch_job_service.MutateBatchJobRequest], + Awaitable[batch_job_service.MutateBatchJobResponse], + ]: + r"""Return a callable for the mutate batch job method over gRPC. + + Mutates a batch job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Returns: + Callable[[~.MutateBatchJobRequest], + Awaitable[~.MutateBatchJobResponse]]: + 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 "mutate_batch_job" not in self._stubs: + self._stubs["mutate_batch_job"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BatchJobService/MutateBatchJob", + request_serializer=batch_job_service.MutateBatchJobRequest.serialize, + response_deserializer=batch_job_service.MutateBatchJobResponse.deserialize, + ) + return self._stubs["mutate_batch_job"] + + @property + def list_batch_job_results( + self, + ) -> Callable[ + [batch_job_service.ListBatchJobResultsRequest], + Awaitable[batch_job_service.ListBatchJobResultsResponse], + ]: + r"""Return a callable for the list batch job results method over gRPC. + + Returns the results of the batch job. The job must be done. + Supports standard list paging. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BatchJobError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.ListBatchJobResultsRequest], + Awaitable[~.ListBatchJobResultsResponse]]: + 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_batch_job_results" not in self._stubs: + self._stubs["list_batch_job_results"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BatchJobService/ListBatchJobResults", + request_serializer=batch_job_service.ListBatchJobResultsRequest.serialize, + response_deserializer=batch_job_service.ListBatchJobResultsResponse.deserialize, + ) + ) + return self._stubs["list_batch_job_results"] + + @property + def run_batch_job( + self, + ) -> Callable[ + [batch_job_service.RunBatchJobRequest], + Awaitable[operations_pb2.Operation], + ]: + r"""Return a callable for the run batch job method over gRPC. + + Runs the batch job. + + The Operation.metadata field type is BatchJobMetadata. When + finished, the long running operation will not contain errors or + a response. Instead, use ListBatchJobResults to get the results + of the job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BatchJobError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.RunBatchJobRequest], + 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 "run_batch_job" not in self._stubs: + self._stubs["run_batch_job"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BatchJobService/RunBatchJob", + request_serializer=batch_job_service.RunBatchJobRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["run_batch_job"] + + @property + def add_batch_job_operations( + self, + ) -> Callable[ + [batch_job_service.AddBatchJobOperationsRequest], + Awaitable[batch_job_service.AddBatchJobOperationsResponse], + ]: + r"""Return a callable for the add batch job operations method over gRPC. + + Add operations to the batch job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BatchJobError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + + Returns: + Callable[[~.AddBatchJobOperationsRequest], + Awaitable[~.AddBatchJobOperationsResponse]]: + 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 "add_batch_job_operations" not in self._stubs: + self._stubs["add_batch_job_operations"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BatchJobService/AddBatchJobOperations", + request_serializer=batch_job_service.AddBatchJobOperationsRequest.serialize, + response_deserializer=batch_job_service.AddBatchJobOperationsResponse.deserialize, + ) + ) + return self._stubs["add_batch_job_operations"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_batch_job: self._wrap_method( + self.mutate_batch_job, + default_timeout=None, + client_info=client_info, + ), + self.list_batch_job_results: self._wrap_method( + self.list_batch_job_results, + default_timeout=None, + client_info=client_info, + ), + self.run_batch_job: self._wrap_method( + self.run_batch_job, + default_timeout=None, + client_info=client_info, + ), + self.add_batch_job_operations: self._wrap_method( + self.add_batch_job_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" + + +__all__ = ("BatchJobServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/benchmarks_service/__init__.py b/google/ads/googleads/v24/services/services/benchmarks_service/__init__.py new file mode 100644 index 000000000..866d1fa27 --- /dev/null +++ b/google/ads/googleads/v24/services/services/benchmarks_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import BenchmarksServiceClient +from .async_client import BenchmarksServiceAsyncClient + +__all__ = ( + "BenchmarksServiceClient", + "BenchmarksServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/benchmarks_service/async_client.py b/google/ads/googleads/v24/services/services/benchmarks_service/async_client.py new file mode 100644 index 000000000..ab17ff5c5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/benchmarks_service/async_client.py @@ -0,0 +1,733 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.enums.types import benchmarks_source_type +from google.ads.googleads.v24.services.types import benchmarks_service +from .transports.base import BenchmarksServiceTransport, DEFAULT_CLIENT_INFO +from .client import BenchmarksServiceClient + +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 BenchmarksServiceAsyncClient: + """BenchmarksService helps users compare YouTube advertisement + data against industry benchmarks. Accessible to allowlisted + customers only. + """ + + _client: BenchmarksServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = BenchmarksServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = BenchmarksServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + BenchmarksServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = BenchmarksServiceClient._DEFAULT_UNIVERSE + + common_billing_account_path = staticmethod( + BenchmarksServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + BenchmarksServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + BenchmarksServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + BenchmarksServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + BenchmarksServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + BenchmarksServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + BenchmarksServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + BenchmarksServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + BenchmarksServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + BenchmarksServiceClient.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: + BenchmarksServiceAsyncClient: The constructed client. + """ + return BenchmarksServiceClient.from_service_account_info.__func__(BenchmarksServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + BenchmarksServiceAsyncClient: The constructed client. + """ + return BenchmarksServiceClient.from_service_account_file.__func__(BenchmarksServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return BenchmarksServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> BenchmarksServiceTransport: + """Returns the transport used by the client instance. + + Returns: + BenchmarksServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = BenchmarksServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + BenchmarksServiceTransport, + Callable[..., BenchmarksServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the benchmarks 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,BenchmarksServiceTransport,Callable[..., BenchmarksServiceTransport]]]): + 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 BenchmarksServiceTransport 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 = BenchmarksServiceClient( + 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.ads.googleads.v24.services.BenchmarksServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.BenchmarksService", + "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.ads.googleads.v24.services.BenchmarksService", + "credentialsType": None, + } + ), + ) + + async def list_benchmarks_available_dates( + self, + request: Optional[ + Union[benchmarks_service.ListBenchmarksAvailableDatesRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> benchmarks_service.ListBenchmarksAvailableDatesResponse: + r"""Returns a date range that supports benchmarks. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListBenchmarksAvailableDatesRequest, dict]]): + The request object. Request message for + [BenchmarksService.ListBenchmarksAvailableDates][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksAvailableDates]. + 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.googleads.v24.services.types.ListBenchmarksAvailableDatesResponse: + Response message for + [BenchmarksService.ListBenchmarksAvailableDates][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksAvailableDates]. + + """ + # 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, benchmarks_service.ListBenchmarksAvailableDatesRequest + ): + request = benchmarks_service.ListBenchmarksAvailableDatesRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_benchmarks_available_dates + ] + + # 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_benchmarks_locations( + self, + request: Optional[ + Union[benchmarks_service.ListBenchmarksLocationsRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> benchmarks_service.ListBenchmarksLocationsResponse: + r"""Returns the list of locations that support benchmarks (for + example, countries). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListBenchmarksLocationsRequest, dict]]): + The request object. Request message for + [BenchmarksService.ListBenchmarksLocations][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksLocations]. + 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.googleads.v24.services.types.ListBenchmarksLocationsResponse: + Response message for + [BenchmarksService.ListBenchmarksLocations][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksLocations]. + + """ + # 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, benchmarks_service.ListBenchmarksLocationsRequest + ): + request = benchmarks_service.ListBenchmarksLocationsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_benchmarks_locations + ] + + # 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_benchmarks_products( + self, + request: Optional[ + Union[benchmarks_service.ListBenchmarksProductsRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> benchmarks_service.ListBenchmarksProductsResponse: + r"""Returns the list of products that supports benchmarks. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListBenchmarksProductsRequest, dict]]): + The request object. Request message for + [BenchmarksService.ListBenchmarksProducts][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksProducts]. + 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.googleads.v24.services.types.ListBenchmarksProductsResponse: + Response message for + [BenchmarksService.ListBenchmarksProducts][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksProducts]. + + """ + # 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, benchmarks_service.ListBenchmarksProductsRequest + ): + request = benchmarks_service.ListBenchmarksProductsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_benchmarks_products + ] + + # 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_benchmarks_sources( + self, + request: Optional[ + Union[benchmarks_service.ListBenchmarksSourcesRequest, dict] + ] = None, + *, + benchmarks_sources: Optional[ + MutableSequence[ + benchmarks_source_type.BenchmarksSourceTypeEnum.BenchmarksSourceType + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> benchmarks_service.ListBenchmarksSourcesResponse: + r"""Returns the list of benchmarks sources (for example, Industry + Verticals). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListBenchmarksSourcesRequest, dict]]): + The request object. Request message for + [BenchmarksService.ListBenchmarksSources][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksSources]. + benchmarks_sources (:class:`MutableSequence[google.ads.googleads.v24.enums.types.BenchmarksSourceTypeEnum.BenchmarksSourceType]`): + Required. The types of benchmarks sources to be returned + (for example, INDUSTRY_VERTICAL). + + This corresponds to the ``benchmarks_sources`` 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.ads.googleads.v24.services.types.ListBenchmarksSourcesResponse: + Response message for + [BenchmarksService.ListBenchmarksSources][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksSources]. + + """ + # 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 = [benchmarks_sources] + 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, benchmarks_service.ListBenchmarksSourcesRequest + ): + request = benchmarks_service.ListBenchmarksSourcesRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if benchmarks_sources: + request.benchmarks_sources.extend(benchmarks_sources) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_benchmarks_sources + ] + + # 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 generate_benchmarks_metrics( + self, + request: Optional[ + Union[benchmarks_service.GenerateBenchmarksMetricsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + location: Optional[criteria.LocationInfo] = None, + benchmarks_source: Optional[benchmarks_service.BenchmarksSource] = None, + product_filter: Optional[benchmarks_service.ProductFilter] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> benchmarks_service.GenerateBenchmarksMetricsResponse: + r"""Returns YouTube advertisement metrics for the given client + against industry benchmarks. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BenchmarksError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateBenchmarksMetricsRequest, dict]]): + The request object. Request message for + [BenchmarksService.GenerateBenchmarksMetrics][google.ads.googleads.v24.services.BenchmarksService.GenerateBenchmarksMetrics]. + customer_id (:class:`str`): + Required. The ID of the customer. + Supply a client customer ID to generate + metrics for the customer. A manager + account customer ID will not return + customer metrics since it does not have + any associated direct ad campaigns. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + location (:class:`google.ads.googleads.v24.common.types.LocationInfo`): + Required. The location to generate + benchmarks metrics for. + + This corresponds to the ``location`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + benchmarks_source (:class:`google.ads.googleads.v24.services.types.BenchmarksSource`): + Required. The source used to generate + benchmarks metrics for. + + This corresponds to the ``benchmarks_source`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + product_filter (:class:`google.ads.googleads.v24.services.types.ProductFilter`): + Required. The products to aggregate + metrics over. Product filter settings + support a list of product IDs or a list + of marketing objectives. + + This corresponds to the ``product_filter`` 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.ads.googleads.v24.services.types.GenerateBenchmarksMetricsResponse: + Response message for + [BenchmarksService.GenerateBenchmarksMetrics][google.ads.googleads.v24.services.BenchmarksService.GenerateBenchmarksMetrics]. + + """ + # 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 = [ + customer_id, + location, + benchmarks_source, + product_filter, + ] + 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, benchmarks_service.GenerateBenchmarksMetricsRequest + ): + request = benchmarks_service.GenerateBenchmarksMetricsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if location is not None: + request.location = location + if benchmarks_source is not None: + request.benchmarks_source = benchmarks_source + if product_filter is not None: + request.product_filter = product_filter + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_benchmarks_metrics + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "BenchmarksServiceAsyncClient": + 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__ = ("BenchmarksServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/benchmarks_service/client.py b/google/ads/googleads/v24/services/services/benchmarks_service/client.py new file mode 100644 index 000000000..516531bd2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/benchmarks_service/client.py @@ -0,0 +1,1182 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.enums.types import benchmarks_source_type +from google.ads.googleads.v24.services.types import benchmarks_service +from .transports.base import BenchmarksServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import BenchmarksServiceGrpcTransport +from .transports.grpc_asyncio import BenchmarksServiceGrpcAsyncIOTransport + + +class BenchmarksServiceClientMeta(type): + """Metaclass for the BenchmarksService 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[BenchmarksServiceTransport]] + _transport_registry["grpc"] = BenchmarksServiceGrpcTransport + _transport_registry["grpc_asyncio"] = BenchmarksServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[BenchmarksServiceTransport]: + """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 BenchmarksServiceClient(metaclass=BenchmarksServiceClientMeta): + """BenchmarksService helps users compare YouTube advertisement + data against industry benchmarks. Accessible to allowlisted + customers only. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + BenchmarksServiceClient: 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: + BenchmarksServiceClient: 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) -> BenchmarksServiceTransport: + """Returns the transport used by the client instance. + + Returns: + BenchmarksServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @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 = BenchmarksServiceClient._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 = BenchmarksServiceClient._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 + ): + """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 = BenchmarksServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = BenchmarksServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + BenchmarksServiceClient._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 = BenchmarksServiceClient._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): + """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, + BenchmarksServiceTransport, + Callable[..., BenchmarksServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the benchmarks 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,BenchmarksServiceTransport,Callable[..., BenchmarksServiceTransport]]]): + 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 BenchmarksServiceTransport 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, + ) = BenchmarksServiceClient._read_environment_variables() + self._client_cert_source = ( + BenchmarksServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = BenchmarksServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, BenchmarksServiceTransport) + if transport_provided: + # transport is a BenchmarksServiceTransport 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(BenchmarksServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or BenchmarksServiceClient._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[BenchmarksServiceTransport], + Callable[..., BenchmarksServiceTransport], + ] = ( + BenchmarksServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., BenchmarksServiceTransport], 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.ads.googleads.v24.services.BenchmarksServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.BenchmarksService", + "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.ads.googleads.v24.services.BenchmarksService", + "credentialsType": None, + } + ), + ) + + def list_benchmarks_available_dates( + self, + request: Optional[ + Union[benchmarks_service.ListBenchmarksAvailableDatesRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> benchmarks_service.ListBenchmarksAvailableDatesResponse: + r"""Returns a date range that supports benchmarks. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListBenchmarksAvailableDatesRequest, dict]): + The request object. Request message for + [BenchmarksService.ListBenchmarksAvailableDates][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksAvailableDates]. + 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.googleads.v24.services.types.ListBenchmarksAvailableDatesResponse: + Response message for + [BenchmarksService.ListBenchmarksAvailableDates][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksAvailableDates]. + + """ + # 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, benchmarks_service.ListBenchmarksAvailableDatesRequest + ): + request = benchmarks_service.ListBenchmarksAvailableDatesRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_benchmarks_available_dates + ] + + # 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_benchmarks_locations( + self, + request: Optional[ + Union[benchmarks_service.ListBenchmarksLocationsRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> benchmarks_service.ListBenchmarksLocationsResponse: + r"""Returns the list of locations that support benchmarks (for + example, countries). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListBenchmarksLocationsRequest, dict]): + The request object. Request message for + [BenchmarksService.ListBenchmarksLocations][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksLocations]. + 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.googleads.v24.services.types.ListBenchmarksLocationsResponse: + Response message for + [BenchmarksService.ListBenchmarksLocations][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksLocations]. + + """ + # 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, benchmarks_service.ListBenchmarksLocationsRequest + ): + request = benchmarks_service.ListBenchmarksLocationsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_benchmarks_locations + ] + + # 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_benchmarks_products( + self, + request: Optional[ + Union[benchmarks_service.ListBenchmarksProductsRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> benchmarks_service.ListBenchmarksProductsResponse: + r"""Returns the list of products that supports benchmarks. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListBenchmarksProductsRequest, dict]): + The request object. Request message for + [BenchmarksService.ListBenchmarksProducts][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksProducts]. + 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.googleads.v24.services.types.ListBenchmarksProductsResponse: + Response message for + [BenchmarksService.ListBenchmarksProducts][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksProducts]. + + """ + # 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, benchmarks_service.ListBenchmarksProductsRequest + ): + request = benchmarks_service.ListBenchmarksProductsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_benchmarks_products + ] + + # 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_benchmarks_sources( + self, + request: Optional[ + Union[benchmarks_service.ListBenchmarksSourcesRequest, dict] + ] = None, + *, + benchmarks_sources: Optional[ + MutableSequence[ + benchmarks_source_type.BenchmarksSourceTypeEnum.BenchmarksSourceType + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> benchmarks_service.ListBenchmarksSourcesResponse: + r"""Returns the list of benchmarks sources (for example, Industry + Verticals). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListBenchmarksSourcesRequest, dict]): + The request object. Request message for + [BenchmarksService.ListBenchmarksSources][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksSources]. + benchmarks_sources (MutableSequence[google.ads.googleads.v24.enums.types.BenchmarksSourceTypeEnum.BenchmarksSourceType]): + Required. The types of benchmarks sources to be returned + (for example, INDUSTRY_VERTICAL). + + This corresponds to the ``benchmarks_sources`` 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.ads.googleads.v24.services.types.ListBenchmarksSourcesResponse: + Response message for + [BenchmarksService.ListBenchmarksSources][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksSources]. + + """ + # 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 = [benchmarks_sources] + 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, benchmarks_service.ListBenchmarksSourcesRequest + ): + request = benchmarks_service.ListBenchmarksSourcesRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if benchmarks_sources is not None: + request.benchmarks_sources = benchmarks_sources + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_benchmarks_sources + ] + + # 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 generate_benchmarks_metrics( + self, + request: Optional[ + Union[benchmarks_service.GenerateBenchmarksMetricsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + location: Optional[criteria.LocationInfo] = None, + benchmarks_source: Optional[benchmarks_service.BenchmarksSource] = None, + product_filter: Optional[benchmarks_service.ProductFilter] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> benchmarks_service.GenerateBenchmarksMetricsResponse: + r"""Returns YouTube advertisement metrics for the given client + against industry benchmarks. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BenchmarksError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateBenchmarksMetricsRequest, dict]): + The request object. Request message for + [BenchmarksService.GenerateBenchmarksMetrics][google.ads.googleads.v24.services.BenchmarksService.GenerateBenchmarksMetrics]. + customer_id (str): + Required. The ID of the customer. + Supply a client customer ID to generate + metrics for the customer. A manager + account customer ID will not return + customer metrics since it does not have + any associated direct ad campaigns. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + location (google.ads.googleads.v24.common.types.LocationInfo): + Required. The location to generate + benchmarks metrics for. + + This corresponds to the ``location`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + benchmarks_source (google.ads.googleads.v24.services.types.BenchmarksSource): + Required. The source used to generate + benchmarks metrics for. + + This corresponds to the ``benchmarks_source`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + product_filter (google.ads.googleads.v24.services.types.ProductFilter): + Required. The products to aggregate + metrics over. Product filter settings + support a list of product IDs or a list + of marketing objectives. + + This corresponds to the ``product_filter`` 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.ads.googleads.v24.services.types.GenerateBenchmarksMetricsResponse: + Response message for + [BenchmarksService.GenerateBenchmarksMetrics][google.ads.googleads.v24.services.BenchmarksService.GenerateBenchmarksMetrics]. + + """ + # 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 = [ + customer_id, + location, + benchmarks_source, + product_filter, + ] + 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, benchmarks_service.GenerateBenchmarksMetricsRequest + ): + request = benchmarks_service.GenerateBenchmarksMetricsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if location is not None: + request.location = location + if benchmarks_source is not None: + request.benchmarks_source = benchmarks_source + if product_filter is not None: + request.product_filter = product_filter + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_benchmarks_metrics + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "BenchmarksServiceClient": + 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() + + +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__ = ("BenchmarksServiceClient",) diff --git a/google/ads/googleads/v24/services/services/benchmarks_service/transports/README.rst b/google/ads/googleads/v24/services/services/benchmarks_service/transports/README.rst new file mode 100644 index 000000000..ba78523ab --- /dev/null +++ b/google/ads/googleads/v24/services/services/benchmarks_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`BenchmarksServiceTransport` is the ABC for all transports. +- public child `BenchmarksServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `BenchmarksServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseBenchmarksServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `BenchmarksServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/benchmarks_service/transports/__init__.py b/google/ads/googleads/v24/services/services/benchmarks_service/transports/__init__.py new file mode 100644 index 000000000..7bf4c663b --- /dev/null +++ b/google/ads/googleads/v24/services/services/benchmarks_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import BenchmarksServiceTransport +from .grpc import BenchmarksServiceGrpcTransport +from .grpc_asyncio import BenchmarksServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[BenchmarksServiceTransport]] +_transport_registry["grpc"] = BenchmarksServiceGrpcTransport +_transport_registry["grpc_asyncio"] = BenchmarksServiceGrpcAsyncIOTransport + +__all__ = ( + "BenchmarksServiceTransport", + "BenchmarksServiceGrpcTransport", + "BenchmarksServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/benchmarks_service/transports/base.py b/google/ads/googleads/v24/services/services/benchmarks_service/transports/base.py new file mode 100644 index 000000000..eb8f7c261 --- /dev/null +++ b/google/ads/googleads/v24/services/services/benchmarks_service/transports/base.py @@ -0,0 +1,241 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import benchmarks_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 BenchmarksServiceTransport(abc.ABC): + """Abstract transport class for BenchmarksService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.list_benchmarks_available_dates: gapic_v1.method.wrap_method( + self.list_benchmarks_available_dates, + default_timeout=None, + client_info=client_info, + ), + self.list_benchmarks_locations: gapic_v1.method.wrap_method( + self.list_benchmarks_locations, + default_timeout=None, + client_info=client_info, + ), + self.list_benchmarks_products: gapic_v1.method.wrap_method( + self.list_benchmarks_products, + default_timeout=None, + client_info=client_info, + ), + self.list_benchmarks_sources: gapic_v1.method.wrap_method( + self.list_benchmarks_sources, + default_timeout=None, + client_info=client_info, + ), + self.generate_benchmarks_metrics: gapic_v1.method.wrap_method( + self.generate_benchmarks_metrics, + 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_benchmarks_available_dates( + self, + ) -> Callable[ + [benchmarks_service.ListBenchmarksAvailableDatesRequest], + Union[ + benchmarks_service.ListBenchmarksAvailableDatesResponse, + Awaitable[benchmarks_service.ListBenchmarksAvailableDatesResponse], + ], + ]: + raise NotImplementedError() + + @property + def list_benchmarks_locations( + self, + ) -> Callable[ + [benchmarks_service.ListBenchmarksLocationsRequest], + Union[ + benchmarks_service.ListBenchmarksLocationsResponse, + Awaitable[benchmarks_service.ListBenchmarksLocationsResponse], + ], + ]: + raise NotImplementedError() + + @property + def list_benchmarks_products( + self, + ) -> Callable[ + [benchmarks_service.ListBenchmarksProductsRequest], + Union[ + benchmarks_service.ListBenchmarksProductsResponse, + Awaitable[benchmarks_service.ListBenchmarksProductsResponse], + ], + ]: + raise NotImplementedError() + + @property + def list_benchmarks_sources( + self, + ) -> Callable[ + [benchmarks_service.ListBenchmarksSourcesRequest], + Union[ + benchmarks_service.ListBenchmarksSourcesResponse, + Awaitable[benchmarks_service.ListBenchmarksSourcesResponse], + ], + ]: + raise NotImplementedError() + + @property + def generate_benchmarks_metrics( + self, + ) -> Callable[ + [benchmarks_service.GenerateBenchmarksMetricsRequest], + Union[ + benchmarks_service.GenerateBenchmarksMetricsResponse, + Awaitable[benchmarks_service.GenerateBenchmarksMetricsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("BenchmarksServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/benchmarks_service/transports/grpc.py b/google/ads/googleads/v24/services/services/benchmarks_service/transports/grpc.py new file mode 100644 index 000000000..481fde7b5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/benchmarks_service/transports/grpc.py @@ -0,0 +1,534 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import benchmarks_service +from .base import BenchmarksServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.BenchmarksService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.BenchmarksService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class BenchmarksServiceGrpcTransport(BenchmarksServiceTransport): + """gRPC backend transport for BenchmarksService. + + BenchmarksService helps users compare YouTube advertisement + data against industry benchmarks. Accessible to allowlisted + customers only. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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_benchmarks_available_dates( + self, + ) -> Callable[ + [benchmarks_service.ListBenchmarksAvailableDatesRequest], + benchmarks_service.ListBenchmarksAvailableDatesResponse, + ]: + r"""Return a callable for the list benchmarks available + dates method over gRPC. + + Returns a date range that supports benchmarks. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListBenchmarksAvailableDatesRequest], + ~.ListBenchmarksAvailableDatesResponse]: + 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_benchmarks_available_dates" not in self._stubs: + self._stubs["list_benchmarks_available_dates"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BenchmarksService/ListBenchmarksAvailableDates", + request_serializer=benchmarks_service.ListBenchmarksAvailableDatesRequest.serialize, + response_deserializer=benchmarks_service.ListBenchmarksAvailableDatesResponse.deserialize, + ) + ) + return self._stubs["list_benchmarks_available_dates"] + + @property + def list_benchmarks_locations( + self, + ) -> Callable[ + [benchmarks_service.ListBenchmarksLocationsRequest], + benchmarks_service.ListBenchmarksLocationsResponse, + ]: + r"""Return a callable for the list benchmarks locations method over gRPC. + + Returns the list of locations that support benchmarks (for + example, countries). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListBenchmarksLocationsRequest], + ~.ListBenchmarksLocationsResponse]: + 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_benchmarks_locations" not in self._stubs: + self._stubs["list_benchmarks_locations"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BenchmarksService/ListBenchmarksLocations", + request_serializer=benchmarks_service.ListBenchmarksLocationsRequest.serialize, + response_deserializer=benchmarks_service.ListBenchmarksLocationsResponse.deserialize, + ) + ) + return self._stubs["list_benchmarks_locations"] + + @property + def list_benchmarks_products( + self, + ) -> Callable[ + [benchmarks_service.ListBenchmarksProductsRequest], + benchmarks_service.ListBenchmarksProductsResponse, + ]: + r"""Return a callable for the list benchmarks products method over gRPC. + + Returns the list of products that supports benchmarks. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListBenchmarksProductsRequest], + ~.ListBenchmarksProductsResponse]: + 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_benchmarks_products" not in self._stubs: + self._stubs["list_benchmarks_products"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BenchmarksService/ListBenchmarksProducts", + request_serializer=benchmarks_service.ListBenchmarksProductsRequest.serialize, + response_deserializer=benchmarks_service.ListBenchmarksProductsResponse.deserialize, + ) + ) + return self._stubs["list_benchmarks_products"] + + @property + def list_benchmarks_sources( + self, + ) -> Callable[ + [benchmarks_service.ListBenchmarksSourcesRequest], + benchmarks_service.ListBenchmarksSourcesResponse, + ]: + r"""Return a callable for the list benchmarks sources method over gRPC. + + Returns the list of benchmarks sources (for example, Industry + Verticals). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListBenchmarksSourcesRequest], + ~.ListBenchmarksSourcesResponse]: + 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_benchmarks_sources" not in self._stubs: + self._stubs["list_benchmarks_sources"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BenchmarksService/ListBenchmarksSources", + request_serializer=benchmarks_service.ListBenchmarksSourcesRequest.serialize, + response_deserializer=benchmarks_service.ListBenchmarksSourcesResponse.deserialize, + ) + ) + return self._stubs["list_benchmarks_sources"] + + @property + def generate_benchmarks_metrics( + self, + ) -> Callable[ + [benchmarks_service.GenerateBenchmarksMetricsRequest], + benchmarks_service.GenerateBenchmarksMetricsResponse, + ]: + r"""Return a callable for the generate benchmarks metrics method over gRPC. + + Returns YouTube advertisement metrics for the given client + against industry benchmarks. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BenchmarksError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateBenchmarksMetricsRequest], + ~.GenerateBenchmarksMetricsResponse]: + 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 "generate_benchmarks_metrics" not in self._stubs: + self._stubs["generate_benchmarks_metrics"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BenchmarksService/GenerateBenchmarksMetrics", + request_serializer=benchmarks_service.GenerateBenchmarksMetricsRequest.serialize, + response_deserializer=benchmarks_service.GenerateBenchmarksMetricsResponse.deserialize, + ) + ) + return self._stubs["generate_benchmarks_metrics"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("BenchmarksServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/benchmarks_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/benchmarks_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..883d48cfc --- /dev/null +++ b/google/ads/googleads/v24/services/services/benchmarks_service/transports/grpc_asyncio.py @@ -0,0 +1,575 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import benchmarks_service +from .base import BenchmarksServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.BenchmarksService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.BenchmarksService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class BenchmarksServiceGrpcAsyncIOTransport(BenchmarksServiceTransport): + """gRPC AsyncIO backend transport for BenchmarksService. + + BenchmarksService helps users compare YouTube advertisement + data against industry benchmarks. Accessible to allowlisted + customers only. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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_benchmarks_available_dates( + self, + ) -> Callable[ + [benchmarks_service.ListBenchmarksAvailableDatesRequest], + Awaitable[benchmarks_service.ListBenchmarksAvailableDatesResponse], + ]: + r"""Return a callable for the list benchmarks available + dates method over gRPC. + + Returns a date range that supports benchmarks. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListBenchmarksAvailableDatesRequest], + Awaitable[~.ListBenchmarksAvailableDatesResponse]]: + 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_benchmarks_available_dates" not in self._stubs: + self._stubs["list_benchmarks_available_dates"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BenchmarksService/ListBenchmarksAvailableDates", + request_serializer=benchmarks_service.ListBenchmarksAvailableDatesRequest.serialize, + response_deserializer=benchmarks_service.ListBenchmarksAvailableDatesResponse.deserialize, + ) + ) + return self._stubs["list_benchmarks_available_dates"] + + @property + def list_benchmarks_locations( + self, + ) -> Callable[ + [benchmarks_service.ListBenchmarksLocationsRequest], + Awaitable[benchmarks_service.ListBenchmarksLocationsResponse], + ]: + r"""Return a callable for the list benchmarks locations method over gRPC. + + Returns the list of locations that support benchmarks (for + example, countries). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListBenchmarksLocationsRequest], + Awaitable[~.ListBenchmarksLocationsResponse]]: + 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_benchmarks_locations" not in self._stubs: + self._stubs["list_benchmarks_locations"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BenchmarksService/ListBenchmarksLocations", + request_serializer=benchmarks_service.ListBenchmarksLocationsRequest.serialize, + response_deserializer=benchmarks_service.ListBenchmarksLocationsResponse.deserialize, + ) + ) + return self._stubs["list_benchmarks_locations"] + + @property + def list_benchmarks_products( + self, + ) -> Callable[ + [benchmarks_service.ListBenchmarksProductsRequest], + Awaitable[benchmarks_service.ListBenchmarksProductsResponse], + ]: + r"""Return a callable for the list benchmarks products method over gRPC. + + Returns the list of products that supports benchmarks. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListBenchmarksProductsRequest], + Awaitable[~.ListBenchmarksProductsResponse]]: + 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_benchmarks_products" not in self._stubs: + self._stubs["list_benchmarks_products"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BenchmarksService/ListBenchmarksProducts", + request_serializer=benchmarks_service.ListBenchmarksProductsRequest.serialize, + response_deserializer=benchmarks_service.ListBenchmarksProductsResponse.deserialize, + ) + ) + return self._stubs["list_benchmarks_products"] + + @property + def list_benchmarks_sources( + self, + ) -> Callable[ + [benchmarks_service.ListBenchmarksSourcesRequest], + Awaitable[benchmarks_service.ListBenchmarksSourcesResponse], + ]: + r"""Return a callable for the list benchmarks sources method over gRPC. + + Returns the list of benchmarks sources (for example, Industry + Verticals). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListBenchmarksSourcesRequest], + Awaitable[~.ListBenchmarksSourcesResponse]]: + 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_benchmarks_sources" not in self._stubs: + self._stubs["list_benchmarks_sources"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BenchmarksService/ListBenchmarksSources", + request_serializer=benchmarks_service.ListBenchmarksSourcesRequest.serialize, + response_deserializer=benchmarks_service.ListBenchmarksSourcesResponse.deserialize, + ) + ) + return self._stubs["list_benchmarks_sources"] + + @property + def generate_benchmarks_metrics( + self, + ) -> Callable[ + [benchmarks_service.GenerateBenchmarksMetricsRequest], + Awaitable[benchmarks_service.GenerateBenchmarksMetricsResponse], + ]: + r"""Return a callable for the generate benchmarks metrics method over gRPC. + + Returns YouTube advertisement metrics for the given client + against industry benchmarks. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BenchmarksError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateBenchmarksMetricsRequest], + Awaitable[~.GenerateBenchmarksMetricsResponse]]: + 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 "generate_benchmarks_metrics" not in self._stubs: + self._stubs["generate_benchmarks_metrics"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BenchmarksService/GenerateBenchmarksMetrics", + request_serializer=benchmarks_service.GenerateBenchmarksMetricsRequest.serialize, + response_deserializer=benchmarks_service.GenerateBenchmarksMetricsResponse.deserialize, + ) + ) + return self._stubs["generate_benchmarks_metrics"] + + 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_benchmarks_available_dates: self._wrap_method( + self.list_benchmarks_available_dates, + default_timeout=None, + client_info=client_info, + ), + self.list_benchmarks_locations: self._wrap_method( + self.list_benchmarks_locations, + default_timeout=None, + client_info=client_info, + ), + self.list_benchmarks_products: self._wrap_method( + self.list_benchmarks_products, + default_timeout=None, + client_info=client_info, + ), + self.list_benchmarks_sources: self._wrap_method( + self.list_benchmarks_sources, + default_timeout=None, + client_info=client_info, + ), + self.generate_benchmarks_metrics: self._wrap_method( + self.generate_benchmarks_metrics, + 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" + + +__all__ = ("BenchmarksServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/__init__.py b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/__init__.py new file mode 100644 index 000000000..fdebf2a58 --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import BiddingDataExclusionServiceClient +from .async_client import BiddingDataExclusionServiceAsyncClient + +__all__ = ( + "BiddingDataExclusionServiceClient", + "BiddingDataExclusionServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/async_client.py b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/async_client.py new file mode 100644 index 000000000..19be0ec7e --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/async_client.py @@ -0,0 +1,439 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + bidding_data_exclusion_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + BiddingDataExclusionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import BiddingDataExclusionServiceClient + +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 BiddingDataExclusionServiceAsyncClient: + """Service to manage bidding data exclusions.""" + + _client: BiddingDataExclusionServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = BiddingDataExclusionServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + BiddingDataExclusionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + BiddingDataExclusionServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = BiddingDataExclusionServiceClient._DEFAULT_UNIVERSE + + bidding_data_exclusion_path = staticmethod( + BiddingDataExclusionServiceClient.bidding_data_exclusion_path + ) + parse_bidding_data_exclusion_path = staticmethod( + BiddingDataExclusionServiceClient.parse_bidding_data_exclusion_path + ) + campaign_path = staticmethod( + BiddingDataExclusionServiceClient.campaign_path + ) + parse_campaign_path = staticmethod( + BiddingDataExclusionServiceClient.parse_campaign_path + ) + common_billing_account_path = staticmethod( + BiddingDataExclusionServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + BiddingDataExclusionServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + BiddingDataExclusionServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + BiddingDataExclusionServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + BiddingDataExclusionServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + BiddingDataExclusionServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + BiddingDataExclusionServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + BiddingDataExclusionServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + BiddingDataExclusionServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + BiddingDataExclusionServiceClient.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: + BiddingDataExclusionServiceAsyncClient: The constructed client. + """ + return BiddingDataExclusionServiceClient.from_service_account_info.__func__(BiddingDataExclusionServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + BiddingDataExclusionServiceAsyncClient: The constructed client. + """ + return BiddingDataExclusionServiceClient.from_service_account_file.__func__(BiddingDataExclusionServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return BiddingDataExclusionServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> BiddingDataExclusionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + BiddingDataExclusionServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = BiddingDataExclusionServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + BiddingDataExclusionServiceTransport, + Callable[..., BiddingDataExclusionServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the bidding data exclusion 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,BiddingDataExclusionServiceTransport,Callable[..., BiddingDataExclusionServiceTransport]]]): + 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 BiddingDataExclusionServiceTransport 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 = BiddingDataExclusionServiceClient( + 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.ads.googleads.v24.services.BiddingDataExclusionServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.BiddingDataExclusionService", + "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.ads.googleads.v24.services.BiddingDataExclusionService", + "credentialsType": None, + } + ), + ) + + async def mutate_bidding_data_exclusions( + self, + request: Optional[ + Union[ + bidding_data_exclusion_service.MutateBiddingDataExclusionsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + bidding_data_exclusion_service.BiddingDataExclusionOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> bidding_data_exclusion_service.MutateBiddingDataExclusionsResponse: + r"""Creates, updates, or removes data exclusions. + Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateBiddingDataExclusionsRequest, dict]]): + The request object. Request message for + [BiddingDataExclusionService.MutateBiddingDataExclusions][google.ads.googleads.v24.services.BiddingDataExclusionService.MutateBiddingDataExclusions]. + customer_id (:class:`str`): + Required. ID of the customer whose + data exclusions are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.BiddingDataExclusionOperation]`): + Required. The list of operations to + perform on individual data exclusions. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateBiddingDataExclusionsResponse: + Response message for data exclusions + mutate. + + """ + # 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 = [customer_id, operations] + 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, + bidding_data_exclusion_service.MutateBiddingDataExclusionsRequest, + ): + request = bidding_data_exclusion_service.MutateBiddingDataExclusionsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_bidding_data_exclusions + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "BiddingDataExclusionServiceAsyncClient": + 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__ = ("BiddingDataExclusionServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/client.py b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/client.py new file mode 100644 index 000000000..18d57be0d --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/client.py @@ -0,0 +1,936 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + bidding_data_exclusion_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + BiddingDataExclusionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import BiddingDataExclusionServiceGrpcTransport +from .transports.grpc_asyncio import ( + BiddingDataExclusionServiceGrpcAsyncIOTransport, +) + + +class BiddingDataExclusionServiceClientMeta(type): + """Metaclass for the BiddingDataExclusionService 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[BiddingDataExclusionServiceTransport]] + _transport_registry["grpc"] = BiddingDataExclusionServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + BiddingDataExclusionServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[BiddingDataExclusionServiceTransport]: + """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 BiddingDataExclusionServiceClient( + metaclass=BiddingDataExclusionServiceClientMeta +): + """Service to manage bidding data exclusions.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + BiddingDataExclusionServiceClient: 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: + BiddingDataExclusionServiceClient: 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) -> BiddingDataExclusionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + BiddingDataExclusionServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def bidding_data_exclusion_path( + customer_id: str, + seasonality_event_id: str, + ) -> str: + """Returns a fully-qualified bidding_data_exclusion string.""" + return "customers/{customer_id}/biddingDataExclusions/{seasonality_event_id}".format( + customer_id=customer_id, + seasonality_event_id=seasonality_event_id, + ) + + @staticmethod + def parse_bidding_data_exclusion_path(path: str) -> Dict[str, str]: + """Parses a bidding_data_exclusion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/biddingDataExclusions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?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 = ( + BiddingDataExclusionServiceClient._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 = ( + BiddingDataExclusionServiceClient._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 + ): + """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 = ( + BiddingDataExclusionServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + BiddingDataExclusionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = BiddingDataExclusionServiceClient._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 = BiddingDataExclusionServiceClient._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): + """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, + BiddingDataExclusionServiceTransport, + Callable[..., BiddingDataExclusionServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the bidding data exclusion 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,BiddingDataExclusionServiceTransport,Callable[..., BiddingDataExclusionServiceTransport]]]): + 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 BiddingDataExclusionServiceTransport 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, + ) = BiddingDataExclusionServiceClient._read_environment_variables() + self._client_cert_source = ( + BiddingDataExclusionServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + BiddingDataExclusionServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, BiddingDataExclusionServiceTransport + ) + if transport_provided: + # transport is a BiddingDataExclusionServiceTransport 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( + BiddingDataExclusionServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or BiddingDataExclusionServiceClient._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[BiddingDataExclusionServiceTransport], + Callable[..., BiddingDataExclusionServiceTransport], + ] = ( + BiddingDataExclusionServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., BiddingDataExclusionServiceTransport], + 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.ads.googleads.v24.services.BiddingDataExclusionServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.BiddingDataExclusionService", + "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.ads.googleads.v24.services.BiddingDataExclusionService", + "credentialsType": None, + } + ), + ) + + def mutate_bidding_data_exclusions( + self, + request: Optional[ + Union[ + bidding_data_exclusion_service.MutateBiddingDataExclusionsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + bidding_data_exclusion_service.BiddingDataExclusionOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> bidding_data_exclusion_service.MutateBiddingDataExclusionsResponse: + r"""Creates, updates, or removes data exclusions. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateBiddingDataExclusionsRequest, dict]): + The request object. Request message for + [BiddingDataExclusionService.MutateBiddingDataExclusions][google.ads.googleads.v24.services.BiddingDataExclusionService.MutateBiddingDataExclusions]. + customer_id (str): + Required. ID of the customer whose + data exclusions are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.BiddingDataExclusionOperation]): + Required. The list of operations to + perform on individual data exclusions. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateBiddingDataExclusionsResponse: + Response message for data exclusions + mutate. + + """ + # 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 = [customer_id, operations] + 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, + bidding_data_exclusion_service.MutateBiddingDataExclusionsRequest, + ): + request = bidding_data_exclusion_service.MutateBiddingDataExclusionsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_bidding_data_exclusions + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "BiddingDataExclusionServiceClient": + 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() + + +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__ = ("BiddingDataExclusionServiceClient",) diff --git a/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/README.rst b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/README.rst new file mode 100644 index 000000000..7d8b33211 --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`BiddingDataExclusionServiceTransport` is the ABC for all transports. +- public child `BiddingDataExclusionServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `BiddingDataExclusionServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseBiddingDataExclusionServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `BiddingDataExclusionServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/__init__.py b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/__init__.py new file mode 100644 index 000000000..2f2f60ead --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import BiddingDataExclusionServiceTransport +from .grpc import BiddingDataExclusionServiceGrpcTransport +from .grpc_asyncio import BiddingDataExclusionServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[BiddingDataExclusionServiceTransport]] +_transport_registry["grpc"] = BiddingDataExclusionServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + BiddingDataExclusionServiceGrpcAsyncIOTransport +) + +__all__ = ( + "BiddingDataExclusionServiceTransport", + "BiddingDataExclusionServiceGrpcTransport", + "BiddingDataExclusionServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/base.py b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/base.py new file mode 100644 index 000000000..e60d15f24 --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + bidding_data_exclusion_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 BiddingDataExclusionServiceTransport(abc.ABC): + """Abstract transport class for BiddingDataExclusionService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_bidding_data_exclusions: gapic_v1.method.wrap_method( + self.mutate_bidding_data_exclusions, + 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 mutate_bidding_data_exclusions( + self, + ) -> Callable[ + [bidding_data_exclusion_service.MutateBiddingDataExclusionsRequest], + Union[ + bidding_data_exclusion_service.MutateBiddingDataExclusionsResponse, + Awaitable[ + bidding_data_exclusion_service.MutateBiddingDataExclusionsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("BiddingDataExclusionServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/grpc.py b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/grpc.py new file mode 100644 index 000000000..0dd23c381 --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/grpc.py @@ -0,0 +1,388 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + bidding_data_exclusion_service, +) +from .base import BiddingDataExclusionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.BiddingDataExclusionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.BiddingDataExclusionService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class BiddingDataExclusionServiceGrpcTransport( + BiddingDataExclusionServiceTransport +): + """gRPC backend transport for BiddingDataExclusionService. + + Service to manage bidding data exclusions. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_bidding_data_exclusions( + self, + ) -> Callable[ + [bidding_data_exclusion_service.MutateBiddingDataExclusionsRequest], + bidding_data_exclusion_service.MutateBiddingDataExclusionsResponse, + ]: + r"""Return a callable for the mutate bidding data exclusions method over gRPC. + + Creates, updates, or removes data exclusions. + Operation statuses are returned. + + Returns: + Callable[[~.MutateBiddingDataExclusionsRequest], + ~.MutateBiddingDataExclusionsResponse]: + 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 "mutate_bidding_data_exclusions" not in self._stubs: + self._stubs["mutate_bidding_data_exclusions"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BiddingDataExclusionService/MutateBiddingDataExclusions", + request_serializer=bidding_data_exclusion_service.MutateBiddingDataExclusionsRequest.serialize, + response_deserializer=bidding_data_exclusion_service.MutateBiddingDataExclusionsResponse.deserialize, + ) + ) + return self._stubs["mutate_bidding_data_exclusions"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("BiddingDataExclusionServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..78c0489d9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_data_exclusion_service/transports/grpc_asyncio.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + bidding_data_exclusion_service, +) +from .base import BiddingDataExclusionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.BiddingDataExclusionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.BiddingDataExclusionService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class BiddingDataExclusionServiceGrpcAsyncIOTransport( + BiddingDataExclusionServiceTransport +): + """gRPC AsyncIO backend transport for BiddingDataExclusionService. + + Service to manage bidding data exclusions. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_bidding_data_exclusions( + self, + ) -> Callable[ + [bidding_data_exclusion_service.MutateBiddingDataExclusionsRequest], + Awaitable[ + bidding_data_exclusion_service.MutateBiddingDataExclusionsResponse + ], + ]: + r"""Return a callable for the mutate bidding data exclusions method over gRPC. + + Creates, updates, or removes data exclusions. + Operation statuses are returned. + + Returns: + Callable[[~.MutateBiddingDataExclusionsRequest], + Awaitable[~.MutateBiddingDataExclusionsResponse]]: + 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 "mutate_bidding_data_exclusions" not in self._stubs: + self._stubs["mutate_bidding_data_exclusions"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BiddingDataExclusionService/MutateBiddingDataExclusions", + request_serializer=bidding_data_exclusion_service.MutateBiddingDataExclusionsRequest.serialize, + response_deserializer=bidding_data_exclusion_service.MutateBiddingDataExclusionsResponse.deserialize, + ) + ) + return self._stubs["mutate_bidding_data_exclusions"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_bidding_data_exclusions: self._wrap_method( + self.mutate_bidding_data_exclusions, + 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" + + +__all__ = ("BiddingDataExclusionServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/__init__.py b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/__init__.py new file mode 100644 index 000000000..264778747 --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import BiddingSeasonalityAdjustmentServiceClient +from .async_client import BiddingSeasonalityAdjustmentServiceAsyncClient + +__all__ = ( + "BiddingSeasonalityAdjustmentServiceClient", + "BiddingSeasonalityAdjustmentServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/async_client.py b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/async_client.py new file mode 100644 index 000000000..3fa036b41 --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/async_client.py @@ -0,0 +1,451 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + bidding_seasonality_adjustment_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + BiddingSeasonalityAdjustmentServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import BiddingSeasonalityAdjustmentServiceClient + +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 BiddingSeasonalityAdjustmentServiceAsyncClient: + """Service to manage bidding seasonality adjustments.""" + + _client: BiddingSeasonalityAdjustmentServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ( + BiddingSeasonalityAdjustmentServiceClient.DEFAULT_ENDPOINT + ) + DEFAULT_MTLS_ENDPOINT = ( + BiddingSeasonalityAdjustmentServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + BiddingSeasonalityAdjustmentServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ( + BiddingSeasonalityAdjustmentServiceClient._DEFAULT_UNIVERSE + ) + + bidding_seasonality_adjustment_path = staticmethod( + BiddingSeasonalityAdjustmentServiceClient.bidding_seasonality_adjustment_path + ) + parse_bidding_seasonality_adjustment_path = staticmethod( + BiddingSeasonalityAdjustmentServiceClient.parse_bidding_seasonality_adjustment_path + ) + campaign_path = staticmethod( + BiddingSeasonalityAdjustmentServiceClient.campaign_path + ) + parse_campaign_path = staticmethod( + BiddingSeasonalityAdjustmentServiceClient.parse_campaign_path + ) + common_billing_account_path = staticmethod( + BiddingSeasonalityAdjustmentServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + BiddingSeasonalityAdjustmentServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + BiddingSeasonalityAdjustmentServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + BiddingSeasonalityAdjustmentServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + BiddingSeasonalityAdjustmentServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + BiddingSeasonalityAdjustmentServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + BiddingSeasonalityAdjustmentServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + BiddingSeasonalityAdjustmentServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + BiddingSeasonalityAdjustmentServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + BiddingSeasonalityAdjustmentServiceClient.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: + BiddingSeasonalityAdjustmentServiceAsyncClient: The constructed client. + """ + return BiddingSeasonalityAdjustmentServiceClient.from_service_account_info.__func__(BiddingSeasonalityAdjustmentServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + BiddingSeasonalityAdjustmentServiceAsyncClient: The constructed client. + """ + return BiddingSeasonalityAdjustmentServiceClient.from_service_account_file.__func__(BiddingSeasonalityAdjustmentServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return BiddingSeasonalityAdjustmentServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> BiddingSeasonalityAdjustmentServiceTransport: + """Returns the transport used by the client instance. + + Returns: + BiddingSeasonalityAdjustmentServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + BiddingSeasonalityAdjustmentServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + BiddingSeasonalityAdjustmentServiceTransport, + Callable[..., BiddingSeasonalityAdjustmentServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the bidding seasonality adjustment 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,BiddingSeasonalityAdjustmentServiceTransport,Callable[..., BiddingSeasonalityAdjustmentServiceTransport]]]): + 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 BiddingSeasonalityAdjustmentServiceTransport 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 = BiddingSeasonalityAdjustmentServiceClient( + 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.ads.googleads.v24.services.BiddingSeasonalityAdjustmentServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.BiddingSeasonalityAdjustmentService", + "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.ads.googleads.v24.services.BiddingSeasonalityAdjustmentService", + "credentialsType": None, + } + ), + ) + + async def mutate_bidding_seasonality_adjustments( + self, + request: Optional[ + Union[ + bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + bidding_seasonality_adjustment_service.BiddingSeasonalityAdjustmentOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsResponse + ): + r"""Creates, updates, or removes seasonality adjustments. + Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateBiddingSeasonalityAdjustmentsRequest, dict]]): + The request object. Request message for + [BiddingSeasonalityAdjustmentService.MutateBiddingSeasonalityAdjustments][google.ads.googleads.v24.services.BiddingSeasonalityAdjustmentService.MutateBiddingSeasonalityAdjustments]. + customer_id (:class:`str`): + Required. ID of the customer whose + seasonality adjustments are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.BiddingSeasonalityAdjustmentOperation]`): + Required. The list of operations to + perform on individual seasonality + adjustments. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateBiddingSeasonalityAdjustmentsResponse: + Response message for seasonality + adjustments mutate. + + """ + # 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 = [customer_id, operations] + 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, + bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsRequest, + ): + request = bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_bidding_seasonality_adjustments + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__( + self, + ) -> "BiddingSeasonalityAdjustmentServiceAsyncClient": + 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__ = ("BiddingSeasonalityAdjustmentServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/client.py b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/client.py new file mode 100644 index 000000000..256cdae1b --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/client.py @@ -0,0 +1,948 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + bidding_seasonality_adjustment_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + BiddingSeasonalityAdjustmentServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import BiddingSeasonalityAdjustmentServiceGrpcTransport +from .transports.grpc_asyncio import ( + BiddingSeasonalityAdjustmentServiceGrpcAsyncIOTransport, +) + + +class BiddingSeasonalityAdjustmentServiceClientMeta(type): + """Metaclass for the BiddingSeasonalityAdjustmentService 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[BiddingSeasonalityAdjustmentServiceTransport]] + _transport_registry["grpc"] = ( + BiddingSeasonalityAdjustmentServiceGrpcTransport + ) + _transport_registry["grpc_asyncio"] = ( + BiddingSeasonalityAdjustmentServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[BiddingSeasonalityAdjustmentServiceTransport]: + """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 BiddingSeasonalityAdjustmentServiceClient( + metaclass=BiddingSeasonalityAdjustmentServiceClientMeta +): + """Service to manage bidding seasonality adjustments.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + BiddingSeasonalityAdjustmentServiceClient: 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: + BiddingSeasonalityAdjustmentServiceClient: 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) -> BiddingSeasonalityAdjustmentServiceTransport: + """Returns the transport used by the client instance. + + Returns: + BiddingSeasonalityAdjustmentServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def bidding_seasonality_adjustment_path( + customer_id: str, + seasonality_event_id: str, + ) -> str: + """Returns a fully-qualified bidding_seasonality_adjustment string.""" + return "customers/{customer_id}/biddingSeasonalityAdjustments/{seasonality_event_id}".format( + customer_id=customer_id, + seasonality_event_id=seasonality_event_id, + ) + + @staticmethod + def parse_bidding_seasonality_adjustment_path(path: str) -> Dict[str, str]: + """Parses a bidding_seasonality_adjustment path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/biddingSeasonalityAdjustments/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?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 = ( + BiddingSeasonalityAdjustmentServiceClient._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 = ( + BiddingSeasonalityAdjustmentServiceClient._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 + ): + """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 = ( + BiddingSeasonalityAdjustmentServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + BiddingSeasonalityAdjustmentServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = BiddingSeasonalityAdjustmentServiceClient._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 = ( + BiddingSeasonalityAdjustmentServiceClient._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): + """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, + BiddingSeasonalityAdjustmentServiceTransport, + Callable[..., BiddingSeasonalityAdjustmentServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the bidding seasonality adjustment 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,BiddingSeasonalityAdjustmentServiceTransport,Callable[..., BiddingSeasonalityAdjustmentServiceTransport]]]): + 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 BiddingSeasonalityAdjustmentServiceTransport 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, + ) = ( + BiddingSeasonalityAdjustmentServiceClient._read_environment_variables() + ) + self._client_cert_source = ( + BiddingSeasonalityAdjustmentServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + BiddingSeasonalityAdjustmentServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, BiddingSeasonalityAdjustmentServiceTransport + ) + if transport_provided: + # transport is a BiddingSeasonalityAdjustmentServiceTransport 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( + BiddingSeasonalityAdjustmentServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or BiddingSeasonalityAdjustmentServiceClient._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[BiddingSeasonalityAdjustmentServiceTransport], + Callable[..., BiddingSeasonalityAdjustmentServiceTransport], + ] = ( + BiddingSeasonalityAdjustmentServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., BiddingSeasonalityAdjustmentServiceTransport], + 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.ads.googleads.v24.services.BiddingSeasonalityAdjustmentServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.BiddingSeasonalityAdjustmentService", + "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.ads.googleads.v24.services.BiddingSeasonalityAdjustmentService", + "credentialsType": None, + } + ), + ) + + def mutate_bidding_seasonality_adjustments( + self, + request: Optional[ + Union[ + bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + bidding_seasonality_adjustment_service.BiddingSeasonalityAdjustmentOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsResponse + ): + r"""Creates, updates, or removes seasonality adjustments. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateBiddingSeasonalityAdjustmentsRequest, dict]): + The request object. Request message for + [BiddingSeasonalityAdjustmentService.MutateBiddingSeasonalityAdjustments][google.ads.googleads.v24.services.BiddingSeasonalityAdjustmentService.MutateBiddingSeasonalityAdjustments]. + customer_id (str): + Required. ID of the customer whose + seasonality adjustments are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.BiddingSeasonalityAdjustmentOperation]): + Required. The list of operations to + perform on individual seasonality + adjustments. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateBiddingSeasonalityAdjustmentsResponse: + Response message for seasonality + adjustments mutate. + + """ + # 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 = [customer_id, operations] + 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, + bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsRequest, + ): + request = bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_bidding_seasonality_adjustments + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "BiddingSeasonalityAdjustmentServiceClient": + 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() + + +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__ = ("BiddingSeasonalityAdjustmentServiceClient",) diff --git a/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/README.rst b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/README.rst new file mode 100644 index 000000000..7797ced1e --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`BiddingSeasonalityAdjustmentServiceTransport` is the ABC for all transports. +- public child `BiddingSeasonalityAdjustmentServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `BiddingSeasonalityAdjustmentServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseBiddingSeasonalityAdjustmentServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `BiddingSeasonalityAdjustmentServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/__init__.py b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/__init__.py new file mode 100644 index 000000000..00f9b153a --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/__init__.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import BiddingSeasonalityAdjustmentServiceTransport +from .grpc import BiddingSeasonalityAdjustmentServiceGrpcTransport +from .grpc_asyncio import ( + BiddingSeasonalityAdjustmentServiceGrpcAsyncIOTransport, +) + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[BiddingSeasonalityAdjustmentServiceTransport]] +_transport_registry["grpc"] = BiddingSeasonalityAdjustmentServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + BiddingSeasonalityAdjustmentServiceGrpcAsyncIOTransport +) + +__all__ = ( + "BiddingSeasonalityAdjustmentServiceTransport", + "BiddingSeasonalityAdjustmentServiceGrpcTransport", + "BiddingSeasonalityAdjustmentServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/base.py b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/base.py new file mode 100644 index 000000000..4307d3a97 --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + bidding_seasonality_adjustment_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 BiddingSeasonalityAdjustmentServiceTransport(abc.ABC): + """Abstract transport class for BiddingSeasonalityAdjustmentService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_bidding_seasonality_adjustments: gapic_v1.method.wrap_method( + self.mutate_bidding_seasonality_adjustments, + 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 mutate_bidding_seasonality_adjustments( + self, + ) -> Callable[ + [ + bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsRequest + ], + Union[ + bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsResponse, + Awaitable[ + bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("BiddingSeasonalityAdjustmentServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/grpc.py b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/grpc.py new file mode 100644 index 000000000..620e22d5e --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/grpc.py @@ -0,0 +1,394 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + bidding_seasonality_adjustment_service, +) +from .base import ( + BiddingSeasonalityAdjustmentServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.BiddingSeasonalityAdjustmentService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.BiddingSeasonalityAdjustmentService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class BiddingSeasonalityAdjustmentServiceGrpcTransport( + BiddingSeasonalityAdjustmentServiceTransport +): + """gRPC backend transport for BiddingSeasonalityAdjustmentService. + + Service to manage bidding seasonality adjustments. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_bidding_seasonality_adjustments( + self, + ) -> Callable[ + [ + bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsRequest + ], + bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsResponse, + ]: + r"""Return a callable for the mutate bidding seasonality + adjustments method over gRPC. + + Creates, updates, or removes seasonality adjustments. + Operation statuses are returned. + + Returns: + Callable[[~.MutateBiddingSeasonalityAdjustmentsRequest], + ~.MutateBiddingSeasonalityAdjustmentsResponse]: + 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 "mutate_bidding_seasonality_adjustments" not in self._stubs: + self._stubs["mutate_bidding_seasonality_adjustments"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BiddingSeasonalityAdjustmentService/MutateBiddingSeasonalityAdjustments", + request_serializer=bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsRequest.serialize, + response_deserializer=bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsResponse.deserialize, + ) + ) + return self._stubs["mutate_bidding_seasonality_adjustments"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("BiddingSeasonalityAdjustmentServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..c2d67e153 --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_seasonality_adjustment_service/transports/grpc_asyncio.py @@ -0,0 +1,417 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + bidding_seasonality_adjustment_service, +) +from .base import ( + BiddingSeasonalityAdjustmentServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.BiddingSeasonalityAdjustmentService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.BiddingSeasonalityAdjustmentService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class BiddingSeasonalityAdjustmentServiceGrpcAsyncIOTransport( + BiddingSeasonalityAdjustmentServiceTransport +): + """gRPC AsyncIO backend transport for BiddingSeasonalityAdjustmentService. + + Service to manage bidding seasonality adjustments. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_bidding_seasonality_adjustments( + self, + ) -> Callable[ + [ + bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsRequest + ], + Awaitable[ + bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsResponse + ], + ]: + r"""Return a callable for the mutate bidding seasonality + adjustments method over gRPC. + + Creates, updates, or removes seasonality adjustments. + Operation statuses are returned. + + Returns: + Callable[[~.MutateBiddingSeasonalityAdjustmentsRequest], + Awaitable[~.MutateBiddingSeasonalityAdjustmentsResponse]]: + 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 "mutate_bidding_seasonality_adjustments" not in self._stubs: + self._stubs["mutate_bidding_seasonality_adjustments"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BiddingSeasonalityAdjustmentService/MutateBiddingSeasonalityAdjustments", + request_serializer=bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsRequest.serialize, + response_deserializer=bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsResponse.deserialize, + ) + ) + return self._stubs["mutate_bidding_seasonality_adjustments"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_bidding_seasonality_adjustments: self._wrap_method( + self.mutate_bidding_seasonality_adjustments, + 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" + + +__all__ = ("BiddingSeasonalityAdjustmentServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/bidding_strategy_service/__init__.py b/google/ads/googleads/v24/services/services/bidding_strategy_service/__init__.py new file mode 100644 index 000000000..bdbde8562 --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_strategy_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import BiddingStrategyServiceClient +from .async_client import BiddingStrategyServiceAsyncClient + +__all__ = ( + "BiddingStrategyServiceClient", + "BiddingStrategyServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/bidding_strategy_service/async_client.py b/google/ads/googleads/v24/services/services/bidding_strategy_service/async_client.py new file mode 100644 index 000000000..4885f399e --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_strategy_service/async_client.py @@ -0,0 +1,438 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import bidding_strategy_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + BiddingStrategyServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import BiddingStrategyServiceClient + +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 BiddingStrategyServiceAsyncClient: + """Service to manage bidding strategies.""" + + _client: BiddingStrategyServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = BiddingStrategyServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = BiddingStrategyServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + BiddingStrategyServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = BiddingStrategyServiceClient._DEFAULT_UNIVERSE + + bidding_strategy_path = staticmethod( + BiddingStrategyServiceClient.bidding_strategy_path + ) + parse_bidding_strategy_path = staticmethod( + BiddingStrategyServiceClient.parse_bidding_strategy_path + ) + common_billing_account_path = staticmethod( + BiddingStrategyServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + BiddingStrategyServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + BiddingStrategyServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + BiddingStrategyServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + BiddingStrategyServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + BiddingStrategyServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + BiddingStrategyServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + BiddingStrategyServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + BiddingStrategyServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + BiddingStrategyServiceClient.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: + BiddingStrategyServiceAsyncClient: The constructed client. + """ + return BiddingStrategyServiceClient.from_service_account_info.__func__(BiddingStrategyServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + BiddingStrategyServiceAsyncClient: The constructed client. + """ + return BiddingStrategyServiceClient.from_service_account_file.__func__(BiddingStrategyServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return BiddingStrategyServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> BiddingStrategyServiceTransport: + """Returns the transport used by the client instance. + + Returns: + BiddingStrategyServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = BiddingStrategyServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + BiddingStrategyServiceTransport, + Callable[..., BiddingStrategyServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the bidding strategy 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,BiddingStrategyServiceTransport,Callable[..., BiddingStrategyServiceTransport]]]): + 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 BiddingStrategyServiceTransport 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 = BiddingStrategyServiceClient( + 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.ads.googleads.v24.services.BiddingStrategyServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.BiddingStrategyService", + "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.ads.googleads.v24.services.BiddingStrategyService", + "credentialsType": None, + } + ), + ) + + async def mutate_bidding_strategies( + self, + request: Optional[ + Union[bidding_strategy_service.MutateBiddingStrategiesRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[bidding_strategy_service.BiddingStrategyOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> bidding_strategy_service.MutateBiddingStrategiesResponse: + r"""Creates, updates, or removes bidding strategies. Operation + statuses are returned. + + List of thrown errors: `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `BiddingError <>`__ `BiddingStrategyError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateBiddingStrategiesRequest, dict]]): + The request object. Request message for + [BiddingStrategyService.MutateBiddingStrategies][google.ads.googleads.v24.services.BiddingStrategyService.MutateBiddingStrategies]. + customer_id (:class:`str`): + Required. The ID of the customer + whose bidding strategies are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.BiddingStrategyOperation]`): + Required. The list of operations to + perform on individual bidding + strategies. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateBiddingStrategiesResponse: + Response message for bidding strategy + mutate. + + """ + # 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 = [customer_id, operations] + 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, bidding_strategy_service.MutateBiddingStrategiesRequest + ): + request = bidding_strategy_service.MutateBiddingStrategiesRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_bidding_strategies + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "BiddingStrategyServiceAsyncClient": + 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__ = ("BiddingStrategyServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/bidding_strategy_service/client.py b/google/ads/googleads/v24/services/services/bidding_strategy_service/client.py new file mode 100644 index 000000000..2111d8838 --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_strategy_service/client.py @@ -0,0 +1,914 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import bidding_strategy_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + BiddingStrategyServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import BiddingStrategyServiceGrpcTransport +from .transports.grpc_asyncio import BiddingStrategyServiceGrpcAsyncIOTransport + + +class BiddingStrategyServiceClientMeta(type): + """Metaclass for the BiddingStrategyService 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[BiddingStrategyServiceTransport]] + _transport_registry["grpc"] = BiddingStrategyServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + BiddingStrategyServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[BiddingStrategyServiceTransport]: + """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 BiddingStrategyServiceClient(metaclass=BiddingStrategyServiceClientMeta): + """Service to manage bidding strategies.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + BiddingStrategyServiceClient: 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: + BiddingStrategyServiceClient: 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) -> BiddingStrategyServiceTransport: + """Returns the transport used by the client instance. + + Returns: + BiddingStrategyServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def bidding_strategy_path( + customer_id: str, + bidding_strategy_id: str, + ) -> str: + """Returns a fully-qualified bidding_strategy string.""" + return "customers/{customer_id}/biddingStrategies/{bidding_strategy_id}".format( + customer_id=customer_id, + bidding_strategy_id=bidding_strategy_id, + ) + + @staticmethod + def parse_bidding_strategy_path(path: str) -> Dict[str, str]: + """Parses a bidding_strategy path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/biddingStrategies/(?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 = ( + BiddingStrategyServiceClient._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 = ( + BiddingStrategyServiceClient._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 + ): + """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 = BiddingStrategyServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = BiddingStrategyServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + BiddingStrategyServiceClient._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 = BiddingStrategyServiceClient._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): + """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, + BiddingStrategyServiceTransport, + Callable[..., BiddingStrategyServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the bidding strategy 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,BiddingStrategyServiceTransport,Callable[..., BiddingStrategyServiceTransport]]]): + 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 BiddingStrategyServiceTransport 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, + ) = BiddingStrategyServiceClient._read_environment_variables() + self._client_cert_source = ( + BiddingStrategyServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + BiddingStrategyServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, BiddingStrategyServiceTransport + ) + if transport_provided: + # transport is a BiddingStrategyServiceTransport 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(BiddingStrategyServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or BiddingStrategyServiceClient._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[BiddingStrategyServiceTransport], + Callable[..., BiddingStrategyServiceTransport], + ] = ( + BiddingStrategyServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., BiddingStrategyServiceTransport], 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.ads.googleads.v24.services.BiddingStrategyServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.BiddingStrategyService", + "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.ads.googleads.v24.services.BiddingStrategyService", + "credentialsType": None, + } + ), + ) + + def mutate_bidding_strategies( + self, + request: Optional[ + Union[bidding_strategy_service.MutateBiddingStrategiesRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[bidding_strategy_service.BiddingStrategyOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> bidding_strategy_service.MutateBiddingStrategiesResponse: + r"""Creates, updates, or removes bidding strategies. Operation + statuses are returned. + + List of thrown errors: `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `BiddingError <>`__ `BiddingStrategyError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateBiddingStrategiesRequest, dict]): + The request object. Request message for + [BiddingStrategyService.MutateBiddingStrategies][google.ads.googleads.v24.services.BiddingStrategyService.MutateBiddingStrategies]. + customer_id (str): + Required. The ID of the customer + whose bidding strategies are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.BiddingStrategyOperation]): + Required. The list of operations to + perform on individual bidding + strategies. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateBiddingStrategiesResponse: + Response message for bidding strategy + mutate. + + """ + # 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 = [customer_id, operations] + 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, bidding_strategy_service.MutateBiddingStrategiesRequest + ): + request = bidding_strategy_service.MutateBiddingStrategiesRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_bidding_strategies + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "BiddingStrategyServiceClient": + 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() + + +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__ = ("BiddingStrategyServiceClient",) diff --git a/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/README.rst b/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/README.rst new file mode 100644 index 000000000..275499aab --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`BiddingStrategyServiceTransport` is the ABC for all transports. +- public child `BiddingStrategyServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `BiddingStrategyServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseBiddingStrategyServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `BiddingStrategyServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/__init__.py b/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/__init__.py new file mode 100644 index 000000000..755922538 --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import BiddingStrategyServiceTransport +from .grpc import BiddingStrategyServiceGrpcTransport +from .grpc_asyncio import BiddingStrategyServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[BiddingStrategyServiceTransport]] +_transport_registry["grpc"] = BiddingStrategyServiceGrpcTransport +_transport_registry["grpc_asyncio"] = BiddingStrategyServiceGrpcAsyncIOTransport + +__all__ = ( + "BiddingStrategyServiceTransport", + "BiddingStrategyServiceGrpcTransport", + "BiddingStrategyServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/base.py b/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/base.py new file mode 100644 index 000000000..642161d86 --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import bidding_strategy_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 BiddingStrategyServiceTransport(abc.ABC): + """Abstract transport class for BiddingStrategyService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_bidding_strategies: gapic_v1.method.wrap_method( + self.mutate_bidding_strategies, + 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 mutate_bidding_strategies( + self, + ) -> Callable[ + [bidding_strategy_service.MutateBiddingStrategiesRequest], + Union[ + bidding_strategy_service.MutateBiddingStrategiesResponse, + Awaitable[bidding_strategy_service.MutateBiddingStrategiesResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("BiddingStrategyServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/grpc.py b/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/grpc.py new file mode 100644 index 000000000..9ad708bbf --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/grpc.py @@ -0,0 +1,397 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import bidding_strategy_service +from .base import BiddingStrategyServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.BiddingStrategyService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.BiddingStrategyService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class BiddingStrategyServiceGrpcTransport(BiddingStrategyServiceTransport): + """gRPC backend transport for BiddingStrategyService. + + Service to manage bidding strategies. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_bidding_strategies( + self, + ) -> Callable[ + [bidding_strategy_service.MutateBiddingStrategiesRequest], + bidding_strategy_service.MutateBiddingStrategiesResponse, + ]: + r"""Return a callable for the mutate bidding strategies method over gRPC. + + Creates, updates, or removes bidding strategies. Operation + statuses are returned. + + List of thrown errors: `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `BiddingError <>`__ `BiddingStrategyError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Returns: + Callable[[~.MutateBiddingStrategiesRequest], + ~.MutateBiddingStrategiesResponse]: + 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 "mutate_bidding_strategies" not in self._stubs: + self._stubs["mutate_bidding_strategies"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BiddingStrategyService/MutateBiddingStrategies", + request_serializer=bidding_strategy_service.MutateBiddingStrategiesRequest.serialize, + response_deserializer=bidding_strategy_service.MutateBiddingStrategiesResponse.deserialize, + ) + ) + return self._stubs["mutate_bidding_strategies"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("BiddingStrategyServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..bb2540d1f --- /dev/null +++ b/google/ads/googleads/v24/services/services/bidding_strategy_service/transports/grpc_asyncio.py @@ -0,0 +1,420 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import bidding_strategy_service +from .base import BiddingStrategyServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.BiddingStrategyService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.BiddingStrategyService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class BiddingStrategyServiceGrpcAsyncIOTransport( + BiddingStrategyServiceTransport +): + """gRPC AsyncIO backend transport for BiddingStrategyService. + + Service to manage bidding strategies. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_bidding_strategies( + self, + ) -> Callable[ + [bidding_strategy_service.MutateBiddingStrategiesRequest], + Awaitable[bidding_strategy_service.MutateBiddingStrategiesResponse], + ]: + r"""Return a callable for the mutate bidding strategies method over gRPC. + + Creates, updates, or removes bidding strategies. Operation + statuses are returned. + + List of thrown errors: `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `BiddingError <>`__ `BiddingStrategyError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Returns: + Callable[[~.MutateBiddingStrategiesRequest], + Awaitable[~.MutateBiddingStrategiesResponse]]: + 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 "mutate_bidding_strategies" not in self._stubs: + self._stubs["mutate_bidding_strategies"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BiddingStrategyService/MutateBiddingStrategies", + request_serializer=bidding_strategy_service.MutateBiddingStrategiesRequest.serialize, + response_deserializer=bidding_strategy_service.MutateBiddingStrategiesResponse.deserialize, + ) + ) + return self._stubs["mutate_bidding_strategies"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_bidding_strategies: self._wrap_method( + self.mutate_bidding_strategies, + 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" + + +__all__ = ("BiddingStrategyServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/billing_setup_service/__init__.py b/google/ads/googleads/v24/services/services/billing_setup_service/__init__.py new file mode 100644 index 000000000..ea44df7fa --- /dev/null +++ b/google/ads/googleads/v24/services/services/billing_setup_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import BillingSetupServiceClient +from .async_client import BillingSetupServiceAsyncClient + +__all__ = ( + "BillingSetupServiceClient", + "BillingSetupServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/billing_setup_service/async_client.py b/google/ads/googleads/v24/services/services/billing_setup_service/async_client.py new file mode 100644 index 000000000..cc35d65c4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/billing_setup_service/async_client.py @@ -0,0 +1,435 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import billing_setup_service +from .transports.base import BillingSetupServiceTransport, DEFAULT_CLIENT_INFO +from .client import BillingSetupServiceClient + +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 BillingSetupServiceAsyncClient: + """A service for designating the business entity responsible for + accrued costs. + A billing setup is associated with a payments account. + Billing-related activity for all billing setups associated with + a particular payments account will appear on a single invoice + generated monthly. + + Mutates: + + The REMOVE operation cancels a pending billing setup. The CREATE + operation creates a new billing setup. + """ + + _client: BillingSetupServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = BillingSetupServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = BillingSetupServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + BillingSetupServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = BillingSetupServiceClient._DEFAULT_UNIVERSE + + billing_setup_path = staticmethod( + BillingSetupServiceClient.billing_setup_path + ) + parse_billing_setup_path = staticmethod( + BillingSetupServiceClient.parse_billing_setup_path + ) + payments_account_path = staticmethod( + BillingSetupServiceClient.payments_account_path + ) + parse_payments_account_path = staticmethod( + BillingSetupServiceClient.parse_payments_account_path + ) + common_billing_account_path = staticmethod( + BillingSetupServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + BillingSetupServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + BillingSetupServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + BillingSetupServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + BillingSetupServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + BillingSetupServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + BillingSetupServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + BillingSetupServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + BillingSetupServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + BillingSetupServiceClient.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: + BillingSetupServiceAsyncClient: The constructed client. + """ + return BillingSetupServiceClient.from_service_account_info.__func__(BillingSetupServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + BillingSetupServiceAsyncClient: The constructed client. + """ + return BillingSetupServiceClient.from_service_account_file.__func__(BillingSetupServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return BillingSetupServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> BillingSetupServiceTransport: + """Returns the transport used by the client instance. + + Returns: + BillingSetupServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = BillingSetupServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + BillingSetupServiceTransport, + Callable[..., BillingSetupServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the billing setup 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,BillingSetupServiceTransport,Callable[..., BillingSetupServiceTransport]]]): + 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 BillingSetupServiceTransport 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 = BillingSetupServiceClient( + 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.ads.googleads.v24.services.BillingSetupServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.BillingSetupService", + "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.ads.googleads.v24.services.BillingSetupService", + "credentialsType": None, + } + ), + ) + + async def mutate_billing_setup( + self, + request: Optional[ + Union[billing_setup_service.MutateBillingSetupRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[billing_setup_service.BillingSetupOperation] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> billing_setup_service.MutateBillingSetupResponse: + r"""Creates a billing setup, or cancels an existing billing setup. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BillingSetupError <>`__ + `DateError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateBillingSetupRequest, dict]]): + The request object. Request message for billing setup + mutate operations. + customer_id (:class:`str`): + Required. Id of the customer to apply + the billing setup mutate operation to. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (:class:`google.ads.googleads.v24.services.types.BillingSetupOperation`): + Required. The operation to perform. + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateBillingSetupResponse: + Response message for a billing setup + operation. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [customer_id, operation] + 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, billing_setup_service.MutateBillingSetupRequest + ): + request = billing_setup_service.MutateBillingSetupRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_billing_setup + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "BillingSetupServiceAsyncClient": + 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__ = ("BillingSetupServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/billing_setup_service/client.py b/google/ads/googleads/v24/services/services/billing_setup_service/client.py new file mode 100644 index 000000000..c548f7bfb --- /dev/null +++ b/google/ads/googleads/v24/services/services/billing_setup_service/client.py @@ -0,0 +1,909 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import billing_setup_service +from .transports.base import BillingSetupServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import BillingSetupServiceGrpcTransport +from .transports.grpc_asyncio import BillingSetupServiceGrpcAsyncIOTransport + + +class BillingSetupServiceClientMeta(type): + """Metaclass for the BillingSetupService 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[BillingSetupServiceTransport]] + _transport_registry["grpc"] = BillingSetupServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + BillingSetupServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[BillingSetupServiceTransport]: + """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 BillingSetupServiceClient(metaclass=BillingSetupServiceClientMeta): + """A service for designating the business entity responsible for + accrued costs. + A billing setup is associated with a payments account. + Billing-related activity for all billing setups associated with + a particular payments account will appear on a single invoice + generated monthly. + + Mutates: + + The REMOVE operation cancels a pending billing setup. The CREATE + operation creates a new billing setup. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + BillingSetupServiceClient: 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: + BillingSetupServiceClient: 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) -> BillingSetupServiceTransport: + """Returns the transport used by the client instance. + + Returns: + BillingSetupServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def billing_setup_path( + customer_id: str, + billing_setup_id: str, + ) -> str: + """Returns a fully-qualified billing_setup string.""" + return ( + "customers/{customer_id}/billingSetups/{billing_setup_id}".format( + customer_id=customer_id, + billing_setup_id=billing_setup_id, + ) + ) + + @staticmethod + def parse_billing_setup_path(path: str) -> Dict[str, str]: + """Parses a billing_setup path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/billingSetups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def payments_account_path( + customer_id: str, + payments_account_id: str, + ) -> str: + """Returns a fully-qualified payments_account string.""" + return "customers/{customer_id}/paymentsAccounts/{payments_account_id}".format( + customer_id=customer_id, + payments_account_id=payments_account_id, + ) + + @staticmethod + def parse_payments_account_path(path: str) -> Dict[str, str]: + """Parses a payments_account path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/paymentsAccounts/(?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 = BillingSetupServiceClient._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 = BillingSetupServiceClient._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 + ): + """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 = BillingSetupServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = BillingSetupServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + BillingSetupServiceClient._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 = BillingSetupServiceClient._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): + """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, + BillingSetupServiceTransport, + Callable[..., BillingSetupServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the billing setup 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,BillingSetupServiceTransport,Callable[..., BillingSetupServiceTransport]]]): + 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 BillingSetupServiceTransport 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, + ) = BillingSetupServiceClient._read_environment_variables() + self._client_cert_source = ( + BillingSetupServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = BillingSetupServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, BillingSetupServiceTransport) + if transport_provided: + # transport is a BillingSetupServiceTransport 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(BillingSetupServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or BillingSetupServiceClient._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[BillingSetupServiceTransport], + Callable[..., BillingSetupServiceTransport], + ] = ( + BillingSetupServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., BillingSetupServiceTransport], 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.ads.googleads.v24.services.BillingSetupServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.BillingSetupService", + "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.ads.googleads.v24.services.BillingSetupService", + "credentialsType": None, + } + ), + ) + + def mutate_billing_setup( + self, + request: Optional[ + Union[billing_setup_service.MutateBillingSetupRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[billing_setup_service.BillingSetupOperation] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> billing_setup_service.MutateBillingSetupResponse: + r"""Creates a billing setup, or cancels an existing billing setup. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BillingSetupError <>`__ + `DateError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateBillingSetupRequest, dict]): + The request object. Request message for billing setup + mutate operations. + customer_id (str): + Required. Id of the customer to apply + the billing setup mutate operation to. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (google.ads.googleads.v24.services.types.BillingSetupOperation): + Required. The operation to perform. + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateBillingSetupResponse: + Response message for a billing setup + operation. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [customer_id, operation] + 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, billing_setup_service.MutateBillingSetupRequest + ): + request = billing_setup_service.MutateBillingSetupRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_billing_setup + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "BillingSetupServiceClient": + 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() + + +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__ = ("BillingSetupServiceClient",) diff --git a/google/ads/googleads/v24/services/services/billing_setup_service/transports/README.rst b/google/ads/googleads/v24/services/services/billing_setup_service/transports/README.rst new file mode 100644 index 000000000..ae7b312b2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/billing_setup_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`BillingSetupServiceTransport` is the ABC for all transports. +- public child `BillingSetupServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `BillingSetupServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseBillingSetupServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `BillingSetupServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/billing_setup_service/transports/__init__.py b/google/ads/googleads/v24/services/services/billing_setup_service/transports/__init__.py new file mode 100644 index 000000000..18af3904b --- /dev/null +++ b/google/ads/googleads/v24/services/services/billing_setup_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import BillingSetupServiceTransport +from .grpc import BillingSetupServiceGrpcTransport +from .grpc_asyncio import BillingSetupServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[BillingSetupServiceTransport]] +_transport_registry["grpc"] = BillingSetupServiceGrpcTransport +_transport_registry["grpc_asyncio"] = BillingSetupServiceGrpcAsyncIOTransport + +__all__ = ( + "BillingSetupServiceTransport", + "BillingSetupServiceGrpcTransport", + "BillingSetupServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/billing_setup_service/transports/base.py b/google/ads/googleads/v24/services/services/billing_setup_service/transports/base.py new file mode 100644 index 000000000..58a692c4b --- /dev/null +++ b/google/ads/googleads/v24/services/services/billing_setup_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import billing_setup_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 BillingSetupServiceTransport(abc.ABC): + """Abstract transport class for BillingSetupService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_billing_setup: gapic_v1.method.wrap_method( + self.mutate_billing_setup, + 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 mutate_billing_setup( + self, + ) -> Callable[ + [billing_setup_service.MutateBillingSetupRequest], + Union[ + billing_setup_service.MutateBillingSetupResponse, + Awaitable[billing_setup_service.MutateBillingSetupResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("BillingSetupServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/billing_setup_service/transports/grpc.py b/google/ads/googleads/v24/services/services/billing_setup_service/transports/grpc.py new file mode 100644 index 000000000..4c2804205 --- /dev/null +++ b/google/ads/googleads/v24/services/services/billing_setup_service/transports/grpc.py @@ -0,0 +1,399 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import billing_setup_service +from .base import BillingSetupServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.BillingSetupService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.BillingSetupService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class BillingSetupServiceGrpcTransport(BillingSetupServiceTransport): + """gRPC backend transport for BillingSetupService. + + A service for designating the business entity responsible for + accrued costs. + A billing setup is associated with a payments account. + Billing-related activity for all billing setups associated with + a particular payments account will appear on a single invoice + generated monthly. + + Mutates: + + The REMOVE operation cancels a pending billing setup. The CREATE + operation creates a new billing setup. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_billing_setup( + self, + ) -> Callable[ + [billing_setup_service.MutateBillingSetupRequest], + billing_setup_service.MutateBillingSetupResponse, + ]: + r"""Return a callable for the mutate billing setup method over gRPC. + + Creates a billing setup, or cancels an existing billing setup. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BillingSetupError <>`__ + `DateError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateBillingSetupRequest], + ~.MutateBillingSetupResponse]: + 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 "mutate_billing_setup" not in self._stubs: + self._stubs["mutate_billing_setup"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BillingSetupService/MutateBillingSetup", + request_serializer=billing_setup_service.MutateBillingSetupRequest.serialize, + response_deserializer=billing_setup_service.MutateBillingSetupResponse.deserialize, + ) + ) + return self._stubs["mutate_billing_setup"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("BillingSetupServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/billing_setup_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/billing_setup_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..52dbb2a08 --- /dev/null +++ b/google/ads/googleads/v24/services/services/billing_setup_service/transports/grpc_asyncio.py @@ -0,0 +1,420 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import billing_setup_service +from .base import BillingSetupServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.BillingSetupService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.BillingSetupService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class BillingSetupServiceGrpcAsyncIOTransport(BillingSetupServiceTransport): + """gRPC AsyncIO backend transport for BillingSetupService. + + A service for designating the business entity responsible for + accrued costs. + A billing setup is associated with a payments account. + Billing-related activity for all billing setups associated with + a particular payments account will appear on a single invoice + generated monthly. + + Mutates: + + The REMOVE operation cancels a pending billing setup. The CREATE + operation creates a new billing setup. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_billing_setup( + self, + ) -> Callable[ + [billing_setup_service.MutateBillingSetupRequest], + Awaitable[billing_setup_service.MutateBillingSetupResponse], + ]: + r"""Return a callable for the mutate billing setup method over gRPC. + + Creates a billing setup, or cancels an existing billing setup. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `BillingSetupError <>`__ + `DateError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateBillingSetupRequest], + Awaitable[~.MutateBillingSetupResponse]]: + 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 "mutate_billing_setup" not in self._stubs: + self._stubs["mutate_billing_setup"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BillingSetupService/MutateBillingSetup", + request_serializer=billing_setup_service.MutateBillingSetupRequest.serialize, + response_deserializer=billing_setup_service.MutateBillingSetupResponse.deserialize, + ) + ) + return self._stubs["mutate_billing_setup"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_billing_setup: self._wrap_method( + self.mutate_billing_setup, + 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" + + +__all__ = ("BillingSetupServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/brand_suggestion_service/__init__.py b/google/ads/googleads/v24/services/services/brand_suggestion_service/__init__.py new file mode 100644 index 000000000..6921acce8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/brand_suggestion_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import BrandSuggestionServiceClient +from .async_client import BrandSuggestionServiceAsyncClient + +__all__ = ( + "BrandSuggestionServiceClient", + "BrandSuggestionServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/brand_suggestion_service/async_client.py b/google/ads/googleads/v24/services/services/brand_suggestion_service/async_client.py new file mode 100644 index 000000000..d45dca966 --- /dev/null +++ b/google/ads/googleads/v24/services/services/brand_suggestion_service/async_client.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import brand_suggestion_service +from .transports.base import ( + BrandSuggestionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import BrandSuggestionServiceClient + +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 BrandSuggestionServiceAsyncClient: + """This service will suggest brands based on a prefix.""" + + _client: BrandSuggestionServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = BrandSuggestionServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = BrandSuggestionServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + BrandSuggestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = BrandSuggestionServiceClient._DEFAULT_UNIVERSE + + common_billing_account_path = staticmethod( + BrandSuggestionServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + BrandSuggestionServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + BrandSuggestionServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + BrandSuggestionServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + BrandSuggestionServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + BrandSuggestionServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + BrandSuggestionServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + BrandSuggestionServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + BrandSuggestionServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + BrandSuggestionServiceClient.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: + BrandSuggestionServiceAsyncClient: The constructed client. + """ + return BrandSuggestionServiceClient.from_service_account_info.__func__(BrandSuggestionServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + BrandSuggestionServiceAsyncClient: The constructed client. + """ + return BrandSuggestionServiceClient.from_service_account_file.__func__(BrandSuggestionServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return BrandSuggestionServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> BrandSuggestionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + BrandSuggestionServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = BrandSuggestionServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + BrandSuggestionServiceTransport, + Callable[..., BrandSuggestionServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the brand suggestion 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,BrandSuggestionServiceTransport,Callable[..., BrandSuggestionServiceTransport]]]): + 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 BrandSuggestionServiceTransport 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 = BrandSuggestionServiceClient( + 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.ads.googleads.v24.services.BrandSuggestionServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.BrandSuggestionService", + "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.ads.googleads.v24.services.BrandSuggestionService", + "credentialsType": None, + } + ), + ) + + async def suggest_brands( + self, + request: Optional[ + Union[brand_suggestion_service.SuggestBrandsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + brand_prefix: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> brand_suggestion_service.SuggestBrandsResponse: + r"""Rpc to return a list of matching brands based on a + prefix for this customer. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.SuggestBrandsRequest, dict]]): + The request object. Request message for + [BrandSuggestionService.SuggestBrands][google.ads.googleads.v24.services.BrandSuggestionService.SuggestBrands]. + customer_id (:class:`str`): + Required. The ID of the customer onto + which to apply the brand suggestion + operation. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + brand_prefix (:class:`str`): + Required. The prefix of a brand name. + This corresponds to the ``brand_prefix`` 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.ads.googleads.v24.services.types.SuggestBrandsResponse: + Response message for + [BrandSuggestionService.SuggestBrands][google.ads.googleads.v24.services.BrandSuggestionService.SuggestBrands]. + + """ + # 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 = [customer_id, brand_prefix] + 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, brand_suggestion_service.SuggestBrandsRequest + ): + request = brand_suggestion_service.SuggestBrandsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if brand_prefix is not None: + request.brand_prefix = brand_prefix + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.suggest_brands + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "BrandSuggestionServiceAsyncClient": + 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__ = ("BrandSuggestionServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/brand_suggestion_service/client.py b/google/ads/googleads/v24/services/services/brand_suggestion_service/client.py new file mode 100644 index 000000000..745173748 --- /dev/null +++ b/google/ads/googleads/v24/services/services/brand_suggestion_service/client.py @@ -0,0 +1,861 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import brand_suggestion_service +from .transports.base import ( + BrandSuggestionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import BrandSuggestionServiceGrpcTransport +from .transports.grpc_asyncio import BrandSuggestionServiceGrpcAsyncIOTransport + + +class BrandSuggestionServiceClientMeta(type): + """Metaclass for the BrandSuggestionService 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[BrandSuggestionServiceTransport]] + _transport_registry["grpc"] = BrandSuggestionServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + BrandSuggestionServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[BrandSuggestionServiceTransport]: + """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 BrandSuggestionServiceClient(metaclass=BrandSuggestionServiceClientMeta): + """This service will suggest brands based on a prefix.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + BrandSuggestionServiceClient: 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: + BrandSuggestionServiceClient: 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) -> BrandSuggestionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + BrandSuggestionServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @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 = ( + BrandSuggestionServiceClient._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 = ( + BrandSuggestionServiceClient._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 + ): + """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 = BrandSuggestionServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = BrandSuggestionServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + BrandSuggestionServiceClient._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 = BrandSuggestionServiceClient._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): + """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, + BrandSuggestionServiceTransport, + Callable[..., BrandSuggestionServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the brand suggestion 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,BrandSuggestionServiceTransport,Callable[..., BrandSuggestionServiceTransport]]]): + 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 BrandSuggestionServiceTransport 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, + ) = BrandSuggestionServiceClient._read_environment_variables() + self._client_cert_source = ( + BrandSuggestionServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + BrandSuggestionServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, BrandSuggestionServiceTransport + ) + if transport_provided: + # transport is a BrandSuggestionServiceTransport 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(BrandSuggestionServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or BrandSuggestionServiceClient._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[BrandSuggestionServiceTransport], + Callable[..., BrandSuggestionServiceTransport], + ] = ( + BrandSuggestionServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., BrandSuggestionServiceTransport], 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.ads.googleads.v24.services.BrandSuggestionServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.BrandSuggestionService", + "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.ads.googleads.v24.services.BrandSuggestionService", + "credentialsType": None, + } + ), + ) + + def suggest_brands( + self, + request: Optional[ + Union[brand_suggestion_service.SuggestBrandsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + brand_prefix: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> brand_suggestion_service.SuggestBrandsResponse: + r"""Rpc to return a list of matching brands based on a + prefix for this customer. + + Args: + request (Union[google.ads.googleads.v24.services.types.SuggestBrandsRequest, dict]): + The request object. Request message for + [BrandSuggestionService.SuggestBrands][google.ads.googleads.v24.services.BrandSuggestionService.SuggestBrands]. + customer_id (str): + Required. The ID of the customer onto + which to apply the brand suggestion + operation. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + brand_prefix (str): + Required. The prefix of a brand name. + This corresponds to the ``brand_prefix`` 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.ads.googleads.v24.services.types.SuggestBrandsResponse: + Response message for + [BrandSuggestionService.SuggestBrands][google.ads.googleads.v24.services.BrandSuggestionService.SuggestBrands]. + + """ + # 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 = [customer_id, brand_prefix] + 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, brand_suggestion_service.SuggestBrandsRequest + ): + request = brand_suggestion_service.SuggestBrandsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if brand_prefix is not None: + request.brand_prefix = brand_prefix + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.suggest_brands] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "BrandSuggestionServiceClient": + 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() + + +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__ = ("BrandSuggestionServiceClient",) diff --git a/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/README.rst b/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/README.rst new file mode 100644 index 000000000..3f86c65a5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`BrandSuggestionServiceTransport` is the ABC for all transports. +- public child `BrandSuggestionServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `BrandSuggestionServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseBrandSuggestionServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `BrandSuggestionServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/__init__.py b/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/__init__.py new file mode 100644 index 000000000..8b28bb9de --- /dev/null +++ b/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import BrandSuggestionServiceTransport +from .grpc import BrandSuggestionServiceGrpcTransport +from .grpc_asyncio import BrandSuggestionServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[BrandSuggestionServiceTransport]] +_transport_registry["grpc"] = BrandSuggestionServiceGrpcTransport +_transport_registry["grpc_asyncio"] = BrandSuggestionServiceGrpcAsyncIOTransport + +__all__ = ( + "BrandSuggestionServiceTransport", + "BrandSuggestionServiceGrpcTransport", + "BrandSuggestionServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/base.py b/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/base.py new file mode 100644 index 000000000..56747fec9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import brand_suggestion_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 BrandSuggestionServiceTransport(abc.ABC): + """Abstract transport class for BrandSuggestionService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.suggest_brands: gapic_v1.method.wrap_method( + self.suggest_brands, + 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 suggest_brands( + self, + ) -> Callable[ + [brand_suggestion_service.SuggestBrandsRequest], + Union[ + brand_suggestion_service.SuggestBrandsResponse, + Awaitable[brand_suggestion_service.SuggestBrandsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("BrandSuggestionServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/grpc.py b/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/grpc.py new file mode 100644 index 000000000..a32012880 --- /dev/null +++ b/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/grpc.py @@ -0,0 +1,382 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import brand_suggestion_service +from .base import BrandSuggestionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.BrandSuggestionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.BrandSuggestionService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class BrandSuggestionServiceGrpcTransport(BrandSuggestionServiceTransport): + """gRPC backend transport for BrandSuggestionService. + + This service will suggest brands based on a prefix. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 suggest_brands( + self, + ) -> Callable[ + [brand_suggestion_service.SuggestBrandsRequest], + brand_suggestion_service.SuggestBrandsResponse, + ]: + r"""Return a callable for the suggest brands method over gRPC. + + Rpc to return a list of matching brands based on a + prefix for this customer. + + Returns: + Callable[[~.SuggestBrandsRequest], + ~.SuggestBrandsResponse]: + 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 "suggest_brands" not in self._stubs: + self._stubs["suggest_brands"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BrandSuggestionService/SuggestBrands", + request_serializer=brand_suggestion_service.SuggestBrandsRequest.serialize, + response_deserializer=brand_suggestion_service.SuggestBrandsResponse.deserialize, + ) + return self._stubs["suggest_brands"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("BrandSuggestionServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..7e5906198 --- /dev/null +++ b/google/ads/googleads/v24/services/services/brand_suggestion_service/transports/grpc_asyncio.py @@ -0,0 +1,405 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import brand_suggestion_service +from .base import BrandSuggestionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.BrandSuggestionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.BrandSuggestionService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class BrandSuggestionServiceGrpcAsyncIOTransport( + BrandSuggestionServiceTransport +): + """gRPC AsyncIO backend transport for BrandSuggestionService. + + This service will suggest brands based on a prefix. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 suggest_brands( + self, + ) -> Callable[ + [brand_suggestion_service.SuggestBrandsRequest], + Awaitable[brand_suggestion_service.SuggestBrandsResponse], + ]: + r"""Return a callable for the suggest brands method over gRPC. + + Rpc to return a list of matching brands based on a + prefix for this customer. + + Returns: + Callable[[~.SuggestBrandsRequest], + Awaitable[~.SuggestBrandsResponse]]: + 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 "suggest_brands" not in self._stubs: + self._stubs["suggest_brands"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.BrandSuggestionService/SuggestBrands", + request_serializer=brand_suggestion_service.SuggestBrandsRequest.serialize, + response_deserializer=brand_suggestion_service.SuggestBrandsResponse.deserialize, + ) + return self._stubs["suggest_brands"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.suggest_brands: self._wrap_method( + self.suggest_brands, + 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" + + +__all__ = ("BrandSuggestionServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_asset_service/__init__.py b/google/ads/googleads/v24/services/services/campaign_asset_service/__init__.py new file mode 100644 index 000000000..f19ef36be --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CampaignAssetServiceClient +from .async_client import CampaignAssetServiceAsyncClient + +__all__ = ( + "CampaignAssetServiceClient", + "CampaignAssetServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/campaign_asset_service/async_client.py b/google/ads/googleads/v24/services/services/campaign_asset_service/async_client.py new file mode 100644 index 000000000..9348b6609 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_service/async_client.py @@ -0,0 +1,433 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import campaign_asset_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CampaignAssetServiceTransport, DEFAULT_CLIENT_INFO +from .client import CampaignAssetServiceClient + +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 CampaignAssetServiceAsyncClient: + """Service to manage campaign assets.""" + + _client: CampaignAssetServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CampaignAssetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CampaignAssetServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CampaignAssetServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CampaignAssetServiceClient._DEFAULT_UNIVERSE + + asset_path = staticmethod(CampaignAssetServiceClient.asset_path) + parse_asset_path = staticmethod(CampaignAssetServiceClient.parse_asset_path) + campaign_path = staticmethod(CampaignAssetServiceClient.campaign_path) + parse_campaign_path = staticmethod( + CampaignAssetServiceClient.parse_campaign_path + ) + campaign_asset_path = staticmethod( + CampaignAssetServiceClient.campaign_asset_path + ) + parse_campaign_asset_path = staticmethod( + CampaignAssetServiceClient.parse_campaign_asset_path + ) + common_billing_account_path = staticmethod( + CampaignAssetServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CampaignAssetServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CampaignAssetServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CampaignAssetServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CampaignAssetServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CampaignAssetServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CampaignAssetServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CampaignAssetServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CampaignAssetServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CampaignAssetServiceClient.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: + CampaignAssetServiceAsyncClient: The constructed client. + """ + return CampaignAssetServiceClient.from_service_account_info.__func__(CampaignAssetServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CampaignAssetServiceAsyncClient: The constructed client. + """ + return CampaignAssetServiceClient.from_service_account_file.__func__(CampaignAssetServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CampaignAssetServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CampaignAssetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignAssetServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CampaignAssetServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CampaignAssetServiceTransport, + Callable[..., CampaignAssetServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign asset 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,CampaignAssetServiceTransport,Callable[..., CampaignAssetServiceTransport]]]): + 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 CampaignAssetServiceTransport 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 = CampaignAssetServiceClient( + 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.ads.googleads.v24.services.CampaignAssetServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignAssetService", + "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.ads.googleads.v24.services.CampaignAssetService", + "credentialsType": None, + } + ), + ) + + async def mutate_campaign_assets( + self, + request: Optional[ + Union[campaign_asset_service.MutateCampaignAssetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_asset_service.CampaignAssetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_asset_service.MutateCampaignAssetsResponse: + r"""Creates, updates, or removes campaign assets. Operation statuses + are returned. + + List of thrown errors: `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `NotAllowlistedError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCampaignAssetsRequest, dict]]): + The request object. Request message for + [CampaignAssetService.MutateCampaignAssets][google.ads.googleads.v24.services.CampaignAssetService.MutateCampaignAssets]. + customer_id (:class:`str`): + Required. The ID of the customer + whose campaign assets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CampaignAssetOperation]`): + Required. The list of operations to + perform on individual campaign assets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignAssetsResponse: + Response message for a campaign asset + mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_asset_service.MutateCampaignAssetsRequest + ): + request = campaign_asset_service.MutateCampaignAssetsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_campaign_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CampaignAssetServiceAsyncClient": + 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__ = ("CampaignAssetServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_asset_service/client.py b/google/ads/googleads/v24/services/services/campaign_asset_service/client.py new file mode 100644 index 000000000..a53111848 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_service/client.py @@ -0,0 +1,944 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import campaign_asset_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CampaignAssetServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CampaignAssetServiceGrpcTransport +from .transports.grpc_asyncio import CampaignAssetServiceGrpcAsyncIOTransport + + +class CampaignAssetServiceClientMeta(type): + """Metaclass for the CampaignAssetService 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[CampaignAssetServiceTransport]] + _transport_registry["grpc"] = CampaignAssetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CampaignAssetServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignAssetServiceTransport]: + """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 CampaignAssetServiceClient(metaclass=CampaignAssetServiceClientMeta): + """Service to manage campaign assets.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CampaignAssetServiceClient: 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: + CampaignAssetServiceClient: 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) -> CampaignAssetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignAssetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def asset_path( + customer_id: str, + asset_id: str, + ) -> str: + """Returns a fully-qualified asset string.""" + return "customers/{customer_id}/assets/{asset_id}".format( + customer_id=customer_id, + asset_id=asset_id, + ) + + @staticmethod + def parse_asset_path(path: str) -> Dict[str, str]: + """Parses a asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assets/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_asset_path( + customer_id: str, + campaign_id: str, + asset_id: str, + field_type: str, + ) -> str: + """Returns a fully-qualified campaign_asset string.""" + return "customers/{customer_id}/campaignAssets/{campaign_id}~{asset_id}~{field_type}".format( + customer_id=customer_id, + campaign_id=campaign_id, + asset_id=asset_id, + field_type=field_type, + ) + + @staticmethod + def parse_campaign_asset_path(path: str) -> Dict[str, str]: + """Parses a campaign_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignAssets/(?P.+?)~(?P.+?)~(?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 = ( + CampaignAssetServiceClient._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 = ( + CampaignAssetServiceClient._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 + ): + """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 = CampaignAssetServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CampaignAssetServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + CampaignAssetServiceClient._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 = CampaignAssetServiceClient._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): + """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, + CampaignAssetServiceTransport, + Callable[..., CampaignAssetServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign asset 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,CampaignAssetServiceTransport,Callable[..., CampaignAssetServiceTransport]]]): + 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 CampaignAssetServiceTransport 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, + ) = CampaignAssetServiceClient._read_environment_variables() + self._client_cert_source = ( + CampaignAssetServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = CampaignAssetServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CampaignAssetServiceTransport + ) + if transport_provided: + # transport is a CampaignAssetServiceTransport 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(CampaignAssetServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CampaignAssetServiceClient._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[CampaignAssetServiceTransport], + Callable[..., CampaignAssetServiceTransport], + ] = ( + CampaignAssetServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CampaignAssetServiceTransport], 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.ads.googleads.v24.services.CampaignAssetServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignAssetService", + "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.ads.googleads.v24.services.CampaignAssetService", + "credentialsType": None, + } + ), + ) + + def mutate_campaign_assets( + self, + request: Optional[ + Union[campaign_asset_service.MutateCampaignAssetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_asset_service.CampaignAssetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_asset_service.MutateCampaignAssetsResponse: + r"""Creates, updates, or removes campaign assets. Operation statuses + are returned. + + List of thrown errors: `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `NotAllowlistedError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCampaignAssetsRequest, dict]): + The request object. Request message for + [CampaignAssetService.MutateCampaignAssets][google.ads.googleads.v24.services.CampaignAssetService.MutateCampaignAssets]. + customer_id (str): + Required. The ID of the customer + whose campaign assets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignAssetOperation]): + Required. The list of operations to + perform on individual campaign assets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignAssetsResponse: + Response message for a campaign asset + mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_asset_service.MutateCampaignAssetsRequest + ): + request = campaign_asset_service.MutateCampaignAssetsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_campaign_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CampaignAssetServiceClient": + 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() + + +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__ = ("CampaignAssetServiceClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_asset_service/transports/README.rst b/google/ads/googleads/v24/services/services/campaign_asset_service/transports/README.rst new file mode 100644 index 000000000..aa02fd1c6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CampaignAssetServiceTransport` is the ABC for all transports. +- public child `CampaignAssetServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CampaignAssetServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCampaignAssetServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CampaignAssetServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/campaign_asset_service/transports/__init__.py b/google/ads/googleads/v24/services/services/campaign_asset_service/transports/__init__.py new file mode 100644 index 000000000..0acc00025 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CampaignAssetServiceTransport +from .grpc import CampaignAssetServiceGrpcTransport +from .grpc_asyncio import CampaignAssetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignAssetServiceTransport]] +_transport_registry["grpc"] = CampaignAssetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = CampaignAssetServiceGrpcAsyncIOTransport + +__all__ = ( + "CampaignAssetServiceTransport", + "CampaignAssetServiceGrpcTransport", + "CampaignAssetServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/campaign_asset_service/transports/base.py b/google/ads/googleads/v24/services/services/campaign_asset_service/transports/base.py new file mode 100644 index 000000000..afba3a3b2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import campaign_asset_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 CampaignAssetServiceTransport(abc.ABC): + """Abstract transport class for CampaignAssetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaign_assets: gapic_v1.method.wrap_method( + self.mutate_campaign_assets, + 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 mutate_campaign_assets( + self, + ) -> Callable[ + [campaign_asset_service.MutateCampaignAssetsRequest], + Union[ + campaign_asset_service.MutateCampaignAssetsResponse, + Awaitable[campaign_asset_service.MutateCampaignAssetsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CampaignAssetServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_asset_service/transports/grpc.py b/google/ads/googleads/v24/services/services/campaign_asset_service/transports/grpc.py new file mode 100644 index 000000000..62e360af0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_service/transports/grpc.py @@ -0,0 +1,390 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import campaign_asset_service +from .base import CampaignAssetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignAssetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignAssetService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignAssetServiceGrpcTransport(CampaignAssetServiceTransport): + """gRPC backend transport for CampaignAssetService. + + Service to manage campaign assets. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_campaign_assets( + self, + ) -> Callable[ + [campaign_asset_service.MutateCampaignAssetsRequest], + campaign_asset_service.MutateCampaignAssetsResponse, + ]: + r"""Return a callable for the mutate campaign assets method over gRPC. + + Creates, updates, or removes campaign assets. Operation statuses + are returned. + + List of thrown errors: `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `NotAllowlistedError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateCampaignAssetsRequest], + ~.MutateCampaignAssetsResponse]: + 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 "mutate_campaign_assets" not in self._stubs: + self._stubs["mutate_campaign_assets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignAssetService/MutateCampaignAssets", + request_serializer=campaign_asset_service.MutateCampaignAssetsRequest.serialize, + response_deserializer=campaign_asset_service.MutateCampaignAssetsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_assets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CampaignAssetServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_asset_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/campaign_asset_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..cb0e76973 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_service/transports/grpc_asyncio.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import campaign_asset_service +from .base import CampaignAssetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignAssetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignAssetService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignAssetServiceGrpcAsyncIOTransport(CampaignAssetServiceTransport): + """gRPC AsyncIO backend transport for CampaignAssetService. + + Service to manage campaign assets. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_campaign_assets( + self, + ) -> Callable[ + [campaign_asset_service.MutateCampaignAssetsRequest], + Awaitable[campaign_asset_service.MutateCampaignAssetsResponse], + ]: + r"""Return a callable for the mutate campaign assets method over gRPC. + + Creates, updates, or removes campaign assets. Operation statuses + are returned. + + List of thrown errors: `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `NotAllowlistedError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateCampaignAssetsRequest], + Awaitable[~.MutateCampaignAssetsResponse]]: + 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 "mutate_campaign_assets" not in self._stubs: + self._stubs["mutate_campaign_assets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignAssetService/MutateCampaignAssets", + request_serializer=campaign_asset_service.MutateCampaignAssetsRequest.serialize, + response_deserializer=campaign_asset_service.MutateCampaignAssetsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_assets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_campaign_assets: self._wrap_method( + self.mutate_campaign_assets, + 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" + + +__all__ = ("CampaignAssetServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_asset_set_service/__init__.py b/google/ads/googleads/v24/services/services/campaign_asset_set_service/__init__.py new file mode 100644 index 000000000..4ba34c875 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_set_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CampaignAssetSetServiceClient +from .async_client import CampaignAssetSetServiceAsyncClient + +__all__ = ( + "CampaignAssetSetServiceClient", + "CampaignAssetSetServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/campaign_asset_set_service/async_client.py b/google/ads/googleads/v24/services/services/campaign_asset_set_service/async_client.py new file mode 100644 index 000000000..41e317884 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_set_service/async_client.py @@ -0,0 +1,437 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import campaign_asset_set_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CampaignAssetSetServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CampaignAssetSetServiceClient + +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 CampaignAssetSetServiceAsyncClient: + """Service to manage campaign asset set""" + + _client: CampaignAssetSetServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CampaignAssetSetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CampaignAssetSetServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CampaignAssetSetServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CampaignAssetSetServiceClient._DEFAULT_UNIVERSE + + asset_set_path = staticmethod(CampaignAssetSetServiceClient.asset_set_path) + parse_asset_set_path = staticmethod( + CampaignAssetSetServiceClient.parse_asset_set_path + ) + campaign_path = staticmethod(CampaignAssetSetServiceClient.campaign_path) + parse_campaign_path = staticmethod( + CampaignAssetSetServiceClient.parse_campaign_path + ) + campaign_asset_set_path = staticmethod( + CampaignAssetSetServiceClient.campaign_asset_set_path + ) + parse_campaign_asset_set_path = staticmethod( + CampaignAssetSetServiceClient.parse_campaign_asset_set_path + ) + common_billing_account_path = staticmethod( + CampaignAssetSetServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CampaignAssetSetServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CampaignAssetSetServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CampaignAssetSetServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CampaignAssetSetServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CampaignAssetSetServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CampaignAssetSetServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CampaignAssetSetServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CampaignAssetSetServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CampaignAssetSetServiceClient.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: + CampaignAssetSetServiceAsyncClient: The constructed client. + """ + return CampaignAssetSetServiceClient.from_service_account_info.__func__(CampaignAssetSetServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CampaignAssetSetServiceAsyncClient: The constructed client. + """ + return CampaignAssetSetServiceClient.from_service_account_file.__func__(CampaignAssetSetServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CampaignAssetSetServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CampaignAssetSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignAssetSetServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CampaignAssetSetServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CampaignAssetSetServiceTransport, + Callable[..., CampaignAssetSetServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign asset set 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,CampaignAssetSetServiceTransport,Callable[..., CampaignAssetSetServiceTransport]]]): + 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 CampaignAssetSetServiceTransport 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 = CampaignAssetSetServiceClient( + 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.ads.googleads.v24.services.CampaignAssetSetServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignAssetSetService", + "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.ads.googleads.v24.services.CampaignAssetSetService", + "credentialsType": None, + } + ), + ) + + async def mutate_campaign_asset_sets( + self, + request: Optional[ + Union[ + campaign_asset_set_service.MutateCampaignAssetSetsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_asset_set_service.CampaignAssetSetOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_asset_set_service.MutateCampaignAssetSetsResponse: + r"""Creates, updates or removes campaign asset sets. + Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCampaignAssetSetsRequest, dict]]): + The request object. Request message for + [CampaignAssetSetService.MutateCampaignAssetSets][google.ads.googleads.v24.services.CampaignAssetSetService.MutateCampaignAssetSets]. + customer_id (:class:`str`): + Required. The ID of the customer + whose campaign asset sets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CampaignAssetSetOperation]`): + Required. The list of operations to + perform on individual campaign asset + sets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignAssetSetsResponse: + Response message for a campaign asset + set mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_asset_set_service.MutateCampaignAssetSetsRequest + ): + request = campaign_asset_set_service.MutateCampaignAssetSetsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_campaign_asset_sets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CampaignAssetSetServiceAsyncClient": + 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__ = ("CampaignAssetSetServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_asset_set_service/client.py b/google/ads/googleads/v24/services/services/campaign_asset_set_service/client.py new file mode 100644 index 000000000..7394360f2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_set_service/client.py @@ -0,0 +1,949 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import campaign_asset_set_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CampaignAssetSetServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CampaignAssetSetServiceGrpcTransport +from .transports.grpc_asyncio import CampaignAssetSetServiceGrpcAsyncIOTransport + + +class CampaignAssetSetServiceClientMeta(type): + """Metaclass for the CampaignAssetSetService 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[CampaignAssetSetServiceTransport]] + _transport_registry["grpc"] = CampaignAssetSetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CampaignAssetSetServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignAssetSetServiceTransport]: + """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 CampaignAssetSetServiceClient( + metaclass=CampaignAssetSetServiceClientMeta +): + """Service to manage campaign asset set""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CampaignAssetSetServiceClient: 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: + CampaignAssetSetServiceClient: 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) -> CampaignAssetSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignAssetSetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def asset_set_path( + customer_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified asset_set string.""" + return "customers/{customer_id}/assetSets/{asset_set_id}".format( + customer_id=customer_id, + asset_set_id=asset_set_id, + ) + + @staticmethod + def parse_asset_set_path(path: str) -> Dict[str, str]: + """Parses a asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetSets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_asset_set_path( + customer_id: str, + campaign_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified campaign_asset_set string.""" + return "customers/{customer_id}/campaignAssetSets/{campaign_id}~{asset_set_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + asset_set_id=asset_set_id, + ) + + @staticmethod + def parse_campaign_asset_set_path(path: str) -> Dict[str, str]: + """Parses a campaign_asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignAssetSets/(?P.+?)~(?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 = ( + CampaignAssetSetServiceClient._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 = ( + CampaignAssetSetServiceClient._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 + ): + """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 = CampaignAssetSetServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CampaignAssetSetServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + CampaignAssetSetServiceClient._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 = CampaignAssetSetServiceClient._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): + """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, + CampaignAssetSetServiceTransport, + Callable[..., CampaignAssetSetServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign asset set 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,CampaignAssetSetServiceTransport,Callable[..., CampaignAssetSetServiceTransport]]]): + 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 CampaignAssetSetServiceTransport 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, + ) = CampaignAssetSetServiceClient._read_environment_variables() + self._client_cert_source = ( + CampaignAssetSetServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CampaignAssetSetServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CampaignAssetSetServiceTransport + ) + if transport_provided: + # transport is a CampaignAssetSetServiceTransport 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(CampaignAssetSetServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CampaignAssetSetServiceClient._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[CampaignAssetSetServiceTransport], + Callable[..., CampaignAssetSetServiceTransport], + ] = ( + CampaignAssetSetServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CampaignAssetSetServiceTransport], 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.ads.googleads.v24.services.CampaignAssetSetServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignAssetSetService", + "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.ads.googleads.v24.services.CampaignAssetSetService", + "credentialsType": None, + } + ), + ) + + def mutate_campaign_asset_sets( + self, + request: Optional[ + Union[ + campaign_asset_set_service.MutateCampaignAssetSetsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_asset_set_service.CampaignAssetSetOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_asset_set_service.MutateCampaignAssetSetsResponse: + r"""Creates, updates or removes campaign asset sets. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCampaignAssetSetsRequest, dict]): + The request object. Request message for + [CampaignAssetSetService.MutateCampaignAssetSets][google.ads.googleads.v24.services.CampaignAssetSetService.MutateCampaignAssetSets]. + customer_id (str): + Required. The ID of the customer + whose campaign asset sets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignAssetSetOperation]): + Required. The list of operations to + perform on individual campaign asset + sets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignAssetSetsResponse: + Response message for a campaign asset + set mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_asset_set_service.MutateCampaignAssetSetsRequest + ): + request = campaign_asset_set_service.MutateCampaignAssetSetsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_campaign_asset_sets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CampaignAssetSetServiceClient": + 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() + + +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__ = ("CampaignAssetSetServiceClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/README.rst b/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/README.rst new file mode 100644 index 000000000..37ce8a341 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CampaignAssetSetServiceTransport` is the ABC for all transports. +- public child `CampaignAssetSetServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CampaignAssetSetServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCampaignAssetSetServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CampaignAssetSetServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/__init__.py b/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/__init__.py new file mode 100644 index 000000000..053cd4010 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CampaignAssetSetServiceTransport +from .grpc import CampaignAssetSetServiceGrpcTransport +from .grpc_asyncio import CampaignAssetSetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignAssetSetServiceTransport]] +_transport_registry["grpc"] = CampaignAssetSetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CampaignAssetSetServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CampaignAssetSetServiceTransport", + "CampaignAssetSetServiceGrpcTransport", + "CampaignAssetSetServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/base.py b/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/base.py new file mode 100644 index 000000000..2aced7ea4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import campaign_asset_set_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 CampaignAssetSetServiceTransport(abc.ABC): + """Abstract transport class for CampaignAssetSetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaign_asset_sets: gapic_v1.method.wrap_method( + self.mutate_campaign_asset_sets, + 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 mutate_campaign_asset_sets( + self, + ) -> Callable[ + [campaign_asset_set_service.MutateCampaignAssetSetsRequest], + Union[ + campaign_asset_set_service.MutateCampaignAssetSetsResponse, + Awaitable[ + campaign_asset_set_service.MutateCampaignAssetSetsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CampaignAssetSetServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/grpc.py b/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/grpc.py new file mode 100644 index 000000000..9db4fa529 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/grpc.py @@ -0,0 +1,384 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import campaign_asset_set_service +from .base import CampaignAssetSetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignAssetSetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignAssetSetService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignAssetSetServiceGrpcTransport(CampaignAssetSetServiceTransport): + """gRPC backend transport for CampaignAssetSetService. + + Service to manage campaign asset set + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_campaign_asset_sets( + self, + ) -> Callable[ + [campaign_asset_set_service.MutateCampaignAssetSetsRequest], + campaign_asset_set_service.MutateCampaignAssetSetsResponse, + ]: + r"""Return a callable for the mutate campaign asset sets method over gRPC. + + Creates, updates or removes campaign asset sets. + Operation statuses are returned. + + Returns: + Callable[[~.MutateCampaignAssetSetsRequest], + ~.MutateCampaignAssetSetsResponse]: + 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 "mutate_campaign_asset_sets" not in self._stubs: + self._stubs["mutate_campaign_asset_sets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignAssetSetService/MutateCampaignAssetSets", + request_serializer=campaign_asset_set_service.MutateCampaignAssetSetsRequest.serialize, + response_deserializer=campaign_asset_set_service.MutateCampaignAssetSetsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_asset_sets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CampaignAssetSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..4eaa93c25 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_asset_set_service/transports/grpc_asyncio.py @@ -0,0 +1,407 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import campaign_asset_set_service +from .base import CampaignAssetSetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignAssetSetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignAssetSetService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignAssetSetServiceGrpcAsyncIOTransport( + CampaignAssetSetServiceTransport +): + """gRPC AsyncIO backend transport for CampaignAssetSetService. + + Service to manage campaign asset set + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_campaign_asset_sets( + self, + ) -> Callable[ + [campaign_asset_set_service.MutateCampaignAssetSetsRequest], + Awaitable[campaign_asset_set_service.MutateCampaignAssetSetsResponse], + ]: + r"""Return a callable for the mutate campaign asset sets method over gRPC. + + Creates, updates or removes campaign asset sets. + Operation statuses are returned. + + Returns: + Callable[[~.MutateCampaignAssetSetsRequest], + Awaitable[~.MutateCampaignAssetSetsResponse]]: + 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 "mutate_campaign_asset_sets" not in self._stubs: + self._stubs["mutate_campaign_asset_sets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignAssetSetService/MutateCampaignAssetSets", + request_serializer=campaign_asset_set_service.MutateCampaignAssetSetsRequest.serialize, + response_deserializer=campaign_asset_set_service.MutateCampaignAssetSetsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_asset_sets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_campaign_asset_sets: self._wrap_method( + self.mutate_campaign_asset_sets, + 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" + + +__all__ = ("CampaignAssetSetServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/__init__.py b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/__init__.py new file mode 100644 index 000000000..dba2deae0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CampaignBidModifierServiceClient +from .async_client import CampaignBidModifierServiceAsyncClient + +__all__ = ( + "CampaignBidModifierServiceClient", + "CampaignBidModifierServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/async_client.py b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/async_client.py new file mode 100644 index 000000000..086c0f19e --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/async_client.py @@ -0,0 +1,451 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + campaign_bid_modifier_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CampaignBidModifierServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CampaignBidModifierServiceClient + +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 CampaignBidModifierServiceAsyncClient: + """Service to manage campaign bid modifiers.""" + + _client: CampaignBidModifierServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CampaignBidModifierServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + CampaignBidModifierServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CampaignBidModifierServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CampaignBidModifierServiceClient._DEFAULT_UNIVERSE + + campaign_path = staticmethod(CampaignBidModifierServiceClient.campaign_path) + parse_campaign_path = staticmethod( + CampaignBidModifierServiceClient.parse_campaign_path + ) + campaign_bid_modifier_path = staticmethod( + CampaignBidModifierServiceClient.campaign_bid_modifier_path + ) + parse_campaign_bid_modifier_path = staticmethod( + CampaignBidModifierServiceClient.parse_campaign_bid_modifier_path + ) + common_billing_account_path = staticmethod( + CampaignBidModifierServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CampaignBidModifierServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CampaignBidModifierServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CampaignBidModifierServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CampaignBidModifierServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CampaignBidModifierServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CampaignBidModifierServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CampaignBidModifierServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CampaignBidModifierServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CampaignBidModifierServiceClient.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: + CampaignBidModifierServiceAsyncClient: The constructed client. + """ + return CampaignBidModifierServiceClient.from_service_account_info.__func__(CampaignBidModifierServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CampaignBidModifierServiceAsyncClient: The constructed client. + """ + return CampaignBidModifierServiceClient.from_service_account_file.__func__(CampaignBidModifierServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CampaignBidModifierServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CampaignBidModifierServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignBidModifierServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CampaignBidModifierServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CampaignBidModifierServiceTransport, + Callable[..., CampaignBidModifierServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign bid modifier 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,CampaignBidModifierServiceTransport,Callable[..., CampaignBidModifierServiceTransport]]]): + 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 CampaignBidModifierServiceTransport 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 = CampaignBidModifierServiceClient( + 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.ads.googleads.v24.services.CampaignBidModifierServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignBidModifierService", + "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.ads.googleads.v24.services.CampaignBidModifierService", + "credentialsType": None, + } + ), + ) + + async def mutate_campaign_bid_modifiers( + self, + request: Optional[ + Union[ + campaign_bid_modifier_service.MutateCampaignBidModifiersRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_bid_modifier_service.CampaignBidModifierOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_bid_modifier_service.MutateCampaignBidModifiersResponse: + r"""Creates, updates, or removes campaign bid modifiers. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ContextError <>`__ + `CriterionError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCampaignBidModifiersRequest, dict]]): + The request object. Request message for + [CampaignBidModifierService.MutateCampaignBidModifiers][google.ads.googleads.v24.services.CampaignBidModifierService.MutateCampaignBidModifiers]. + customer_id (:class:`str`): + Required. ID of the customer whose + campaign bid modifiers are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CampaignBidModifierOperation]`): + Required. The list of operations to + perform on individual campaign bid + modifiers. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignBidModifiersResponse: + Response message for campaign bid + modifiers mutate. + + """ + # 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 = [customer_id, operations] + 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, + campaign_bid_modifier_service.MutateCampaignBidModifiersRequest, + ): + request = ( + campaign_bid_modifier_service.MutateCampaignBidModifiersRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_campaign_bid_modifiers + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CampaignBidModifierServiceAsyncClient": + 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__ = ("CampaignBidModifierServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/client.py b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/client.py new file mode 100644 index 000000000..a93a56596 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/client.py @@ -0,0 +1,952 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + campaign_bid_modifier_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CampaignBidModifierServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CampaignBidModifierServiceGrpcTransport +from .transports.grpc_asyncio import ( + CampaignBidModifierServiceGrpcAsyncIOTransport, +) + + +class CampaignBidModifierServiceClientMeta(type): + """Metaclass for the CampaignBidModifierService 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[CampaignBidModifierServiceTransport]] + _transport_registry["grpc"] = CampaignBidModifierServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CampaignBidModifierServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignBidModifierServiceTransport]: + """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 CampaignBidModifierServiceClient( + metaclass=CampaignBidModifierServiceClientMeta +): + """Service to manage campaign bid modifiers.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CampaignBidModifierServiceClient: 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: + CampaignBidModifierServiceClient: 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) -> CampaignBidModifierServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignBidModifierServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_bid_modifier_path( + customer_id: str, + campaign_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified campaign_bid_modifier string.""" + return "customers/{customer_id}/campaignBidModifiers/{campaign_id}~{criterion_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_campaign_bid_modifier_path(path: str) -> Dict[str, str]: + """Parses a campaign_bid_modifier path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignBidModifiers/(?P.+?)~(?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 = ( + CampaignBidModifierServiceClient._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 = ( + CampaignBidModifierServiceClient._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 + ): + """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 = ( + CampaignBidModifierServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + CampaignBidModifierServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = CampaignBidModifierServiceClient._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 = CampaignBidModifierServiceClient._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): + """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, + CampaignBidModifierServiceTransport, + Callable[..., CampaignBidModifierServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign bid modifier 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,CampaignBidModifierServiceTransport,Callable[..., CampaignBidModifierServiceTransport]]]): + 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 CampaignBidModifierServiceTransport 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, + ) = CampaignBidModifierServiceClient._read_environment_variables() + self._client_cert_source = ( + CampaignBidModifierServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CampaignBidModifierServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CampaignBidModifierServiceTransport + ) + if transport_provided: + # transport is a CampaignBidModifierServiceTransport 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( + CampaignBidModifierServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CampaignBidModifierServiceClient._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[CampaignBidModifierServiceTransport], + Callable[..., CampaignBidModifierServiceTransport], + ] = ( + CampaignBidModifierServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CampaignBidModifierServiceTransport], + 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.ads.googleads.v24.services.CampaignBidModifierServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignBidModifierService", + "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.ads.googleads.v24.services.CampaignBidModifierService", + "credentialsType": None, + } + ), + ) + + def mutate_campaign_bid_modifiers( + self, + request: Optional[ + Union[ + campaign_bid_modifier_service.MutateCampaignBidModifiersRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_bid_modifier_service.CampaignBidModifierOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_bid_modifier_service.MutateCampaignBidModifiersResponse: + r"""Creates, updates, or removes campaign bid modifiers. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ContextError <>`__ + `CriterionError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCampaignBidModifiersRequest, dict]): + The request object. Request message for + [CampaignBidModifierService.MutateCampaignBidModifiers][google.ads.googleads.v24.services.CampaignBidModifierService.MutateCampaignBidModifiers]. + customer_id (str): + Required. ID of the customer whose + campaign bid modifiers are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignBidModifierOperation]): + Required. The list of operations to + perform on individual campaign bid + modifiers. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignBidModifiersResponse: + Response message for campaign bid + modifiers mutate. + + """ + # 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 = [customer_id, operations] + 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, + campaign_bid_modifier_service.MutateCampaignBidModifiersRequest, + ): + request = ( + campaign_bid_modifier_service.MutateCampaignBidModifiersRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_campaign_bid_modifiers + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CampaignBidModifierServiceClient": + 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() + + +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__ = ("CampaignBidModifierServiceClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/README.rst b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/README.rst new file mode 100644 index 000000000..40d672f08 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CampaignBidModifierServiceTransport` is the ABC for all transports. +- public child `CampaignBidModifierServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CampaignBidModifierServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCampaignBidModifierServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CampaignBidModifierServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/__init__.py b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/__init__.py new file mode 100644 index 000000000..fb9466447 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CampaignBidModifierServiceTransport +from .grpc import CampaignBidModifierServiceGrpcTransport +from .grpc_asyncio import CampaignBidModifierServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignBidModifierServiceTransport]] +_transport_registry["grpc"] = CampaignBidModifierServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CampaignBidModifierServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CampaignBidModifierServiceTransport", + "CampaignBidModifierServiceGrpcTransport", + "CampaignBidModifierServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/base.py b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/base.py new file mode 100644 index 000000000..c6a5e8cda --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + campaign_bid_modifier_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 CampaignBidModifierServiceTransport(abc.ABC): + """Abstract transport class for CampaignBidModifierService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaign_bid_modifiers: gapic_v1.method.wrap_method( + self.mutate_campaign_bid_modifiers, + 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 mutate_campaign_bid_modifiers( + self, + ) -> Callable[ + [campaign_bid_modifier_service.MutateCampaignBidModifiersRequest], + Union[ + campaign_bid_modifier_service.MutateCampaignBidModifiersResponse, + Awaitable[ + campaign_bid_modifier_service.MutateCampaignBidModifiersResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CampaignBidModifierServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/grpc.py b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/grpc.py new file mode 100644 index 000000000..c22cc588d --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/grpc.py @@ -0,0 +1,398 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + campaign_bid_modifier_service, +) +from .base import CampaignBidModifierServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignBidModifierService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignBidModifierService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignBidModifierServiceGrpcTransport( + CampaignBidModifierServiceTransport +): + """gRPC backend transport for CampaignBidModifierService. + + Service to manage campaign bid modifiers. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_campaign_bid_modifiers( + self, + ) -> Callable[ + [campaign_bid_modifier_service.MutateCampaignBidModifiersRequest], + campaign_bid_modifier_service.MutateCampaignBidModifiersResponse, + ]: + r"""Return a callable for the mutate campaign bid modifiers method over gRPC. + + Creates, updates, or removes campaign bid modifiers. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ContextError <>`__ + `CriterionError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateCampaignBidModifiersRequest], + ~.MutateCampaignBidModifiersResponse]: + 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 "mutate_campaign_bid_modifiers" not in self._stubs: + self._stubs["mutate_campaign_bid_modifiers"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignBidModifierService/MutateCampaignBidModifiers", + request_serializer=campaign_bid_modifier_service.MutateCampaignBidModifiersRequest.serialize, + response_deserializer=campaign_bid_modifier_service.MutateCampaignBidModifiersResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_bid_modifiers"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CampaignBidModifierServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..a4b704576 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_bid_modifier_service/transports/grpc_asyncio.py @@ -0,0 +1,421 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + campaign_bid_modifier_service, +) +from .base import CampaignBidModifierServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignBidModifierService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignBidModifierService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignBidModifierServiceGrpcAsyncIOTransport( + CampaignBidModifierServiceTransport +): + """gRPC AsyncIO backend transport for CampaignBidModifierService. + + Service to manage campaign bid modifiers. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_campaign_bid_modifiers( + self, + ) -> Callable[ + [campaign_bid_modifier_service.MutateCampaignBidModifiersRequest], + Awaitable[ + campaign_bid_modifier_service.MutateCampaignBidModifiersResponse + ], + ]: + r"""Return a callable for the mutate campaign bid modifiers method over gRPC. + + Creates, updates, or removes campaign bid modifiers. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ContextError <>`__ + `CriterionError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateCampaignBidModifiersRequest], + Awaitable[~.MutateCampaignBidModifiersResponse]]: + 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 "mutate_campaign_bid_modifiers" not in self._stubs: + self._stubs["mutate_campaign_bid_modifiers"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignBidModifierService/MutateCampaignBidModifiers", + request_serializer=campaign_bid_modifier_service.MutateCampaignBidModifiersRequest.serialize, + response_deserializer=campaign_bid_modifier_service.MutateCampaignBidModifiersResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_bid_modifiers"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_campaign_bid_modifiers: self._wrap_method( + self.mutate_campaign_bid_modifiers, + 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" + + +__all__ = ("CampaignBidModifierServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_budget_service/__init__.py b/google/ads/googleads/v24/services/services/campaign_budget_service/__init__.py new file mode 100644 index 000000000..1b76d8948 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_budget_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CampaignBudgetServiceClient +from .async_client import CampaignBudgetServiceAsyncClient + +__all__ = ( + "CampaignBudgetServiceClient", + "CampaignBudgetServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/campaign_budget_service/async_client.py b/google/ads/googleads/v24/services/services/campaign_budget_service/async_client.py new file mode 100644 index 000000000..2fdb78977 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_budget_service/async_client.py @@ -0,0 +1,430 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import campaign_budget_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CampaignBudgetServiceTransport, DEFAULT_CLIENT_INFO +from .client import CampaignBudgetServiceClient + +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 CampaignBudgetServiceAsyncClient: + """Service to manage campaign budgets.""" + + _client: CampaignBudgetServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CampaignBudgetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CampaignBudgetServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CampaignBudgetServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CampaignBudgetServiceClient._DEFAULT_UNIVERSE + + campaign_budget_path = staticmethod( + CampaignBudgetServiceClient.campaign_budget_path + ) + parse_campaign_budget_path = staticmethod( + CampaignBudgetServiceClient.parse_campaign_budget_path + ) + common_billing_account_path = staticmethod( + CampaignBudgetServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CampaignBudgetServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CampaignBudgetServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CampaignBudgetServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CampaignBudgetServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CampaignBudgetServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CampaignBudgetServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CampaignBudgetServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CampaignBudgetServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CampaignBudgetServiceClient.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: + CampaignBudgetServiceAsyncClient: The constructed client. + """ + return CampaignBudgetServiceClient.from_service_account_info.__func__(CampaignBudgetServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CampaignBudgetServiceAsyncClient: The constructed client. + """ + return CampaignBudgetServiceClient.from_service_account_file.__func__(CampaignBudgetServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CampaignBudgetServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CampaignBudgetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignBudgetServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CampaignBudgetServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CampaignBudgetServiceTransport, + Callable[..., CampaignBudgetServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign budget 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,CampaignBudgetServiceTransport,Callable[..., CampaignBudgetServiceTransport]]]): + 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 CampaignBudgetServiceTransport 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 = CampaignBudgetServiceClient( + 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.ads.googleads.v24.services.CampaignBudgetServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignBudgetService", + "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.ads.googleads.v24.services.CampaignBudgetService", + "credentialsType": None, + } + ), + ) + + async def mutate_campaign_budgets( + self, + request: Optional[ + Union[campaign_budget_service.MutateCampaignBudgetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_budget_service.CampaignBudgetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_budget_service.MutateCampaignBudgetsResponse: + r"""Creates, updates, or removes campaign budgets. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignBudgetError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `OperationAccessDeniedError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `StringLengthError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCampaignBudgetsRequest, dict]]): + The request object. Request message for + [CampaignBudgetService.MutateCampaignBudgets][google.ads.googleads.v24.services.CampaignBudgetService.MutateCampaignBudgets]. + customer_id (:class:`str`): + Required. The ID of the customer + whose campaign budgets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CampaignBudgetOperation]`): + Required. The list of operations to + perform on individual campaign budgets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignBudgetsResponse: + Response message for campaign budget + mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_budget_service.MutateCampaignBudgetsRequest + ): + request = campaign_budget_service.MutateCampaignBudgetsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_campaign_budgets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CampaignBudgetServiceAsyncClient": + 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__ = ("CampaignBudgetServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_budget_service/client.py b/google/ads/googleads/v24/services/services/campaign_budget_service/client.py new file mode 100644 index 000000000..5c9247c19 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_budget_service/client.py @@ -0,0 +1,906 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import campaign_budget_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CampaignBudgetServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CampaignBudgetServiceGrpcTransport +from .transports.grpc_asyncio import CampaignBudgetServiceGrpcAsyncIOTransport + + +class CampaignBudgetServiceClientMeta(type): + """Metaclass for the CampaignBudgetService 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[CampaignBudgetServiceTransport]] + _transport_registry["grpc"] = CampaignBudgetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CampaignBudgetServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignBudgetServiceTransport]: + """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 CampaignBudgetServiceClient(metaclass=CampaignBudgetServiceClientMeta): + """Service to manage campaign budgets.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CampaignBudgetServiceClient: 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: + CampaignBudgetServiceClient: 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) -> CampaignBudgetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignBudgetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_budget_path( + customer_id: str, + campaign_budget_id: str, + ) -> str: + """Returns a fully-qualified campaign_budget string.""" + return "customers/{customer_id}/campaignBudgets/{campaign_budget_id}".format( + customer_id=customer_id, + campaign_budget_id=campaign_budget_id, + ) + + @staticmethod + def parse_campaign_budget_path(path: str) -> Dict[str, str]: + """Parses a campaign_budget path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignBudgets/(?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 = ( + CampaignBudgetServiceClient._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 = ( + CampaignBudgetServiceClient._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 + ): + """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 = CampaignBudgetServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CampaignBudgetServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + CampaignBudgetServiceClient._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 = CampaignBudgetServiceClient._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): + """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, + CampaignBudgetServiceTransport, + Callable[..., CampaignBudgetServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign budget 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,CampaignBudgetServiceTransport,Callable[..., CampaignBudgetServiceTransport]]]): + 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 CampaignBudgetServiceTransport 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, + ) = CampaignBudgetServiceClient._read_environment_variables() + self._client_cert_source = ( + CampaignBudgetServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CampaignBudgetServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CampaignBudgetServiceTransport + ) + if transport_provided: + # transport is a CampaignBudgetServiceTransport 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(CampaignBudgetServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CampaignBudgetServiceClient._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[CampaignBudgetServiceTransport], + Callable[..., CampaignBudgetServiceTransport], + ] = ( + CampaignBudgetServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CampaignBudgetServiceTransport], 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.ads.googleads.v24.services.CampaignBudgetServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignBudgetService", + "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.ads.googleads.v24.services.CampaignBudgetService", + "credentialsType": None, + } + ), + ) + + def mutate_campaign_budgets( + self, + request: Optional[ + Union[campaign_budget_service.MutateCampaignBudgetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_budget_service.CampaignBudgetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_budget_service.MutateCampaignBudgetsResponse: + r"""Creates, updates, or removes campaign budgets. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignBudgetError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `OperationAccessDeniedError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCampaignBudgetsRequest, dict]): + The request object. Request message for + [CampaignBudgetService.MutateCampaignBudgets][google.ads.googleads.v24.services.CampaignBudgetService.MutateCampaignBudgets]. + customer_id (str): + Required. The ID of the customer + whose campaign budgets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignBudgetOperation]): + Required. The list of operations to + perform on individual campaign budgets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignBudgetsResponse: + Response message for campaign budget + mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_budget_service.MutateCampaignBudgetsRequest + ): + request = campaign_budget_service.MutateCampaignBudgetsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_campaign_budgets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CampaignBudgetServiceClient": + 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() + + +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__ = ("CampaignBudgetServiceClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_budget_service/transports/README.rst b/google/ads/googleads/v24/services/services/campaign_budget_service/transports/README.rst new file mode 100644 index 000000000..0b2d94eea --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_budget_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CampaignBudgetServiceTransport` is the ABC for all transports. +- public child `CampaignBudgetServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CampaignBudgetServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCampaignBudgetServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CampaignBudgetServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/campaign_budget_service/transports/__init__.py b/google/ads/googleads/v24/services/services/campaign_budget_service/transports/__init__.py new file mode 100644 index 000000000..e35958f44 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_budget_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CampaignBudgetServiceTransport +from .grpc import CampaignBudgetServiceGrpcTransport +from .grpc_asyncio import CampaignBudgetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignBudgetServiceTransport]] +_transport_registry["grpc"] = CampaignBudgetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = CampaignBudgetServiceGrpcAsyncIOTransport + +__all__ = ( + "CampaignBudgetServiceTransport", + "CampaignBudgetServiceGrpcTransport", + "CampaignBudgetServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/campaign_budget_service/transports/base.py b/google/ads/googleads/v24/services/services/campaign_budget_service/transports/base.py new file mode 100644 index 000000000..130454f23 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_budget_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import campaign_budget_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 CampaignBudgetServiceTransport(abc.ABC): + """Abstract transport class for CampaignBudgetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaign_budgets: gapic_v1.method.wrap_method( + self.mutate_campaign_budgets, + 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 mutate_campaign_budgets( + self, + ) -> Callable[ + [campaign_budget_service.MutateCampaignBudgetsRequest], + Union[ + campaign_budget_service.MutateCampaignBudgetsResponse, + Awaitable[campaign_budget_service.MutateCampaignBudgetsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CampaignBudgetServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_budget_service/transports/grpc.py b/google/ads/googleads/v24/services/services/campaign_budget_service/transports/grpc.py new file mode 100644 index 000000000..7ac94b8d3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_budget_service/transports/grpc.py @@ -0,0 +1,393 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import campaign_budget_service +from .base import CampaignBudgetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignBudgetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignBudgetService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignBudgetServiceGrpcTransport(CampaignBudgetServiceTransport): + """gRPC backend transport for CampaignBudgetService. + + Service to manage campaign budgets. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_campaign_budgets( + self, + ) -> Callable[ + [campaign_budget_service.MutateCampaignBudgetsRequest], + campaign_budget_service.MutateCampaignBudgetsResponse, + ]: + r"""Return a callable for the mutate campaign budgets method over gRPC. + + Creates, updates, or removes campaign budgets. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignBudgetError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `OperationAccessDeniedError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateCampaignBudgetsRequest], + ~.MutateCampaignBudgetsResponse]: + 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 "mutate_campaign_budgets" not in self._stubs: + self._stubs["mutate_campaign_budgets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignBudgetService/MutateCampaignBudgets", + request_serializer=campaign_budget_service.MutateCampaignBudgetsRequest.serialize, + response_deserializer=campaign_budget_service.MutateCampaignBudgetsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_budgets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CampaignBudgetServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_budget_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/campaign_budget_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..d0f6f1c90 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_budget_service/transports/grpc_asyncio.py @@ -0,0 +1,414 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import campaign_budget_service +from .base import CampaignBudgetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignBudgetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignBudgetService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignBudgetServiceGrpcAsyncIOTransport(CampaignBudgetServiceTransport): + """gRPC AsyncIO backend transport for CampaignBudgetService. + + Service to manage campaign budgets. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_campaign_budgets( + self, + ) -> Callable[ + [campaign_budget_service.MutateCampaignBudgetsRequest], + Awaitable[campaign_budget_service.MutateCampaignBudgetsResponse], + ]: + r"""Return a callable for the mutate campaign budgets method over gRPC. + + Creates, updates, or removes campaign budgets. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignBudgetError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `OperationAccessDeniedError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateCampaignBudgetsRequest], + Awaitable[~.MutateCampaignBudgetsResponse]]: + 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 "mutate_campaign_budgets" not in self._stubs: + self._stubs["mutate_campaign_budgets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignBudgetService/MutateCampaignBudgets", + request_serializer=campaign_budget_service.MutateCampaignBudgetsRequest.serialize, + response_deserializer=campaign_budget_service.MutateCampaignBudgetsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_budgets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_campaign_budgets: self._wrap_method( + self.mutate_campaign_budgets, + 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" + + +__all__ = ("CampaignBudgetServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/__init__.py b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/__init__.py new file mode 100644 index 000000000..19d4cde4c --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CampaignConversionGoalServiceClient +from .async_client import CampaignConversionGoalServiceAsyncClient + +__all__ = ( + "CampaignConversionGoalServiceClient", + "CampaignConversionGoalServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/async_client.py b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/async_client.py new file mode 100644 index 000000000..b9fb4f26e --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/async_client.py @@ -0,0 +1,442 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + campaign_conversion_goal_service, +) +from .transports.base import ( + CampaignConversionGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CampaignConversionGoalServiceClient + +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 CampaignConversionGoalServiceAsyncClient: + """Service to manage campaign conversion goal.""" + + _client: CampaignConversionGoalServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CampaignConversionGoalServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + CampaignConversionGoalServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CampaignConversionGoalServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CampaignConversionGoalServiceClient._DEFAULT_UNIVERSE + + campaign_path = staticmethod( + CampaignConversionGoalServiceClient.campaign_path + ) + parse_campaign_path = staticmethod( + CampaignConversionGoalServiceClient.parse_campaign_path + ) + campaign_conversion_goal_path = staticmethod( + CampaignConversionGoalServiceClient.campaign_conversion_goal_path + ) + parse_campaign_conversion_goal_path = staticmethod( + CampaignConversionGoalServiceClient.parse_campaign_conversion_goal_path + ) + common_billing_account_path = staticmethod( + CampaignConversionGoalServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CampaignConversionGoalServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CampaignConversionGoalServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CampaignConversionGoalServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CampaignConversionGoalServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CampaignConversionGoalServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CampaignConversionGoalServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CampaignConversionGoalServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CampaignConversionGoalServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CampaignConversionGoalServiceClient.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: + CampaignConversionGoalServiceAsyncClient: The constructed client. + """ + return CampaignConversionGoalServiceClient.from_service_account_info.__func__(CampaignConversionGoalServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CampaignConversionGoalServiceAsyncClient: The constructed client. + """ + return CampaignConversionGoalServiceClient.from_service_account_file.__func__(CampaignConversionGoalServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CampaignConversionGoalServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CampaignConversionGoalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignConversionGoalServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + CampaignConversionGoalServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CampaignConversionGoalServiceTransport, + Callable[..., CampaignConversionGoalServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign conversion goal 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,CampaignConversionGoalServiceTransport,Callable[..., CampaignConversionGoalServiceTransport]]]): + 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 CampaignConversionGoalServiceTransport 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 = CampaignConversionGoalServiceClient( + 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.ads.googleads.v24.services.CampaignConversionGoalServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignConversionGoalService", + "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.ads.googleads.v24.services.CampaignConversionGoalService", + "credentialsType": None, + } + ), + ) + + async def mutate_campaign_conversion_goals( + self, + request: Optional[ + Union[ + campaign_conversion_goal_service.MutateCampaignConversionGoalsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_conversion_goal_service.CampaignConversionGoalOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_conversion_goal_service.MutateCampaignConversionGoalsResponse: + r"""Creates, updates or removes campaign conversion + goals. Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCampaignConversionGoalsRequest, dict]]): + The request object. Request message for + [CampaignConversionGoalService.MutateCampaignConversionGoals][google.ads.googleads.v24.services.CampaignConversionGoalService.MutateCampaignConversionGoals]. + customer_id (:class:`str`): + Required. The ID of the customer + whose campaign conversion goals are + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CampaignConversionGoalOperation]`): + Required. The list of operations to + perform on individual campaign + conversion goal. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignConversionGoalsResponse: + Response message for a campaign + conversion goal mutate. + + """ + # 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 = [customer_id, operations] + 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, + campaign_conversion_goal_service.MutateCampaignConversionGoalsRequest, + ): + request = campaign_conversion_goal_service.MutateCampaignConversionGoalsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_campaign_conversion_goals + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CampaignConversionGoalServiceAsyncClient": + 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__ = ("CampaignConversionGoalServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/client.py b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/client.py new file mode 100644 index 000000000..c8dff9291 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/client.py @@ -0,0 +1,943 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + campaign_conversion_goal_service, +) +from .transports.base import ( + CampaignConversionGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CampaignConversionGoalServiceGrpcTransport +from .transports.grpc_asyncio import ( + CampaignConversionGoalServiceGrpcAsyncIOTransport, +) + + +class CampaignConversionGoalServiceClientMeta(type): + """Metaclass for the CampaignConversionGoalService 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[CampaignConversionGoalServiceTransport]] + _transport_registry["grpc"] = CampaignConversionGoalServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CampaignConversionGoalServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignConversionGoalServiceTransport]: + """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 CampaignConversionGoalServiceClient( + metaclass=CampaignConversionGoalServiceClientMeta +): + """Service to manage campaign conversion goal.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CampaignConversionGoalServiceClient: 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: + CampaignConversionGoalServiceClient: 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) -> CampaignConversionGoalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignConversionGoalServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_conversion_goal_path( + customer_id: str, + campaign_id: str, + category: str, + source: str, + ) -> str: + """Returns a fully-qualified campaign_conversion_goal string.""" + return "customers/{customer_id}/campaignConversionGoals/{campaign_id}~{category}~{source}".format( + customer_id=customer_id, + campaign_id=campaign_id, + category=category, + source=source, + ) + + @staticmethod + def parse_campaign_conversion_goal_path(path: str) -> Dict[str, str]: + """Parses a campaign_conversion_goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignConversionGoals/(?P.+?)~(?P.+?)~(?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 = ( + CampaignConversionGoalServiceClient._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 = ( + CampaignConversionGoalServiceClient._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 + ): + """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 = ( + CampaignConversionGoalServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + CampaignConversionGoalServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = CampaignConversionGoalServiceClient._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 = CampaignConversionGoalServiceClient._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): + """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, + CampaignConversionGoalServiceTransport, + Callable[..., CampaignConversionGoalServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign conversion goal 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,CampaignConversionGoalServiceTransport,Callable[..., CampaignConversionGoalServiceTransport]]]): + 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 CampaignConversionGoalServiceTransport 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, + ) = CampaignConversionGoalServiceClient._read_environment_variables() + self._client_cert_source = ( + CampaignConversionGoalServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CampaignConversionGoalServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CampaignConversionGoalServiceTransport + ) + if transport_provided: + # transport is a CampaignConversionGoalServiceTransport 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( + CampaignConversionGoalServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CampaignConversionGoalServiceClient._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[CampaignConversionGoalServiceTransport], + Callable[..., CampaignConversionGoalServiceTransport], + ] = ( + CampaignConversionGoalServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CampaignConversionGoalServiceTransport], + 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.ads.googleads.v24.services.CampaignConversionGoalServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignConversionGoalService", + "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.ads.googleads.v24.services.CampaignConversionGoalService", + "credentialsType": None, + } + ), + ) + + def mutate_campaign_conversion_goals( + self, + request: Optional[ + Union[ + campaign_conversion_goal_service.MutateCampaignConversionGoalsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_conversion_goal_service.CampaignConversionGoalOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_conversion_goal_service.MutateCampaignConversionGoalsResponse: + r"""Creates, updates or removes campaign conversion + goals. Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCampaignConversionGoalsRequest, dict]): + The request object. Request message for + [CampaignConversionGoalService.MutateCampaignConversionGoals][google.ads.googleads.v24.services.CampaignConversionGoalService.MutateCampaignConversionGoals]. + customer_id (str): + Required. The ID of the customer + whose campaign conversion goals are + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignConversionGoalOperation]): + Required. The list of operations to + perform on individual campaign + conversion goal. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignConversionGoalsResponse: + Response message for a campaign + conversion goal mutate. + + """ + # 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 = [customer_id, operations] + 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, + campaign_conversion_goal_service.MutateCampaignConversionGoalsRequest, + ): + request = campaign_conversion_goal_service.MutateCampaignConversionGoalsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_campaign_conversion_goals + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CampaignConversionGoalServiceClient": + 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() + + +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__ = ("CampaignConversionGoalServiceClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/README.rst b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/README.rst new file mode 100644 index 000000000..f13a9b346 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CampaignConversionGoalServiceTransport` is the ABC for all transports. +- public child `CampaignConversionGoalServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CampaignConversionGoalServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCampaignConversionGoalServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CampaignConversionGoalServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/__init__.py b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/__init__.py new file mode 100644 index 000000000..e377debc2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CampaignConversionGoalServiceTransport +from .grpc import CampaignConversionGoalServiceGrpcTransport +from .grpc_asyncio import CampaignConversionGoalServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignConversionGoalServiceTransport]] +_transport_registry["grpc"] = CampaignConversionGoalServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CampaignConversionGoalServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CampaignConversionGoalServiceTransport", + "CampaignConversionGoalServiceGrpcTransport", + "CampaignConversionGoalServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/base.py b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/base.py new file mode 100644 index 000000000..98e4ce92d --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + campaign_conversion_goal_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 CampaignConversionGoalServiceTransport(abc.ABC): + """Abstract transport class for CampaignConversionGoalService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaign_conversion_goals: gapic_v1.method.wrap_method( + self.mutate_campaign_conversion_goals, + 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 mutate_campaign_conversion_goals( + self, + ) -> Callable[ + [campaign_conversion_goal_service.MutateCampaignConversionGoalsRequest], + Union[ + campaign_conversion_goal_service.MutateCampaignConversionGoalsResponse, + Awaitable[ + campaign_conversion_goal_service.MutateCampaignConversionGoalsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CampaignConversionGoalServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/grpc.py b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/grpc.py new file mode 100644 index 000000000..ae1d399f6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/grpc.py @@ -0,0 +1,389 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + campaign_conversion_goal_service, +) +from .base import CampaignConversionGoalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignConversionGoalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignConversionGoalService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignConversionGoalServiceGrpcTransport( + CampaignConversionGoalServiceTransport +): + """gRPC backend transport for CampaignConversionGoalService. + + Service to manage campaign conversion goal. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_campaign_conversion_goals( + self, + ) -> Callable[ + [campaign_conversion_goal_service.MutateCampaignConversionGoalsRequest], + campaign_conversion_goal_service.MutateCampaignConversionGoalsResponse, + ]: + r"""Return a callable for the mutate campaign conversion + goals method over gRPC. + + Creates, updates or removes campaign conversion + goals. Operation statuses are returned. + + Returns: + Callable[[~.MutateCampaignConversionGoalsRequest], + ~.MutateCampaignConversionGoalsResponse]: + 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 "mutate_campaign_conversion_goals" not in self._stubs: + self._stubs["mutate_campaign_conversion_goals"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignConversionGoalService/MutateCampaignConversionGoals", + request_serializer=campaign_conversion_goal_service.MutateCampaignConversionGoalsRequest.serialize, + response_deserializer=campaign_conversion_goal_service.MutateCampaignConversionGoalsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_conversion_goals"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CampaignConversionGoalServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..2989ed79b --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_conversion_goal_service/transports/grpc_asyncio.py @@ -0,0 +1,412 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + campaign_conversion_goal_service, +) +from .base import CampaignConversionGoalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignConversionGoalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignConversionGoalService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignConversionGoalServiceGrpcAsyncIOTransport( + CampaignConversionGoalServiceTransport +): + """gRPC AsyncIO backend transport for CampaignConversionGoalService. + + Service to manage campaign conversion goal. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_campaign_conversion_goals( + self, + ) -> Callable[ + [campaign_conversion_goal_service.MutateCampaignConversionGoalsRequest], + Awaitable[ + campaign_conversion_goal_service.MutateCampaignConversionGoalsResponse + ], + ]: + r"""Return a callable for the mutate campaign conversion + goals method over gRPC. + + Creates, updates or removes campaign conversion + goals. Operation statuses are returned. + + Returns: + Callable[[~.MutateCampaignConversionGoalsRequest], + Awaitable[~.MutateCampaignConversionGoalsResponse]]: + 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 "mutate_campaign_conversion_goals" not in self._stubs: + self._stubs["mutate_campaign_conversion_goals"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignConversionGoalService/MutateCampaignConversionGoals", + request_serializer=campaign_conversion_goal_service.MutateCampaignConversionGoalsRequest.serialize, + response_deserializer=campaign_conversion_goal_service.MutateCampaignConversionGoalsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_conversion_goals"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_campaign_conversion_goals: self._wrap_method( + self.mutate_campaign_conversion_goals, + 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" + + +__all__ = ("CampaignConversionGoalServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_criterion_service/__init__.py b/google/ads/googleads/v24/services/services/campaign_criterion_service/__init__.py new file mode 100644 index 000000000..bd8bef758 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_criterion_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CampaignCriterionServiceClient +from .async_client import CampaignCriterionServiceAsyncClient + +__all__ = ( + "CampaignCriterionServiceClient", + "CampaignCriterionServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/campaign_criterion_service/async_client.py b/google/ads/googleads/v24/services/services/campaign_criterion_service/async_client.py new file mode 100644 index 000000000..e7cddce79 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_criterion_service/async_client.py @@ -0,0 +1,487 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import campaign_criterion_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CampaignCriterionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CampaignCriterionServiceClient + +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 CampaignCriterionServiceAsyncClient: + """Service to manage campaign criteria.""" + + _client: CampaignCriterionServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CampaignCriterionServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CampaignCriterionServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CampaignCriterionServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CampaignCriterionServiceClient._DEFAULT_UNIVERSE + + campaign_path = staticmethod(CampaignCriterionServiceClient.campaign_path) + parse_campaign_path = staticmethod( + CampaignCriterionServiceClient.parse_campaign_path + ) + campaign_criterion_path = staticmethod( + CampaignCriterionServiceClient.campaign_criterion_path + ) + parse_campaign_criterion_path = staticmethod( + CampaignCriterionServiceClient.parse_campaign_criterion_path + ) + carrier_constant_path = staticmethod( + CampaignCriterionServiceClient.carrier_constant_path + ) + parse_carrier_constant_path = staticmethod( + CampaignCriterionServiceClient.parse_carrier_constant_path + ) + combined_audience_path = staticmethod( + CampaignCriterionServiceClient.combined_audience_path + ) + parse_combined_audience_path = staticmethod( + CampaignCriterionServiceClient.parse_combined_audience_path + ) + keyword_theme_constant_path = staticmethod( + CampaignCriterionServiceClient.keyword_theme_constant_path + ) + parse_keyword_theme_constant_path = staticmethod( + CampaignCriterionServiceClient.parse_keyword_theme_constant_path + ) + mobile_app_category_constant_path = staticmethod( + CampaignCriterionServiceClient.mobile_app_category_constant_path + ) + parse_mobile_app_category_constant_path = staticmethod( + CampaignCriterionServiceClient.parse_mobile_app_category_constant_path + ) + mobile_device_constant_path = staticmethod( + CampaignCriterionServiceClient.mobile_device_constant_path + ) + parse_mobile_device_constant_path = staticmethod( + CampaignCriterionServiceClient.parse_mobile_device_constant_path + ) + operating_system_version_constant_path = staticmethod( + CampaignCriterionServiceClient.operating_system_version_constant_path + ) + parse_operating_system_version_constant_path = staticmethod( + CampaignCriterionServiceClient.parse_operating_system_version_constant_path + ) + topic_constant_path = staticmethod( + CampaignCriterionServiceClient.topic_constant_path + ) + parse_topic_constant_path = staticmethod( + CampaignCriterionServiceClient.parse_topic_constant_path + ) + common_billing_account_path = staticmethod( + CampaignCriterionServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CampaignCriterionServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CampaignCriterionServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CampaignCriterionServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CampaignCriterionServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CampaignCriterionServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CampaignCriterionServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CampaignCriterionServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CampaignCriterionServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CampaignCriterionServiceClient.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: + CampaignCriterionServiceAsyncClient: The constructed client. + """ + return CampaignCriterionServiceClient.from_service_account_info.__func__(CampaignCriterionServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CampaignCriterionServiceAsyncClient: The constructed client. + """ + return CampaignCriterionServiceClient.from_service_account_file.__func__(CampaignCriterionServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CampaignCriterionServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CampaignCriterionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignCriterionServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CampaignCriterionServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CampaignCriterionServiceTransport, + Callable[..., CampaignCriterionServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign criterion 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,CampaignCriterionServiceTransport,Callable[..., CampaignCriterionServiceTransport]]]): + 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 CampaignCriterionServiceTransport 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 = CampaignCriterionServiceClient( + 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.ads.googleads.v24.services.CampaignCriterionServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignCriterionService", + "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.ads.googleads.v24.services.CampaignCriterionService", + "credentialsType": None, + } + ), + ) + + async def mutate_campaign_criteria( + self, + request: Optional[ + Union[ + campaign_criterion_service.MutateCampaignCriteriaRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_criterion_service.CampaignCriterionOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_criterion_service.MutateCampaignCriteriaResponse: + r"""Creates, updates, or removes criteria. Operation statuses are + returned. + + List of thrown errors: `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CampaignCriterionError <>`__ `CollectionSizeError <>`__ + `ContextError <>`__ `CriterionError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `FunctionError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RegionCodeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCampaignCriteriaRequest, dict]]): + The request object. Request message for + [CampaignCriterionService.MutateCampaignCriteria][google.ads.googleads.v24.services.CampaignCriterionService.MutateCampaignCriteria]. + customer_id (:class:`str`): + Required. The ID of the customer + whose criteria are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CampaignCriterionOperation]`): + Required. The list of operations to + perform on individual criteria. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignCriteriaResponse: + Response message for campaign + criterion mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_criterion_service.MutateCampaignCriteriaRequest + ): + request = campaign_criterion_service.MutateCampaignCriteriaRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_campaign_criteria + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CampaignCriterionServiceAsyncClient": + 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__ = ("CampaignCriterionServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_criterion_service/client.py b/google/ads/googleads/v24/services/services/campaign_criterion_service/client.py new file mode 100644 index 000000000..b75807890 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_criterion_service/client.py @@ -0,0 +1,1063 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import campaign_criterion_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CampaignCriterionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CampaignCriterionServiceGrpcTransport +from .transports.grpc_asyncio import ( + CampaignCriterionServiceGrpcAsyncIOTransport, +) + + +class CampaignCriterionServiceClientMeta(type): + """Metaclass for the CampaignCriterionService 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[CampaignCriterionServiceTransport]] + _transport_registry["grpc"] = CampaignCriterionServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CampaignCriterionServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignCriterionServiceTransport]: + """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 CampaignCriterionServiceClient( + metaclass=CampaignCriterionServiceClientMeta +): + """Service to manage campaign criteria.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CampaignCriterionServiceClient: 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: + CampaignCriterionServiceClient: 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) -> CampaignCriterionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignCriterionServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_criterion_path( + customer_id: str, + campaign_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified campaign_criterion string.""" + return "customers/{customer_id}/campaignCriteria/{campaign_id}~{criterion_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_campaign_criterion_path(path: str) -> Dict[str, str]: + """Parses a campaign_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignCriteria/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def carrier_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified carrier_constant string.""" + return "carrierConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_carrier_constant_path(path: str) -> Dict[str, str]: + """Parses a carrier_constant path into its component segments.""" + m = re.match(r"^carrierConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def combined_audience_path( + customer_id: str, + combined_audience_id: str, + ) -> str: + """Returns a fully-qualified combined_audience string.""" + return "customers/{customer_id}/combinedAudiences/{combined_audience_id}".format( + customer_id=customer_id, + combined_audience_id=combined_audience_id, + ) + + @staticmethod + def parse_combined_audience_path(path: str) -> Dict[str, str]: + """Parses a combined_audience path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/combinedAudiences/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_theme_constant_path( + express_category_id: str, + express_sub_category_id: str, + ) -> str: + """Returns a fully-qualified keyword_theme_constant string.""" + return "keywordThemeConstants/{express_category_id}~{express_sub_category_id}".format( + express_category_id=express_category_id, + express_sub_category_id=express_sub_category_id, + ) + + @staticmethod + def parse_keyword_theme_constant_path(path: str) -> Dict[str, str]: + """Parses a keyword_theme_constant path into its component segments.""" + m = re.match( + r"^keywordThemeConstants/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def mobile_app_category_constant_path( + mobile_app_category_id: str, + ) -> str: + """Returns a fully-qualified mobile_app_category_constant string.""" + return "mobileAppCategoryConstants/{mobile_app_category_id}".format( + mobile_app_category_id=mobile_app_category_id, + ) + + @staticmethod + def parse_mobile_app_category_constant_path(path: str) -> Dict[str, str]: + """Parses a mobile_app_category_constant path into its component segments.""" + m = re.match( + r"^mobileAppCategoryConstants/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def mobile_device_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified mobile_device_constant string.""" + return "mobileDeviceConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_mobile_device_constant_path(path: str) -> Dict[str, str]: + """Parses a mobile_device_constant path into its component segments.""" + m = re.match(r"^mobileDeviceConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def operating_system_version_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified operating_system_version_constant string.""" + return "operatingSystemVersionConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_operating_system_version_constant_path( + path: str, + ) -> Dict[str, str]: + """Parses a operating_system_version_constant path into its component segments.""" + m = re.match( + r"^operatingSystemVersionConstants/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def topic_constant_path( + topic_id: str, + ) -> str: + """Returns a fully-qualified topic_constant string.""" + return "topicConstants/{topic_id}".format( + topic_id=topic_id, + ) + + @staticmethod + def parse_topic_constant_path(path: str) -> Dict[str, str]: + """Parses a topic_constant path into its component segments.""" + m = re.match(r"^topicConstants/(?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 = ( + CampaignCriterionServiceClient._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 = ( + CampaignCriterionServiceClient._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 + ): + """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 = CampaignCriterionServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CampaignCriterionServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = CampaignCriterionServiceClient._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 = CampaignCriterionServiceClient._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): + """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, + CampaignCriterionServiceTransport, + Callable[..., CampaignCriterionServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign criterion 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,CampaignCriterionServiceTransport,Callable[..., CampaignCriterionServiceTransport]]]): + 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 CampaignCriterionServiceTransport 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, + ) = CampaignCriterionServiceClient._read_environment_variables() + self._client_cert_source = ( + CampaignCriterionServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CampaignCriterionServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CampaignCriterionServiceTransport + ) + if transport_provided: + # transport is a CampaignCriterionServiceTransport 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(CampaignCriterionServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CampaignCriterionServiceClient._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[CampaignCriterionServiceTransport], + Callable[..., CampaignCriterionServiceTransport], + ] = ( + CampaignCriterionServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CampaignCriterionServiceTransport], 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.ads.googleads.v24.services.CampaignCriterionServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignCriterionService", + "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.ads.googleads.v24.services.CampaignCriterionService", + "credentialsType": None, + } + ), + ) + + def mutate_campaign_criteria( + self, + request: Optional[ + Union[ + campaign_criterion_service.MutateCampaignCriteriaRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_criterion_service.CampaignCriterionOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_criterion_service.MutateCampaignCriteriaResponse: + r"""Creates, updates, or removes criteria. Operation statuses are + returned. + + List of thrown errors: `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CampaignCriterionError <>`__ `CollectionSizeError <>`__ + `ContextError <>`__ `CriterionError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `FunctionError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RegionCodeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCampaignCriteriaRequest, dict]): + The request object. Request message for + [CampaignCriterionService.MutateCampaignCriteria][google.ads.googleads.v24.services.CampaignCriterionService.MutateCampaignCriteria]. + customer_id (str): + Required. The ID of the customer + whose criteria are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignCriterionOperation]): + Required. The list of operations to + perform on individual criteria. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignCriteriaResponse: + Response message for campaign + criterion mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_criterion_service.MutateCampaignCriteriaRequest + ): + request = campaign_criterion_service.MutateCampaignCriteriaRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_campaign_criteria + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CampaignCriterionServiceClient": + 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() + + +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__ = ("CampaignCriterionServiceClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/README.rst b/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/README.rst new file mode 100644 index 000000000..1ca0443a5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CampaignCriterionServiceTransport` is the ABC for all transports. +- public child `CampaignCriterionServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CampaignCriterionServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCampaignCriterionServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CampaignCriterionServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/__init__.py b/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/__init__.py new file mode 100644 index 000000000..3f023f65d --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CampaignCriterionServiceTransport +from .grpc import CampaignCriterionServiceGrpcTransport +from .grpc_asyncio import CampaignCriterionServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignCriterionServiceTransport]] +_transport_registry["grpc"] = CampaignCriterionServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CampaignCriterionServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CampaignCriterionServiceTransport", + "CampaignCriterionServiceGrpcTransport", + "CampaignCriterionServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/base.py b/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/base.py new file mode 100644 index 000000000..cdde52764 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import campaign_criterion_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 CampaignCriterionServiceTransport(abc.ABC): + """Abstract transport class for CampaignCriterionService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaign_criteria: gapic_v1.method.wrap_method( + self.mutate_campaign_criteria, + 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 mutate_campaign_criteria( + self, + ) -> Callable[ + [campaign_criterion_service.MutateCampaignCriteriaRequest], + Union[ + campaign_criterion_service.MutateCampaignCriteriaResponse, + Awaitable[ + campaign_criterion_service.MutateCampaignCriteriaResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CampaignCriterionServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/grpc.py b/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/grpc.py new file mode 100644 index 000000000..91d6d4320 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/grpc.py @@ -0,0 +1,398 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import campaign_criterion_service +from .base import CampaignCriterionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignCriterionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignCriterionService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignCriterionServiceGrpcTransport(CampaignCriterionServiceTransport): + """gRPC backend transport for CampaignCriterionService. + + Service to manage campaign criteria. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_campaign_criteria( + self, + ) -> Callable[ + [campaign_criterion_service.MutateCampaignCriteriaRequest], + campaign_criterion_service.MutateCampaignCriteriaResponse, + ]: + r"""Return a callable for the mutate campaign criteria method over gRPC. + + Creates, updates, or removes criteria. Operation statuses are + returned. + + List of thrown errors: `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CampaignCriterionError <>`__ `CollectionSizeError <>`__ + `ContextError <>`__ `CriterionError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `FunctionError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RegionCodeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateCampaignCriteriaRequest], + ~.MutateCampaignCriteriaResponse]: + 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 "mutate_campaign_criteria" not in self._stubs: + self._stubs["mutate_campaign_criteria"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignCriterionService/MutateCampaignCriteria", + request_serializer=campaign_criterion_service.MutateCampaignCriteriaRequest.serialize, + response_deserializer=campaign_criterion_service.MutateCampaignCriteriaResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_criteria"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CampaignCriterionServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..4fff4700d --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_criterion_service/transports/grpc_asyncio.py @@ -0,0 +1,421 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import campaign_criterion_service +from .base import CampaignCriterionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignCriterionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignCriterionService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignCriterionServiceGrpcAsyncIOTransport( + CampaignCriterionServiceTransport +): + """gRPC AsyncIO backend transport for CampaignCriterionService. + + Service to manage campaign criteria. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_campaign_criteria( + self, + ) -> Callable[ + [campaign_criterion_service.MutateCampaignCriteriaRequest], + Awaitable[campaign_criterion_service.MutateCampaignCriteriaResponse], + ]: + r"""Return a callable for the mutate campaign criteria method over gRPC. + + Creates, updates, or removes criteria. Operation statuses are + returned. + + List of thrown errors: `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CampaignCriterionError <>`__ `CollectionSizeError <>`__ + `ContextError <>`__ `CriterionError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `FunctionError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RegionCodeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateCampaignCriteriaRequest], + Awaitable[~.MutateCampaignCriteriaResponse]]: + 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 "mutate_campaign_criteria" not in self._stubs: + self._stubs["mutate_campaign_criteria"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignCriterionService/MutateCampaignCriteria", + request_serializer=campaign_criterion_service.MutateCampaignCriteriaRequest.serialize, + response_deserializer=campaign_criterion_service.MutateCampaignCriteriaResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_criteria"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_campaign_criteria: self._wrap_method( + self.mutate_campaign_criteria, + 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" + + +__all__ = ("CampaignCriterionServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_customizer_service/__init__.py b/google/ads/googleads/v24/services/services/campaign_customizer_service/__init__.py new file mode 100644 index 000000000..44eb2026a --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_customizer_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CampaignCustomizerServiceClient +from .async_client import CampaignCustomizerServiceAsyncClient + +__all__ = ( + "CampaignCustomizerServiceClient", + "CampaignCustomizerServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/campaign_customizer_service/async_client.py b/google/ads/googleads/v24/services/services/campaign_customizer_service/async_client.py new file mode 100644 index 000000000..bed1a7862 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_customizer_service/async_client.py @@ -0,0 +1,445 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import campaign_customizer_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CampaignCustomizerServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CampaignCustomizerServiceClient + +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 CampaignCustomizerServiceAsyncClient: + """Service to manage campaign customizer""" + + _client: CampaignCustomizerServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CampaignCustomizerServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + CampaignCustomizerServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CampaignCustomizerServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CampaignCustomizerServiceClient._DEFAULT_UNIVERSE + + campaign_path = staticmethod(CampaignCustomizerServiceClient.campaign_path) + parse_campaign_path = staticmethod( + CampaignCustomizerServiceClient.parse_campaign_path + ) + campaign_customizer_path = staticmethod( + CampaignCustomizerServiceClient.campaign_customizer_path + ) + parse_campaign_customizer_path = staticmethod( + CampaignCustomizerServiceClient.parse_campaign_customizer_path + ) + customizer_attribute_path = staticmethod( + CampaignCustomizerServiceClient.customizer_attribute_path + ) + parse_customizer_attribute_path = staticmethod( + CampaignCustomizerServiceClient.parse_customizer_attribute_path + ) + common_billing_account_path = staticmethod( + CampaignCustomizerServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CampaignCustomizerServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CampaignCustomizerServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CampaignCustomizerServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CampaignCustomizerServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CampaignCustomizerServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CampaignCustomizerServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CampaignCustomizerServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CampaignCustomizerServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CampaignCustomizerServiceClient.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: + CampaignCustomizerServiceAsyncClient: The constructed client. + """ + return CampaignCustomizerServiceClient.from_service_account_info.__func__(CampaignCustomizerServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CampaignCustomizerServiceAsyncClient: The constructed client. + """ + return CampaignCustomizerServiceClient.from_service_account_file.__func__(CampaignCustomizerServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CampaignCustomizerServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CampaignCustomizerServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignCustomizerServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CampaignCustomizerServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CampaignCustomizerServiceTransport, + Callable[..., CampaignCustomizerServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign customizer 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,CampaignCustomizerServiceTransport,Callable[..., CampaignCustomizerServiceTransport]]]): + 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 CampaignCustomizerServiceTransport 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 = CampaignCustomizerServiceClient( + 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.ads.googleads.v24.services.CampaignCustomizerServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignCustomizerService", + "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.ads.googleads.v24.services.CampaignCustomizerService", + "credentialsType": None, + } + ), + ) + + async def mutate_campaign_customizers( + self, + request: Optional[ + Union[ + campaign_customizer_service.MutateCampaignCustomizersRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_customizer_service.CampaignCustomizerOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_customizer_service.MutateCampaignCustomizersResponse: + r"""Creates, updates or removes campaign customizers. + Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCampaignCustomizersRequest, dict]]): + The request object. Request message for + [CampaignCustomizerService.MutateCampaignCustomizers][google.ads.googleads.v24.services.CampaignCustomizerService.MutateCampaignCustomizers]. + customer_id (:class:`str`): + Required. The ID of the customer + whose campaign customizers are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CampaignCustomizerOperation]`): + Required. The list of operations to + perform on individual campaign + customizers. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignCustomizersResponse: + Response message for a campaign + customizer mutate. + + """ + # 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 = [customer_id, operations] + 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, + campaign_customizer_service.MutateCampaignCustomizersRequest, + ): + request = ( + campaign_customizer_service.MutateCampaignCustomizersRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_campaign_customizers + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CampaignCustomizerServiceAsyncClient": + 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__ = ("CampaignCustomizerServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_customizer_service/client.py b/google/ads/googleads/v24/services/services/campaign_customizer_service/client.py new file mode 100644 index 000000000..6277a149a --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_customizer_service/client.py @@ -0,0 +1,957 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import campaign_customizer_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CampaignCustomizerServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CampaignCustomizerServiceGrpcTransport +from .transports.grpc_asyncio import ( + CampaignCustomizerServiceGrpcAsyncIOTransport, +) + + +class CampaignCustomizerServiceClientMeta(type): + """Metaclass for the CampaignCustomizerService 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[CampaignCustomizerServiceTransport]] + _transport_registry["grpc"] = CampaignCustomizerServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CampaignCustomizerServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignCustomizerServiceTransport]: + """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 CampaignCustomizerServiceClient( + metaclass=CampaignCustomizerServiceClientMeta +): + """Service to manage campaign customizer""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CampaignCustomizerServiceClient: 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: + CampaignCustomizerServiceClient: 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) -> CampaignCustomizerServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignCustomizerServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_customizer_path( + customer_id: str, + campaign_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified campaign_customizer string.""" + return "customers/{customer_id}/campaignCustomizers/{campaign_id}~{customizer_attribute_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_campaign_customizer_path(path: str) -> Dict[str, str]: + """Parses a campaign_customizer path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignCustomizers/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customizer_attribute_path( + customer_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified customizer_attribute string.""" + return "customers/{customer_id}/customizerAttributes/{customizer_attribute_id}".format( + customer_id=customer_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_customizer_attribute_path(path: str) -> Dict[str, str]: + """Parses a customizer_attribute path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customizerAttributes/(?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 = ( + CampaignCustomizerServiceClient._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 = ( + CampaignCustomizerServiceClient._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 + ): + """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 = ( + CampaignCustomizerServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CampaignCustomizerServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = CampaignCustomizerServiceClient._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 = CampaignCustomizerServiceClient._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): + """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, + CampaignCustomizerServiceTransport, + Callable[..., CampaignCustomizerServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign customizer 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,CampaignCustomizerServiceTransport,Callable[..., CampaignCustomizerServiceTransport]]]): + 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 CampaignCustomizerServiceTransport 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, + ) = CampaignCustomizerServiceClient._read_environment_variables() + self._client_cert_source = ( + CampaignCustomizerServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CampaignCustomizerServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CampaignCustomizerServiceTransport + ) + if transport_provided: + # transport is a CampaignCustomizerServiceTransport 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( + CampaignCustomizerServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CampaignCustomizerServiceClient._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[CampaignCustomizerServiceTransport], + Callable[..., CampaignCustomizerServiceTransport], + ] = ( + CampaignCustomizerServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CampaignCustomizerServiceTransport], 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.ads.googleads.v24.services.CampaignCustomizerServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignCustomizerService", + "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.ads.googleads.v24.services.CampaignCustomizerService", + "credentialsType": None, + } + ), + ) + + def mutate_campaign_customizers( + self, + request: Optional[ + Union[ + campaign_customizer_service.MutateCampaignCustomizersRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_customizer_service.CampaignCustomizerOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_customizer_service.MutateCampaignCustomizersResponse: + r"""Creates, updates or removes campaign customizers. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCampaignCustomizersRequest, dict]): + The request object. Request message for + [CampaignCustomizerService.MutateCampaignCustomizers][google.ads.googleads.v24.services.CampaignCustomizerService.MutateCampaignCustomizers]. + customer_id (str): + Required. The ID of the customer + whose campaign customizers are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignCustomizerOperation]): + Required. The list of operations to + perform on individual campaign + customizers. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignCustomizersResponse: + Response message for a campaign + customizer mutate. + + """ + # 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 = [customer_id, operations] + 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, + campaign_customizer_service.MutateCampaignCustomizersRequest, + ): + request = ( + campaign_customizer_service.MutateCampaignCustomizersRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_campaign_customizers + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CampaignCustomizerServiceClient": + 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() + + +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__ = ("CampaignCustomizerServiceClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/README.rst b/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/README.rst new file mode 100644 index 000000000..48e30de05 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CampaignCustomizerServiceTransport` is the ABC for all transports. +- public child `CampaignCustomizerServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CampaignCustomizerServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCampaignCustomizerServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CampaignCustomizerServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/__init__.py b/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/__init__.py new file mode 100644 index 000000000..35c08bb47 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CampaignCustomizerServiceTransport +from .grpc import CampaignCustomizerServiceGrpcTransport +from .grpc_asyncio import CampaignCustomizerServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignCustomizerServiceTransport]] +_transport_registry["grpc"] = CampaignCustomizerServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CampaignCustomizerServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CampaignCustomizerServiceTransport", + "CampaignCustomizerServiceGrpcTransport", + "CampaignCustomizerServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/base.py b/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/base.py new file mode 100644 index 000000000..eabc22a25 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import campaign_customizer_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 CampaignCustomizerServiceTransport(abc.ABC): + """Abstract transport class for CampaignCustomizerService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaign_customizers: gapic_v1.method.wrap_method( + self.mutate_campaign_customizers, + 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 mutate_campaign_customizers( + self, + ) -> Callable[ + [campaign_customizer_service.MutateCampaignCustomizersRequest], + Union[ + campaign_customizer_service.MutateCampaignCustomizersResponse, + Awaitable[ + campaign_customizer_service.MutateCampaignCustomizersResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CampaignCustomizerServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/grpc.py b/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/grpc.py new file mode 100644 index 000000000..e01765477 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/grpc.py @@ -0,0 +1,386 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import campaign_customizer_service +from .base import CampaignCustomizerServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignCustomizerService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignCustomizerService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignCustomizerServiceGrpcTransport( + CampaignCustomizerServiceTransport +): + """gRPC backend transport for CampaignCustomizerService. + + Service to manage campaign customizer + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_campaign_customizers( + self, + ) -> Callable[ + [campaign_customizer_service.MutateCampaignCustomizersRequest], + campaign_customizer_service.MutateCampaignCustomizersResponse, + ]: + r"""Return a callable for the mutate campaign customizers method over gRPC. + + Creates, updates or removes campaign customizers. + Operation statuses are returned. + + Returns: + Callable[[~.MutateCampaignCustomizersRequest], + ~.MutateCampaignCustomizersResponse]: + 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 "mutate_campaign_customizers" not in self._stubs: + self._stubs["mutate_campaign_customizers"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignCustomizerService/MutateCampaignCustomizers", + request_serializer=campaign_customizer_service.MutateCampaignCustomizersRequest.serialize, + response_deserializer=campaign_customizer_service.MutateCampaignCustomizersResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_customizers"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CampaignCustomizerServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..ddebec052 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_customizer_service/transports/grpc_asyncio.py @@ -0,0 +1,409 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import campaign_customizer_service +from .base import CampaignCustomizerServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignCustomizerService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignCustomizerService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignCustomizerServiceGrpcAsyncIOTransport( + CampaignCustomizerServiceTransport +): + """gRPC AsyncIO backend transport for CampaignCustomizerService. + + Service to manage campaign customizer + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_campaign_customizers( + self, + ) -> Callable[ + [campaign_customizer_service.MutateCampaignCustomizersRequest], + Awaitable[ + campaign_customizer_service.MutateCampaignCustomizersResponse + ], + ]: + r"""Return a callable for the mutate campaign customizers method over gRPC. + + Creates, updates or removes campaign customizers. + Operation statuses are returned. + + Returns: + Callable[[~.MutateCampaignCustomizersRequest], + Awaitable[~.MutateCampaignCustomizersResponse]]: + 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 "mutate_campaign_customizers" not in self._stubs: + self._stubs["mutate_campaign_customizers"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignCustomizerService/MutateCampaignCustomizers", + request_serializer=campaign_customizer_service.MutateCampaignCustomizersRequest.serialize, + response_deserializer=campaign_customizer_service.MutateCampaignCustomizersResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_customizers"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_campaign_customizers: self._wrap_method( + self.mutate_campaign_customizers, + 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" + + +__all__ = ("CampaignCustomizerServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_draft_service/__init__.py b/google/ads/googleads/v24/services/services/campaign_draft_service/__init__.py new file mode 100644 index 000000000..2df9b304e --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_draft_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CampaignDraftServiceClient +from .async_client import CampaignDraftServiceAsyncClient + +__all__ = ( + "CampaignDraftServiceClient", + "CampaignDraftServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/campaign_draft_service/async_client.py b/google/ads/googleads/v24/services/services/campaign_draft_service/async_client.py new file mode 100644 index 000000000..caca2d5a1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_draft_service/async_client.py @@ -0,0 +1,681 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.services.campaign_draft_service import ( + pagers, +) +from google.ads.googleads.v24.services.types import campaign_draft_service +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore +from google.protobuf import empty_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore +from .transports.base import CampaignDraftServiceTransport, DEFAULT_CLIENT_INFO +from .client import CampaignDraftServiceClient + +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 CampaignDraftServiceAsyncClient: + """Service to manage campaign drafts.""" + + _client: CampaignDraftServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CampaignDraftServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CampaignDraftServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CampaignDraftServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CampaignDraftServiceClient._DEFAULT_UNIVERSE + + campaign_path = staticmethod(CampaignDraftServiceClient.campaign_path) + parse_campaign_path = staticmethod( + CampaignDraftServiceClient.parse_campaign_path + ) + campaign_draft_path = staticmethod( + CampaignDraftServiceClient.campaign_draft_path + ) + parse_campaign_draft_path = staticmethod( + CampaignDraftServiceClient.parse_campaign_draft_path + ) + common_billing_account_path = staticmethod( + CampaignDraftServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CampaignDraftServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CampaignDraftServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CampaignDraftServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CampaignDraftServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CampaignDraftServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CampaignDraftServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CampaignDraftServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CampaignDraftServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CampaignDraftServiceClient.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: + CampaignDraftServiceAsyncClient: The constructed client. + """ + return CampaignDraftServiceClient.from_service_account_info.__func__(CampaignDraftServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CampaignDraftServiceAsyncClient: The constructed client. + """ + return CampaignDraftServiceClient.from_service_account_file.__func__(CampaignDraftServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CampaignDraftServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CampaignDraftServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignDraftServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CampaignDraftServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CampaignDraftServiceTransport, + Callable[..., CampaignDraftServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign draft 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,CampaignDraftServiceTransport,Callable[..., CampaignDraftServiceTransport]]]): + 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 CampaignDraftServiceTransport 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 = CampaignDraftServiceClient( + 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.ads.googleads.v24.services.CampaignDraftServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignDraftService", + "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.ads.googleads.v24.services.CampaignDraftService", + "credentialsType": None, + } + ), + ) + + async def mutate_campaign_drafts( + self, + request: Optional[ + Union[campaign_draft_service.MutateCampaignDraftsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_draft_service.CampaignDraftOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_draft_service.MutateCampaignDraftsResponse: + r"""Creates, updates, or removes campaign drafts. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignDraftError <>`__ + `DatabaseError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCampaignDraftsRequest, dict]]): + The request object. Request message for + [CampaignDraftService.MutateCampaignDrafts][google.ads.googleads.v24.services.CampaignDraftService.MutateCampaignDrafts]. + customer_id (:class:`str`): + Required. The ID of the customer + whose campaign drafts are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CampaignDraftOperation]`): + Required. The list of operations to + perform on individual campaign drafts. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignDraftsResponse: + Response message for campaign draft + mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_draft_service.MutateCampaignDraftsRequest + ): + request = campaign_draft_service.MutateCampaignDraftsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_campaign_drafts + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 promote_campaign_draft( + self, + request: Optional[ + Union[campaign_draft_service.PromoteCampaignDraftRequest, dict] + ] = None, + *, + campaign_draft: Optional[str] = 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"""Promotes the changes in a draft back to the base campaign. + + This method returns a Long Running Operation (LRO) indicating if + the Promote is done. Use + [google.longrunning.Operations.GetOperation][google.longrunning.Operations.GetOperation] + to poll the LRO until it is done. Only a done status is returned + in the response. See the status in the Campaign Draft resource + to determine if the promotion was successful. If the LRO failed, + use + [CampaignDraftService.ListCampaignDraftAsyncErrors][google.ads.googleads.v24.services.CampaignDraftService.ListCampaignDraftAsyncErrors] + to view the list of error reasons. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignDraftError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.PromoteCampaignDraftRequest, dict]]): + The request object. Request message for + [CampaignDraftService.PromoteCampaignDraft][google.ads.googleads.v24.services.CampaignDraftService.PromoteCampaignDraft]. + campaign_draft (:class:`str`): + Required. The resource name of the + campaign draft to promote. + + This corresponds to the ``campaign_draft`` 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 = [campaign_draft] + 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, campaign_draft_service.PromoteCampaignDraftRequest + ): + request = campaign_draft_service.PromoteCampaignDraftRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if campaign_draft is not None: + request.campaign_draft = campaign_draft + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.promote_campaign_draft + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("campaign_draft", request.campaign_draft),) + ), + ) + + # 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=empty_pb2.Empty, + ) + + # Done; return the response. + return response + + async def list_campaign_draft_async_errors( + self, + request: Optional[ + Union[ + campaign_draft_service.ListCampaignDraftAsyncErrorsRequest, dict + ] + ] = None, + *, + resource_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]]] = (), + ) -> pagers.ListCampaignDraftAsyncErrorsAsyncPager: + r"""Returns all errors that occurred during CampaignDraft promote. + Throws an error if called before campaign draft is promoted. + Supports standard list paging. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListCampaignDraftAsyncErrorsRequest, dict]]): + The request object. Request message for + [CampaignDraftService.ListCampaignDraftAsyncErrors][google.ads.googleads.v24.services.CampaignDraftService.ListCampaignDraftAsyncErrors]. + resource_name (:class:`str`): + Required. The name of the campaign + draft from which to retrieve the async + errors. + + This corresponds to the ``resource_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.ads.googleads.v24.services.services.campaign_draft_service.pagers.ListCampaignDraftAsyncErrorsAsyncPager: + Response message for + [CampaignDraftService.ListCampaignDraftAsyncErrors][google.ads.googleads.v24.services.CampaignDraftService.ListCampaignDraftAsyncErrors]. + + 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 = [resource_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, campaign_draft_service.ListCampaignDraftAsyncErrorsRequest + ): + request = ( + campaign_draft_service.ListCampaignDraftAsyncErrorsRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_campaign_draft_async_errors + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_name),) + ), + ) + + # 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.ListCampaignDraftAsyncErrorsAsyncPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CampaignDraftServiceAsyncClient": + 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__ = ("CampaignDraftServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_draft_service/client.py b/google/ads/googleads/v24/services/services/campaign_draft_service/client.py new file mode 100644 index 000000000..930ae4d09 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_draft_service/client.py @@ -0,0 +1,1171 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.services.campaign_draft_service import ( + pagers, +) +from google.ads.googleads.v24.services.types import campaign_draft_service +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore +from google.protobuf import empty_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore +from .transports.base import CampaignDraftServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CampaignDraftServiceGrpcTransport +from .transports.grpc_asyncio import CampaignDraftServiceGrpcAsyncIOTransport + + +class CampaignDraftServiceClientMeta(type): + """Metaclass for the CampaignDraftService 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[CampaignDraftServiceTransport]] + _transport_registry["grpc"] = CampaignDraftServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CampaignDraftServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignDraftServiceTransport]: + """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 CampaignDraftServiceClient(metaclass=CampaignDraftServiceClientMeta): + """Service to manage campaign drafts.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CampaignDraftServiceClient: 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: + CampaignDraftServiceClient: 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) -> CampaignDraftServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignDraftServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_draft_path( + customer_id: str, + base_campaign_id: str, + draft_id: str, + ) -> str: + """Returns a fully-qualified campaign_draft string.""" + return "customers/{customer_id}/campaignDrafts/{base_campaign_id}~{draft_id}".format( + customer_id=customer_id, + base_campaign_id=base_campaign_id, + draft_id=draft_id, + ) + + @staticmethod + def parse_campaign_draft_path(path: str) -> Dict[str, str]: + """Parses a campaign_draft path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignDrafts/(?P.+?)~(?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 = ( + CampaignDraftServiceClient._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 = ( + CampaignDraftServiceClient._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 + ): + """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 = CampaignDraftServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CampaignDraftServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + CampaignDraftServiceClient._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 = CampaignDraftServiceClient._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): + """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, + CampaignDraftServiceTransport, + Callable[..., CampaignDraftServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign draft 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,CampaignDraftServiceTransport,Callable[..., CampaignDraftServiceTransport]]]): + 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 CampaignDraftServiceTransport 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, + ) = CampaignDraftServiceClient._read_environment_variables() + self._client_cert_source = ( + CampaignDraftServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = CampaignDraftServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CampaignDraftServiceTransport + ) + if transport_provided: + # transport is a CampaignDraftServiceTransport 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(CampaignDraftServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CampaignDraftServiceClient._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[CampaignDraftServiceTransport], + Callable[..., CampaignDraftServiceTransport], + ] = ( + CampaignDraftServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CampaignDraftServiceTransport], 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.ads.googleads.v24.services.CampaignDraftServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignDraftService", + "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.ads.googleads.v24.services.CampaignDraftService", + "credentialsType": None, + } + ), + ) + + def mutate_campaign_drafts( + self, + request: Optional[ + Union[campaign_draft_service.MutateCampaignDraftsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_draft_service.CampaignDraftOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_draft_service.MutateCampaignDraftsResponse: + r"""Creates, updates, or removes campaign drafts. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignDraftError <>`__ + `DatabaseError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCampaignDraftsRequest, dict]): + The request object. Request message for + [CampaignDraftService.MutateCampaignDrafts][google.ads.googleads.v24.services.CampaignDraftService.MutateCampaignDrafts]. + customer_id (str): + Required. The ID of the customer + whose campaign drafts are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignDraftOperation]): + Required. The list of operations to + perform on individual campaign drafts. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignDraftsResponse: + Response message for campaign draft + mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_draft_service.MutateCampaignDraftsRequest + ): + request = campaign_draft_service.MutateCampaignDraftsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_campaign_drafts + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 promote_campaign_draft( + self, + request: Optional[ + Union[campaign_draft_service.PromoteCampaignDraftRequest, dict] + ] = None, + *, + campaign_draft: Optional[str] = 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"""Promotes the changes in a draft back to the base campaign. + + This method returns a Long Running Operation (LRO) indicating if + the Promote is done. Use + [google.longrunning.Operations.GetOperation][google.longrunning.Operations.GetOperation] + to poll the LRO until it is done. Only a done status is returned + in the response. See the status in the Campaign Draft resource + to determine if the promotion was successful. If the LRO failed, + use + [CampaignDraftService.ListCampaignDraftAsyncErrors][google.ads.googleads.v24.services.CampaignDraftService.ListCampaignDraftAsyncErrors] + to view the list of error reasons. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignDraftError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.PromoteCampaignDraftRequest, dict]): + The request object. Request message for + [CampaignDraftService.PromoteCampaignDraft][google.ads.googleads.v24.services.CampaignDraftService.PromoteCampaignDraft]. + campaign_draft (str): + Required. The resource name of the + campaign draft to promote. + + This corresponds to the ``campaign_draft`` 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 = [campaign_draft] + 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, campaign_draft_service.PromoteCampaignDraftRequest + ): + request = campaign_draft_service.PromoteCampaignDraftRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if campaign_draft is not None: + request.campaign_draft = campaign_draft + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.promote_campaign_draft + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("campaign_draft", request.campaign_draft),) + ), + ) + + # 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=empty_pb2.Empty, + ) + + # Done; return the response. + return response + + def list_campaign_draft_async_errors( + self, + request: Optional[ + Union[ + campaign_draft_service.ListCampaignDraftAsyncErrorsRequest, dict + ] + ] = None, + *, + resource_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]]] = (), + ) -> pagers.ListCampaignDraftAsyncErrorsPager: + r"""Returns all errors that occurred during CampaignDraft promote. + Throws an error if called before campaign draft is promoted. + Supports standard list paging. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListCampaignDraftAsyncErrorsRequest, dict]): + The request object. Request message for + [CampaignDraftService.ListCampaignDraftAsyncErrors][google.ads.googleads.v24.services.CampaignDraftService.ListCampaignDraftAsyncErrors]. + resource_name (str): + Required. The name of the campaign + draft from which to retrieve the async + errors. + + This corresponds to the ``resource_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.ads.googleads.v24.services.services.campaign_draft_service.pagers.ListCampaignDraftAsyncErrorsPager: + Response message for + [CampaignDraftService.ListCampaignDraftAsyncErrors][google.ads.googleads.v24.services.CampaignDraftService.ListCampaignDraftAsyncErrors]. + + 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 = [resource_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, campaign_draft_service.ListCampaignDraftAsyncErrorsRequest + ): + request = ( + campaign_draft_service.ListCampaignDraftAsyncErrorsRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_campaign_draft_async_errors + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_name),) + ), + ) + + # 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.ListCampaignDraftAsyncErrorsPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def __enter__(self) -> "CampaignDraftServiceClient": + 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() + + +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__ = ("CampaignDraftServiceClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_draft_service/pagers.py b/google/ads/googleads/v24/services/services/campaign_draft_service/pagers.py new file mode 100644 index 000000000..f52969039 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_draft_service/pagers.py @@ -0,0 +1,213 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import retry_async as retries_async +from typing import ( + Any, + AsyncIterator, + Awaitable, + Callable, + Sequence, + Tuple, + Iterator, + Union, +) + +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.ads.googleads.v24.services.types import campaign_draft_service +from google.rpc import status_pb2 # type: ignore + + +class ListCampaignDraftAsyncErrorsPager: + """A pager for iterating through ``list_campaign_draft_async_errors`` requests. + + This class thinly wraps an initial + :class:`google.ads.googleads.v24.services.types.ListCampaignDraftAsyncErrorsResponse` object, and + provides an ``__iter__`` method to iterate through its + ``errors`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``ListCampaignDraftAsyncErrors`` requests and continue to iterate + through the ``errors`` field on the + corresponding responses. + + All the usual :class:`google.ads.googleads.v24.services.types.ListCampaignDraftAsyncErrorsResponse` + 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[ + ..., campaign_draft_service.ListCampaignDraftAsyncErrorsResponse + ], + request: campaign_draft_service.ListCampaignDraftAsyncErrorsRequest, + response: campaign_draft_service.ListCampaignDraftAsyncErrorsResponse, + *, + 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.ads.googleads.v24.services.types.ListCampaignDraftAsyncErrorsRequest): + The initial request object. + response (google.ads.googleads.v24.services.types.ListCampaignDraftAsyncErrorsResponse): + 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 = ( + campaign_draft_service.ListCampaignDraftAsyncErrorsRequest(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[campaign_draft_service.ListCampaignDraftAsyncErrorsResponse]: + 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[status_pb2.Status]: + for page in self.pages: + yield from page.errors + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListCampaignDraftAsyncErrorsAsyncPager: + """A pager for iterating through ``list_campaign_draft_async_errors`` requests. + + This class thinly wraps an initial + :class:`google.ads.googleads.v24.services.types.ListCampaignDraftAsyncErrorsResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``errors`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``ListCampaignDraftAsyncErrors`` requests and continue to iterate + through the ``errors`` field on the + corresponding responses. + + All the usual :class:`google.ads.googleads.v24.services.types.ListCampaignDraftAsyncErrorsResponse` + 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[ + campaign_draft_service.ListCampaignDraftAsyncErrorsResponse + ], + ], + request: campaign_draft_service.ListCampaignDraftAsyncErrorsRequest, + response: campaign_draft_service.ListCampaignDraftAsyncErrorsResponse, + *, + 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.ads.googleads.v24.services.types.ListCampaignDraftAsyncErrorsRequest): + The initial request object. + response (google.ads.googleads.v24.services.types.ListCampaignDraftAsyncErrorsResponse): + 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 = ( + campaign_draft_service.ListCampaignDraftAsyncErrorsRequest(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[ + campaign_draft_service.ListCampaignDraftAsyncErrorsResponse + ]: + 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[status_pb2.Status]: + async def async_generator(): + async for page in self.pages: + for response in page.errors: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/google/ads/googleads/v24/services/services/campaign_draft_service/transports/README.rst b/google/ads/googleads/v24/services/services/campaign_draft_service/transports/README.rst new file mode 100644 index 000000000..9c11475e0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_draft_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CampaignDraftServiceTransport` is the ABC for all transports. +- public child `CampaignDraftServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CampaignDraftServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCampaignDraftServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CampaignDraftServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/campaign_draft_service/transports/__init__.py b/google/ads/googleads/v24/services/services/campaign_draft_service/transports/__init__.py new file mode 100644 index 000000000..b80ec7146 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_draft_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CampaignDraftServiceTransport +from .grpc import CampaignDraftServiceGrpcTransport +from .grpc_asyncio import CampaignDraftServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignDraftServiceTransport]] +_transport_registry["grpc"] = CampaignDraftServiceGrpcTransport +_transport_registry["grpc_asyncio"] = CampaignDraftServiceGrpcAsyncIOTransport + +__all__ = ( + "CampaignDraftServiceTransport", + "CampaignDraftServiceGrpcTransport", + "CampaignDraftServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/campaign_draft_service/transports/base.py b/google/ads/googleads/v24/services/services/campaign_draft_service/transports/base.py new file mode 100644 index 000000000..809638f02 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_draft_service/transports/base.py @@ -0,0 +1,212 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import campaign_draft_service +from google.longrunning import operations_pb2 # type: ignore + +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 CampaignDraftServiceTransport(abc.ABC): + """Abstract transport class for CampaignDraftService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaign_drafts: gapic_v1.method.wrap_method( + self.mutate_campaign_drafts, + default_timeout=None, + client_info=client_info, + ), + self.promote_campaign_draft: gapic_v1.method.wrap_method( + self.promote_campaign_draft, + default_timeout=None, + client_info=client_info, + ), + self.list_campaign_draft_async_errors: gapic_v1.method.wrap_method( + self.list_campaign_draft_async_errors, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def operations_client(self): + """Return the client designed to process long-running operations.""" + raise NotImplementedError() + + @property + def mutate_campaign_drafts( + self, + ) -> Callable[ + [campaign_draft_service.MutateCampaignDraftsRequest], + Union[ + campaign_draft_service.MutateCampaignDraftsResponse, + Awaitable[campaign_draft_service.MutateCampaignDraftsResponse], + ], + ]: + raise NotImplementedError() + + @property + def promote_campaign_draft( + self, + ) -> Callable[ + [campaign_draft_service.PromoteCampaignDraftRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def list_campaign_draft_async_errors( + self, + ) -> Callable[ + [campaign_draft_service.ListCampaignDraftAsyncErrorsRequest], + Union[ + campaign_draft_service.ListCampaignDraftAsyncErrorsResponse, + Awaitable[ + campaign_draft_service.ListCampaignDraftAsyncErrorsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CampaignDraftServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_draft_service/transports/grpc.py b/google/ads/googleads/v24/services/services/campaign_draft_service/transports/grpc.py new file mode 100644 index 000000000..7e128359d --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_draft_service/transports/grpc.py @@ -0,0 +1,493 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import campaign_draft_service +from google.longrunning import operations_pb2 # type: ignore +from .base import CampaignDraftServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignDraftService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignDraftService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignDraftServiceGrpcTransport(CampaignDraftServiceTransport): + """gRPC backend transport for CampaignDraftService. + + Service to manage campaign drafts. + + 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 = "googleads.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: 'googleads.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. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client: Optional[operations_v1.OperationsClient] = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if 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 = "googleads.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 operations_client(self) -> operations_v1.OperationsClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Quick check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsClient( + self._logged_channel + ) + + # Return the client from cache. + return self._operations_client + + @property + def mutate_campaign_drafts( + self, + ) -> Callable[ + [campaign_draft_service.MutateCampaignDraftsRequest], + campaign_draft_service.MutateCampaignDraftsResponse, + ]: + r"""Return a callable for the mutate campaign drafts method over gRPC. + + Creates, updates, or removes campaign drafts. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignDraftError <>`__ + `DatabaseError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateCampaignDraftsRequest], + ~.MutateCampaignDraftsResponse]: + 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 "mutate_campaign_drafts" not in self._stubs: + self._stubs["mutate_campaign_drafts"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignDraftService/MutateCampaignDrafts", + request_serializer=campaign_draft_service.MutateCampaignDraftsRequest.serialize, + response_deserializer=campaign_draft_service.MutateCampaignDraftsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_drafts"] + + @property + def promote_campaign_draft( + self, + ) -> Callable[ + [campaign_draft_service.PromoteCampaignDraftRequest], + operations_pb2.Operation, + ]: + r"""Return a callable for the promote campaign draft method over gRPC. + + Promotes the changes in a draft back to the base campaign. + + This method returns a Long Running Operation (LRO) indicating if + the Promote is done. Use + [google.longrunning.Operations.GetOperation][google.longrunning.Operations.GetOperation] + to poll the LRO until it is done. Only a done status is returned + in the response. See the status in the Campaign Draft resource + to determine if the promotion was successful. If the LRO failed, + use + [CampaignDraftService.ListCampaignDraftAsyncErrors][google.ads.googleads.v24.services.CampaignDraftService.ListCampaignDraftAsyncErrors] + to view the list of error reasons. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignDraftError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.PromoteCampaignDraftRequest], + ~.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 "promote_campaign_draft" not in self._stubs: + self._stubs["promote_campaign_draft"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignDraftService/PromoteCampaignDraft", + request_serializer=campaign_draft_service.PromoteCampaignDraftRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + ) + return self._stubs["promote_campaign_draft"] + + @property + def list_campaign_draft_async_errors( + self, + ) -> Callable[ + [campaign_draft_service.ListCampaignDraftAsyncErrorsRequest], + campaign_draft_service.ListCampaignDraftAsyncErrorsResponse, + ]: + r"""Return a callable for the list campaign draft async + errors method over gRPC. + + Returns all errors that occurred during CampaignDraft promote. + Throws an error if called before campaign draft is promoted. + Supports standard list paging. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListCampaignDraftAsyncErrorsRequest], + ~.ListCampaignDraftAsyncErrorsResponse]: + 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_campaign_draft_async_errors" not in self._stubs: + self._stubs["list_campaign_draft_async_errors"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignDraftService/ListCampaignDraftAsyncErrors", + request_serializer=campaign_draft_service.ListCampaignDraftAsyncErrorsRequest.serialize, + response_deserializer=campaign_draft_service.ListCampaignDraftAsyncErrorsResponse.deserialize, + ) + ) + return self._stubs["list_campaign_draft_async_errors"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CampaignDraftServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_draft_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/campaign_draft_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..30c2d46f6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_draft_service/transports/grpc_asyncio.py @@ -0,0 +1,526 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import campaign_draft_service +from google.longrunning import operations_pb2 # type: ignore +from .base import CampaignDraftServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignDraftService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignDraftService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignDraftServiceGrpcAsyncIOTransport(CampaignDraftServiceTransport): + """gRPC AsyncIO backend transport for CampaignDraftService. + + Service to manage campaign drafts. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client: Optional[ + operations_v1.OperationsAsyncClient + ] = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if 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 operations_client(self) -> operations_v1.OperationsAsyncClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Quick check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsAsyncClient( + self._logged_channel + ) + + # Return the client from cache. + return self._operations_client + + @property + def mutate_campaign_drafts( + self, + ) -> Callable[ + [campaign_draft_service.MutateCampaignDraftsRequest], + Awaitable[campaign_draft_service.MutateCampaignDraftsResponse], + ]: + r"""Return a callable for the mutate campaign drafts method over gRPC. + + Creates, updates, or removes campaign drafts. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignDraftError <>`__ + `DatabaseError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateCampaignDraftsRequest], + Awaitable[~.MutateCampaignDraftsResponse]]: + 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 "mutate_campaign_drafts" not in self._stubs: + self._stubs["mutate_campaign_drafts"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignDraftService/MutateCampaignDrafts", + request_serializer=campaign_draft_service.MutateCampaignDraftsRequest.serialize, + response_deserializer=campaign_draft_service.MutateCampaignDraftsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_drafts"] + + @property + def promote_campaign_draft( + self, + ) -> Callable[ + [campaign_draft_service.PromoteCampaignDraftRequest], + Awaitable[operations_pb2.Operation], + ]: + r"""Return a callable for the promote campaign draft method over gRPC. + + Promotes the changes in a draft back to the base campaign. + + This method returns a Long Running Operation (LRO) indicating if + the Promote is done. Use + [google.longrunning.Operations.GetOperation][google.longrunning.Operations.GetOperation] + to poll the LRO until it is done. Only a done status is returned + in the response. See the status in the Campaign Draft resource + to determine if the promotion was successful. If the LRO failed, + use + [CampaignDraftService.ListCampaignDraftAsyncErrors][google.ads.googleads.v24.services.CampaignDraftService.ListCampaignDraftAsyncErrors] + to view the list of error reasons. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignDraftError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.PromoteCampaignDraftRequest], + 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 "promote_campaign_draft" not in self._stubs: + self._stubs["promote_campaign_draft"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignDraftService/PromoteCampaignDraft", + request_serializer=campaign_draft_service.PromoteCampaignDraftRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + ) + return self._stubs["promote_campaign_draft"] + + @property + def list_campaign_draft_async_errors( + self, + ) -> Callable[ + [campaign_draft_service.ListCampaignDraftAsyncErrorsRequest], + Awaitable[campaign_draft_service.ListCampaignDraftAsyncErrorsResponse], + ]: + r"""Return a callable for the list campaign draft async + errors method over gRPC. + + Returns all errors that occurred during CampaignDraft promote. + Throws an error if called before campaign draft is promoted. + Supports standard list paging. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListCampaignDraftAsyncErrorsRequest], + Awaitable[~.ListCampaignDraftAsyncErrorsResponse]]: + 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_campaign_draft_async_errors" not in self._stubs: + self._stubs["list_campaign_draft_async_errors"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignDraftService/ListCampaignDraftAsyncErrors", + request_serializer=campaign_draft_service.ListCampaignDraftAsyncErrorsRequest.serialize, + response_deserializer=campaign_draft_service.ListCampaignDraftAsyncErrorsResponse.deserialize, + ) + ) + return self._stubs["list_campaign_draft_async_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.mutate_campaign_drafts: self._wrap_method( + self.mutate_campaign_drafts, + default_timeout=None, + client_info=client_info, + ), + self.promote_campaign_draft: self._wrap_method( + self.promote_campaign_draft, + default_timeout=None, + client_info=client_info, + ), + self.list_campaign_draft_async_errors: self._wrap_method( + self.list_campaign_draft_async_errors, + 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" + + +__all__ = ("CampaignDraftServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_goal_config_service/__init__.py b/google/ads/googleads/v24/services/services/campaign_goal_config_service/__init__.py new file mode 100644 index 000000000..2fb24e867 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_goal_config_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CampaignGoalConfigServiceClient +from .async_client import CampaignGoalConfigServiceAsyncClient + +__all__ = ( + "CampaignGoalConfigServiceClient", + "CampaignGoalConfigServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/campaign_goal_config_service/async_client.py b/google/ads/googleads/v24/services/services/campaign_goal_config_service/async_client.py new file mode 100644 index 000000000..c53838b24 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_goal_config_service/async_client.py @@ -0,0 +1,446 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import campaign_goal_config_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CampaignGoalConfigServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CampaignGoalConfigServiceClient + +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 CampaignGoalConfigServiceAsyncClient: + """Service to manage campaign goal configs.""" + + _client: CampaignGoalConfigServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CampaignGoalConfigServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + CampaignGoalConfigServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CampaignGoalConfigServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CampaignGoalConfigServiceClient._DEFAULT_UNIVERSE + + campaign_path = staticmethod(CampaignGoalConfigServiceClient.campaign_path) + parse_campaign_path = staticmethod( + CampaignGoalConfigServiceClient.parse_campaign_path + ) + campaign_goal_config_path = staticmethod( + CampaignGoalConfigServiceClient.campaign_goal_config_path + ) + parse_campaign_goal_config_path = staticmethod( + CampaignGoalConfigServiceClient.parse_campaign_goal_config_path + ) + goal_path = staticmethod(CampaignGoalConfigServiceClient.goal_path) + parse_goal_path = staticmethod( + CampaignGoalConfigServiceClient.parse_goal_path + ) + common_billing_account_path = staticmethod( + CampaignGoalConfigServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CampaignGoalConfigServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CampaignGoalConfigServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CampaignGoalConfigServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CampaignGoalConfigServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CampaignGoalConfigServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CampaignGoalConfigServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CampaignGoalConfigServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CampaignGoalConfigServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CampaignGoalConfigServiceClient.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: + CampaignGoalConfigServiceAsyncClient: The constructed client. + """ + return CampaignGoalConfigServiceClient.from_service_account_info.__func__(CampaignGoalConfigServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CampaignGoalConfigServiceAsyncClient: The constructed client. + """ + return CampaignGoalConfigServiceClient.from_service_account_file.__func__(CampaignGoalConfigServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CampaignGoalConfigServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CampaignGoalConfigServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignGoalConfigServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CampaignGoalConfigServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CampaignGoalConfigServiceTransport, + Callable[..., CampaignGoalConfigServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign goal 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,CampaignGoalConfigServiceTransport,Callable[..., CampaignGoalConfigServiceTransport]]]): + 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 CampaignGoalConfigServiceTransport 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 = CampaignGoalConfigServiceClient( + 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.ads.googleads.v24.services.CampaignGoalConfigServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignGoalConfigService", + "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.ads.googleads.v24.services.CampaignGoalConfigService", + "credentialsType": None, + } + ), + ) + + async def mutate_campaign_goal_configs( + self, + request: Optional[ + Union[ + campaign_goal_config_service.MutateCampaignGoalConfigsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_goal_config_service.CampaignGoalConfigOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_goal_config_service.MutateCampaignGoalConfigsResponse: + r"""Create or update campaign goal configs. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + `CampaignGoalConfigError <>`__ `GoalServicesError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCampaignGoalConfigsRequest, dict]]): + The request object. Request message for + [CampaignGoalConfigService.MutateCampaignGoalConfigs][google.ads.googleads.v24.services.CampaignGoalConfigService.MutateCampaignGoalConfigs]. + customer_id (:class:`str`): + Required. The ID of the customer + whose campaign goal configs are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CampaignGoalConfigOperation]`): + Required. The list of operations to + perform on the campaign goal configs. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignGoalConfigsResponse: + Response message for a campaign goal + config mutate. + + """ + # 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 = [customer_id, operations] + 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, + campaign_goal_config_service.MutateCampaignGoalConfigsRequest, + ): + request = ( + campaign_goal_config_service.MutateCampaignGoalConfigsRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_campaign_goal_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CampaignGoalConfigServiceAsyncClient": + 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__ = ("CampaignGoalConfigServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_goal_config_service/client.py b/google/ads/googleads/v24/services/services/campaign_goal_config_service/client.py new file mode 100644 index 000000000..01da78ab8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_goal_config_service/client.py @@ -0,0 +1,960 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import campaign_goal_config_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CampaignGoalConfigServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CampaignGoalConfigServiceGrpcTransport +from .transports.grpc_asyncio import ( + CampaignGoalConfigServiceGrpcAsyncIOTransport, +) + + +class CampaignGoalConfigServiceClientMeta(type): + """Metaclass for the CampaignGoalConfigService 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[CampaignGoalConfigServiceTransport]] + _transport_registry["grpc"] = CampaignGoalConfigServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CampaignGoalConfigServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignGoalConfigServiceTransport]: + """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 CampaignGoalConfigServiceClient( + metaclass=CampaignGoalConfigServiceClientMeta +): + """Service to manage campaign goal configs.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CampaignGoalConfigServiceClient: 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: + CampaignGoalConfigServiceClient: 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) -> CampaignGoalConfigServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignGoalConfigServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_goal_config_path( + customer_id: str, + campaign_id: str, + unified_goal_id: str, + ) -> str: + """Returns a fully-qualified campaign_goal_config string.""" + return "customers/{customer_id}/campaignGoalConfigs/{campaign_id}~{unified_goal_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + unified_goal_id=unified_goal_id, + ) + + @staticmethod + def parse_campaign_goal_config_path(path: str) -> Dict[str, str]: + """Parses a campaign_goal_config path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignGoalConfigs/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def goal_path( + customer_id: str, + unified_goal_id: str, + ) -> str: + """Returns a fully-qualified goal string.""" + return "customers/{customer_id}/goals/{unified_goal_id}".format( + customer_id=customer_id, + unified_goal_id=unified_goal_id, + ) + + @staticmethod + def parse_goal_path(path: str) -> Dict[str, str]: + """Parses a goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/goals/(?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 = ( + CampaignGoalConfigServiceClient._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 = ( + CampaignGoalConfigServiceClient._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 + ): + """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 = ( + CampaignGoalConfigServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CampaignGoalConfigServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = CampaignGoalConfigServiceClient._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 = CampaignGoalConfigServiceClient._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): + """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, + CampaignGoalConfigServiceTransport, + Callable[..., CampaignGoalConfigServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign goal 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,CampaignGoalConfigServiceTransport,Callable[..., CampaignGoalConfigServiceTransport]]]): + 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 CampaignGoalConfigServiceTransport 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, + ) = CampaignGoalConfigServiceClient._read_environment_variables() + self._client_cert_source = ( + CampaignGoalConfigServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CampaignGoalConfigServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CampaignGoalConfigServiceTransport + ) + if transport_provided: + # transport is a CampaignGoalConfigServiceTransport 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( + CampaignGoalConfigServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CampaignGoalConfigServiceClient._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[CampaignGoalConfigServiceTransport], + Callable[..., CampaignGoalConfigServiceTransport], + ] = ( + CampaignGoalConfigServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CampaignGoalConfigServiceTransport], 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.ads.googleads.v24.services.CampaignGoalConfigServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignGoalConfigService", + "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.ads.googleads.v24.services.CampaignGoalConfigService", + "credentialsType": None, + } + ), + ) + + def mutate_campaign_goal_configs( + self, + request: Optional[ + Union[ + campaign_goal_config_service.MutateCampaignGoalConfigsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_goal_config_service.CampaignGoalConfigOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_goal_config_service.MutateCampaignGoalConfigsResponse: + r"""Create or update campaign goal configs. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + `CampaignGoalConfigError <>`__ `GoalServicesError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCampaignGoalConfigsRequest, dict]): + The request object. Request message for + [CampaignGoalConfigService.MutateCampaignGoalConfigs][google.ads.googleads.v24.services.CampaignGoalConfigService.MutateCampaignGoalConfigs]. + customer_id (str): + Required. The ID of the customer + whose campaign goal configs are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignGoalConfigOperation]): + Required. The list of operations to + perform on the campaign goal configs. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignGoalConfigsResponse: + Response message for a campaign goal + config mutate. + + """ + # 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 = [customer_id, operations] + 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, + campaign_goal_config_service.MutateCampaignGoalConfigsRequest, + ): + request = ( + campaign_goal_config_service.MutateCampaignGoalConfigsRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_campaign_goal_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CampaignGoalConfigServiceClient": + 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() + + +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__ = ("CampaignGoalConfigServiceClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/README.rst b/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/README.rst new file mode 100644 index 000000000..d1a9b602b --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CampaignGoalConfigServiceTransport` is the ABC for all transports. +- public child `CampaignGoalConfigServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CampaignGoalConfigServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCampaignGoalConfigServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CampaignGoalConfigServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/__init__.py b/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/__init__.py new file mode 100644 index 000000000..d09fdd235 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CampaignGoalConfigServiceTransport +from .grpc import CampaignGoalConfigServiceGrpcTransport +from .grpc_asyncio import CampaignGoalConfigServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignGoalConfigServiceTransport]] +_transport_registry["grpc"] = CampaignGoalConfigServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CampaignGoalConfigServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CampaignGoalConfigServiceTransport", + "CampaignGoalConfigServiceGrpcTransport", + "CampaignGoalConfigServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/base.py b/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/base.py new file mode 100644 index 000000000..a77132d9c --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import campaign_goal_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 CampaignGoalConfigServiceTransport(abc.ABC): + """Abstract transport class for CampaignGoalConfigService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaign_goal_configs: gapic_v1.method.wrap_method( + self.mutate_campaign_goal_configs, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def mutate_campaign_goal_configs( + self, + ) -> Callable[ + [campaign_goal_config_service.MutateCampaignGoalConfigsRequest], + Union[ + campaign_goal_config_service.MutateCampaignGoalConfigsResponse, + Awaitable[ + campaign_goal_config_service.MutateCampaignGoalConfigsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CampaignGoalConfigServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/grpc.py b/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/grpc.py new file mode 100644 index 000000000..70eb9f4a8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/grpc.py @@ -0,0 +1,390 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import campaign_goal_config_service +from .base import CampaignGoalConfigServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignGoalConfigService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignGoalConfigService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignGoalConfigServiceGrpcTransport( + CampaignGoalConfigServiceTransport +): + """gRPC backend transport for CampaignGoalConfigService. + + Service to manage campaign goal configs. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_campaign_goal_configs( + self, + ) -> Callable[ + [campaign_goal_config_service.MutateCampaignGoalConfigsRequest], + campaign_goal_config_service.MutateCampaignGoalConfigsResponse, + ]: + r"""Return a callable for the mutate campaign goal configs method over gRPC. + + Create or update campaign goal configs. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + `CampaignGoalConfigError <>`__ `GoalServicesError <>`__ + + Returns: + Callable[[~.MutateCampaignGoalConfigsRequest], + ~.MutateCampaignGoalConfigsResponse]: + 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 "mutate_campaign_goal_configs" not in self._stubs: + self._stubs["mutate_campaign_goal_configs"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignGoalConfigService/MutateCampaignGoalConfigs", + request_serializer=campaign_goal_config_service.MutateCampaignGoalConfigsRequest.serialize, + response_deserializer=campaign_goal_config_service.MutateCampaignGoalConfigsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_goal_configs"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CampaignGoalConfigServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..5327eb8e0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_goal_config_service/transports/grpc_asyncio.py @@ -0,0 +1,413 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import campaign_goal_config_service +from .base import CampaignGoalConfigServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignGoalConfigService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignGoalConfigService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignGoalConfigServiceGrpcAsyncIOTransport( + CampaignGoalConfigServiceTransport +): + """gRPC AsyncIO backend transport for CampaignGoalConfigService. + + Service to manage campaign goal configs. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_campaign_goal_configs( + self, + ) -> Callable[ + [campaign_goal_config_service.MutateCampaignGoalConfigsRequest], + Awaitable[ + campaign_goal_config_service.MutateCampaignGoalConfigsResponse + ], + ]: + r"""Return a callable for the mutate campaign goal configs method over gRPC. + + Create or update campaign goal configs. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + `CampaignGoalConfigError <>`__ `GoalServicesError <>`__ + + Returns: + Callable[[~.MutateCampaignGoalConfigsRequest], + Awaitable[~.MutateCampaignGoalConfigsResponse]]: + 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 "mutate_campaign_goal_configs" not in self._stubs: + self._stubs["mutate_campaign_goal_configs"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignGoalConfigService/MutateCampaignGoalConfigs", + request_serializer=campaign_goal_config_service.MutateCampaignGoalConfigsRequest.serialize, + response_deserializer=campaign_goal_config_service.MutateCampaignGoalConfigsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_goal_configs"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_campaign_goal_configs: self._wrap_method( + self.mutate_campaign_goal_configs, + 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" + + +__all__ = ("CampaignGoalConfigServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_group_service/__init__.py b/google/ads/googleads/v24/services/services/campaign_group_service/__init__.py new file mode 100644 index 000000000..331885395 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_group_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CampaignGroupServiceClient +from .async_client import CampaignGroupServiceAsyncClient + +__all__ = ( + "CampaignGroupServiceClient", + "CampaignGroupServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/campaign_group_service/async_client.py b/google/ads/googleads/v24/services/services/campaign_group_service/async_client.py new file mode 100644 index 000000000..d37a80ff2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_group_service/async_client.py @@ -0,0 +1,421 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import campaign_group_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CampaignGroupServiceTransport, DEFAULT_CLIENT_INFO +from .client import CampaignGroupServiceClient + +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 CampaignGroupServiceAsyncClient: + """Service to manage campaign groups.""" + + _client: CampaignGroupServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CampaignGroupServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CampaignGroupServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CampaignGroupServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CampaignGroupServiceClient._DEFAULT_UNIVERSE + + campaign_group_path = staticmethod( + CampaignGroupServiceClient.campaign_group_path + ) + parse_campaign_group_path = staticmethod( + CampaignGroupServiceClient.parse_campaign_group_path + ) + common_billing_account_path = staticmethod( + CampaignGroupServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CampaignGroupServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CampaignGroupServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CampaignGroupServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CampaignGroupServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CampaignGroupServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CampaignGroupServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CampaignGroupServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CampaignGroupServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CampaignGroupServiceClient.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: + CampaignGroupServiceAsyncClient: The constructed client. + """ + return CampaignGroupServiceClient.from_service_account_info.__func__(CampaignGroupServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CampaignGroupServiceAsyncClient: The constructed client. + """ + return CampaignGroupServiceClient.from_service_account_file.__func__(CampaignGroupServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CampaignGroupServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CampaignGroupServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignGroupServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CampaignGroupServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CampaignGroupServiceTransport, + Callable[..., CampaignGroupServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign group 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,CampaignGroupServiceTransport,Callable[..., CampaignGroupServiceTransport]]]): + 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 CampaignGroupServiceTransport 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 = CampaignGroupServiceClient( + 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.ads.googleads.v24.services.CampaignGroupServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignGroupService", + "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.ads.googleads.v24.services.CampaignGroupService", + "credentialsType": None, + } + ), + ) + + async def mutate_campaign_groups( + self, + request: Optional[ + Union[campaign_group_service.MutateCampaignGroupsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_group_service.CampaignGroupOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_group_service.MutateCampaignGroupsResponse: + r"""Creates, updates, or removes campaign groups. + Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCampaignGroupsRequest, dict]]): + The request object. Request message for + [CampaignGroupService.MutateCampaignGroups][google.ads.googleads.v24.services.CampaignGroupService.MutateCampaignGroups]. + customer_id (:class:`str`): + Required. The ID of the customer + whose campaign groups are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CampaignGroupOperation]`): + Required. The list of operations to + perform on individual campaign groups. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignGroupsResponse: + Response message for campaign group + mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_group_service.MutateCampaignGroupsRequest + ): + request = campaign_group_service.MutateCampaignGroupsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_campaign_groups + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CampaignGroupServiceAsyncClient": + 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__ = ("CampaignGroupServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_group_service/client.py b/google/ads/googleads/v24/services/services/campaign_group_service/client.py new file mode 100644 index 000000000..e4ba492a2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_group_service/client.py @@ -0,0 +1,897 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import campaign_group_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CampaignGroupServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CampaignGroupServiceGrpcTransport +from .transports.grpc_asyncio import CampaignGroupServiceGrpcAsyncIOTransport + + +class CampaignGroupServiceClientMeta(type): + """Metaclass for the CampaignGroupService 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[CampaignGroupServiceTransport]] + _transport_registry["grpc"] = CampaignGroupServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CampaignGroupServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignGroupServiceTransport]: + """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 CampaignGroupServiceClient(metaclass=CampaignGroupServiceClientMeta): + """Service to manage campaign groups.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CampaignGroupServiceClient: 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: + CampaignGroupServiceClient: 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) -> CampaignGroupServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignGroupServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_group_path( + customer_id: str, + campaign_group_id: str, + ) -> str: + """Returns a fully-qualified campaign_group string.""" + return ( + "customers/{customer_id}/campaignGroups/{campaign_group_id}".format( + customer_id=customer_id, + campaign_group_id=campaign_group_id, + ) + ) + + @staticmethod + def parse_campaign_group_path(path: str) -> Dict[str, str]: + """Parses a campaign_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignGroups/(?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 = ( + CampaignGroupServiceClient._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 = ( + CampaignGroupServiceClient._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 + ): + """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 = CampaignGroupServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CampaignGroupServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + CampaignGroupServiceClient._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 = CampaignGroupServiceClient._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): + """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, + CampaignGroupServiceTransport, + Callable[..., CampaignGroupServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign group 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,CampaignGroupServiceTransport,Callable[..., CampaignGroupServiceTransport]]]): + 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 CampaignGroupServiceTransport 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, + ) = CampaignGroupServiceClient._read_environment_variables() + self._client_cert_source = ( + CampaignGroupServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = CampaignGroupServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CampaignGroupServiceTransport + ) + if transport_provided: + # transport is a CampaignGroupServiceTransport 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(CampaignGroupServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CampaignGroupServiceClient._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[CampaignGroupServiceTransport], + Callable[..., CampaignGroupServiceTransport], + ] = ( + CampaignGroupServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CampaignGroupServiceTransport], 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.ads.googleads.v24.services.CampaignGroupServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignGroupService", + "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.ads.googleads.v24.services.CampaignGroupService", + "credentialsType": None, + } + ), + ) + + def mutate_campaign_groups( + self, + request: Optional[ + Union[campaign_group_service.MutateCampaignGroupsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_group_service.CampaignGroupOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_group_service.MutateCampaignGroupsResponse: + r"""Creates, updates, or removes campaign groups. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCampaignGroupsRequest, dict]): + The request object. Request message for + [CampaignGroupService.MutateCampaignGroups][google.ads.googleads.v24.services.CampaignGroupService.MutateCampaignGroups]. + customer_id (str): + Required. The ID of the customer + whose campaign groups are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignGroupOperation]): + Required. The list of operations to + perform on individual campaign groups. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignGroupsResponse: + Response message for campaign group + mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_group_service.MutateCampaignGroupsRequest + ): + request = campaign_group_service.MutateCampaignGroupsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_campaign_groups + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CampaignGroupServiceClient": + 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() + + +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__ = ("CampaignGroupServiceClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_group_service/transports/README.rst b/google/ads/googleads/v24/services/services/campaign_group_service/transports/README.rst new file mode 100644 index 000000000..ade5408fe --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_group_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CampaignGroupServiceTransport` is the ABC for all transports. +- public child `CampaignGroupServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CampaignGroupServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCampaignGroupServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CampaignGroupServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/campaign_group_service/transports/__init__.py b/google/ads/googleads/v24/services/services/campaign_group_service/transports/__init__.py new file mode 100644 index 000000000..5ff75f6f6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_group_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CampaignGroupServiceTransport +from .grpc import CampaignGroupServiceGrpcTransport +from .grpc_asyncio import CampaignGroupServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignGroupServiceTransport]] +_transport_registry["grpc"] = CampaignGroupServiceGrpcTransport +_transport_registry["grpc_asyncio"] = CampaignGroupServiceGrpcAsyncIOTransport + +__all__ = ( + "CampaignGroupServiceTransport", + "CampaignGroupServiceGrpcTransport", + "CampaignGroupServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/campaign_group_service/transports/base.py b/google/ads/googleads/v24/services/services/campaign_group_service/transports/base.py new file mode 100644 index 000000000..c00069e17 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_group_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import campaign_group_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 CampaignGroupServiceTransport(abc.ABC): + """Abstract transport class for CampaignGroupService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaign_groups: gapic_v1.method.wrap_method( + self.mutate_campaign_groups, + 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 mutate_campaign_groups( + self, + ) -> Callable[ + [campaign_group_service.MutateCampaignGroupsRequest], + Union[ + campaign_group_service.MutateCampaignGroupsResponse, + Awaitable[campaign_group_service.MutateCampaignGroupsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CampaignGroupServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_group_service/transports/grpc.py b/google/ads/googleads/v24/services/services/campaign_group_service/transports/grpc.py new file mode 100644 index 000000000..d62f94c8e --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_group_service/transports/grpc.py @@ -0,0 +1,384 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import campaign_group_service +from .base import CampaignGroupServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignGroupService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignGroupService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignGroupServiceGrpcTransport(CampaignGroupServiceTransport): + """gRPC backend transport for CampaignGroupService. + + Service to manage campaign groups. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_campaign_groups( + self, + ) -> Callable[ + [campaign_group_service.MutateCampaignGroupsRequest], + campaign_group_service.MutateCampaignGroupsResponse, + ]: + r"""Return a callable for the mutate campaign groups method over gRPC. + + Creates, updates, or removes campaign groups. + Operation statuses are returned. + + Returns: + Callable[[~.MutateCampaignGroupsRequest], + ~.MutateCampaignGroupsResponse]: + 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 "mutate_campaign_groups" not in self._stubs: + self._stubs["mutate_campaign_groups"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignGroupService/MutateCampaignGroups", + request_serializer=campaign_group_service.MutateCampaignGroupsRequest.serialize, + response_deserializer=campaign_group_service.MutateCampaignGroupsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_groups"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CampaignGroupServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_group_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/campaign_group_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..038d33d66 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_group_service/transports/grpc_asyncio.py @@ -0,0 +1,405 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import campaign_group_service +from .base import CampaignGroupServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignGroupService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignGroupService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignGroupServiceGrpcAsyncIOTransport(CampaignGroupServiceTransport): + """gRPC AsyncIO backend transport for CampaignGroupService. + + Service to manage campaign groups. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_campaign_groups( + self, + ) -> Callable[ + [campaign_group_service.MutateCampaignGroupsRequest], + Awaitable[campaign_group_service.MutateCampaignGroupsResponse], + ]: + r"""Return a callable for the mutate campaign groups method over gRPC. + + Creates, updates, or removes campaign groups. + Operation statuses are returned. + + Returns: + Callable[[~.MutateCampaignGroupsRequest], + Awaitable[~.MutateCampaignGroupsResponse]]: + 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 "mutate_campaign_groups" not in self._stubs: + self._stubs["mutate_campaign_groups"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignGroupService/MutateCampaignGroups", + request_serializer=campaign_group_service.MutateCampaignGroupsRequest.serialize, + response_deserializer=campaign_group_service.MutateCampaignGroupsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_groups"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_campaign_groups: self._wrap_method( + self.mutate_campaign_groups, + 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" + + +__all__ = ("CampaignGroupServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_label_service/__init__.py b/google/ads/googleads/v24/services/services/campaign_label_service/__init__.py new file mode 100644 index 000000000..d05b79160 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_label_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CampaignLabelServiceClient +from .async_client import CampaignLabelServiceAsyncClient + +__all__ = ( + "CampaignLabelServiceClient", + "CampaignLabelServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/campaign_label_service/async_client.py b/google/ads/googleads/v24/services/services/campaign_label_service/async_client.py new file mode 100644 index 000000000..cb41d1046 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_label_service/async_client.py @@ -0,0 +1,433 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import campaign_label_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CampaignLabelServiceTransport, DEFAULT_CLIENT_INFO +from .client import CampaignLabelServiceClient + +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 CampaignLabelServiceAsyncClient: + """Service to manage labels on campaigns.""" + + _client: CampaignLabelServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CampaignLabelServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CampaignLabelServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CampaignLabelServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CampaignLabelServiceClient._DEFAULT_UNIVERSE + + campaign_path = staticmethod(CampaignLabelServiceClient.campaign_path) + parse_campaign_path = staticmethod( + CampaignLabelServiceClient.parse_campaign_path + ) + campaign_label_path = staticmethod( + CampaignLabelServiceClient.campaign_label_path + ) + parse_campaign_label_path = staticmethod( + CampaignLabelServiceClient.parse_campaign_label_path + ) + label_path = staticmethod(CampaignLabelServiceClient.label_path) + parse_label_path = staticmethod(CampaignLabelServiceClient.parse_label_path) + common_billing_account_path = staticmethod( + CampaignLabelServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CampaignLabelServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CampaignLabelServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CampaignLabelServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CampaignLabelServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CampaignLabelServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CampaignLabelServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CampaignLabelServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CampaignLabelServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CampaignLabelServiceClient.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: + CampaignLabelServiceAsyncClient: The constructed client. + """ + return CampaignLabelServiceClient.from_service_account_info.__func__(CampaignLabelServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CampaignLabelServiceAsyncClient: The constructed client. + """ + return CampaignLabelServiceClient.from_service_account_file.__func__(CampaignLabelServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CampaignLabelServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CampaignLabelServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignLabelServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CampaignLabelServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CampaignLabelServiceTransport, + Callable[..., CampaignLabelServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign label 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,CampaignLabelServiceTransport,Callable[..., CampaignLabelServiceTransport]]]): + 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 CampaignLabelServiceTransport 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 = CampaignLabelServiceClient( + 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.ads.googleads.v24.services.CampaignLabelServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignLabelService", + "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.ads.googleads.v24.services.CampaignLabelService", + "credentialsType": None, + } + ), + ) + + async def mutate_campaign_labels( + self, + request: Optional[ + Union[campaign_label_service.MutateCampaignLabelsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_label_service.CampaignLabelOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_label_service.MutateCampaignLabelsResponse: + r"""Creates and removes campaign-label relationships. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCampaignLabelsRequest, dict]]): + The request object. Request message for + [CampaignLabelService.MutateCampaignLabels][google.ads.googleads.v24.services.CampaignLabelService.MutateCampaignLabels]. + customer_id (:class:`str`): + Required. ID of the customer whose + campaign-label relationships are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CampaignLabelOperation]`): + Required. The list of operations to + perform on campaign-label relationships. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignLabelsResponse: + Response message for a campaign + labels mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_label_service.MutateCampaignLabelsRequest + ): + request = campaign_label_service.MutateCampaignLabelsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_campaign_labels + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CampaignLabelServiceAsyncClient": + 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__ = ("CampaignLabelServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_label_service/client.py b/google/ads/googleads/v24/services/services/campaign_label_service/client.py new file mode 100644 index 000000000..6f21e8243 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_label_service/client.py @@ -0,0 +1,942 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import campaign_label_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CampaignLabelServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CampaignLabelServiceGrpcTransport +from .transports.grpc_asyncio import CampaignLabelServiceGrpcAsyncIOTransport + + +class CampaignLabelServiceClientMeta(type): + """Metaclass for the CampaignLabelService 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[CampaignLabelServiceTransport]] + _transport_registry["grpc"] = CampaignLabelServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CampaignLabelServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignLabelServiceTransport]: + """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 CampaignLabelServiceClient(metaclass=CampaignLabelServiceClientMeta): + """Service to manage labels on campaigns.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CampaignLabelServiceClient: 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: + CampaignLabelServiceClient: 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) -> CampaignLabelServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignLabelServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_label_path( + customer_id: str, + campaign_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified campaign_label string.""" + return "customers/{customer_id}/campaignLabels/{campaign_id}~{label_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + label_id=label_id, + ) + + @staticmethod + def parse_campaign_label_path(path: str) -> Dict[str, str]: + """Parses a campaign_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignLabels/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def label_path( + customer_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified label string.""" + return "customers/{customer_id}/labels/{label_id}".format( + customer_id=customer_id, + label_id=label_id, + ) + + @staticmethod + def parse_label_path(path: str) -> Dict[str, str]: + """Parses a label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/labels/(?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 = ( + CampaignLabelServiceClient._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 = ( + CampaignLabelServiceClient._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 + ): + """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 = CampaignLabelServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CampaignLabelServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + CampaignLabelServiceClient._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 = CampaignLabelServiceClient._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): + """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, + CampaignLabelServiceTransport, + Callable[..., CampaignLabelServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign label 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,CampaignLabelServiceTransport,Callable[..., CampaignLabelServiceTransport]]]): + 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 CampaignLabelServiceTransport 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, + ) = CampaignLabelServiceClient._read_environment_variables() + self._client_cert_source = ( + CampaignLabelServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = CampaignLabelServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CampaignLabelServiceTransport + ) + if transport_provided: + # transport is a CampaignLabelServiceTransport 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(CampaignLabelServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CampaignLabelServiceClient._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[CampaignLabelServiceTransport], + Callable[..., CampaignLabelServiceTransport], + ] = ( + CampaignLabelServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CampaignLabelServiceTransport], 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.ads.googleads.v24.services.CampaignLabelServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignLabelService", + "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.ads.googleads.v24.services.CampaignLabelService", + "credentialsType": None, + } + ), + ) + + def mutate_campaign_labels( + self, + request: Optional[ + Union[campaign_label_service.MutateCampaignLabelsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_label_service.CampaignLabelOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_label_service.MutateCampaignLabelsResponse: + r"""Creates and removes campaign-label relationships. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCampaignLabelsRequest, dict]): + The request object. Request message for + [CampaignLabelService.MutateCampaignLabels][google.ads.googleads.v24.services.CampaignLabelService.MutateCampaignLabels]. + customer_id (str): + Required. ID of the customer whose + campaign-label relationships are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignLabelOperation]): + Required. The list of operations to + perform on campaign-label relationships. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignLabelsResponse: + Response message for a campaign + labels mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_label_service.MutateCampaignLabelsRequest + ): + request = campaign_label_service.MutateCampaignLabelsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_campaign_labels + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CampaignLabelServiceClient": + 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() + + +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__ = ("CampaignLabelServiceClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_label_service/transports/README.rst b/google/ads/googleads/v24/services/services/campaign_label_service/transports/README.rst new file mode 100644 index 000000000..0572f8cb3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_label_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CampaignLabelServiceTransport` is the ABC for all transports. +- public child `CampaignLabelServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CampaignLabelServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCampaignLabelServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CampaignLabelServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/campaign_label_service/transports/__init__.py b/google/ads/googleads/v24/services/services/campaign_label_service/transports/__init__.py new file mode 100644 index 000000000..cea79c0e2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_label_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CampaignLabelServiceTransport +from .grpc import CampaignLabelServiceGrpcTransport +from .grpc_asyncio import CampaignLabelServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignLabelServiceTransport]] +_transport_registry["grpc"] = CampaignLabelServiceGrpcTransport +_transport_registry["grpc_asyncio"] = CampaignLabelServiceGrpcAsyncIOTransport + +__all__ = ( + "CampaignLabelServiceTransport", + "CampaignLabelServiceGrpcTransport", + "CampaignLabelServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/campaign_label_service/transports/base.py b/google/ads/googleads/v24/services/services/campaign_label_service/transports/base.py new file mode 100644 index 000000000..b7bafc9fd --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_label_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import campaign_label_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 CampaignLabelServiceTransport(abc.ABC): + """Abstract transport class for CampaignLabelService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaign_labels: gapic_v1.method.wrap_method( + self.mutate_campaign_labels, + 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 mutate_campaign_labels( + self, + ) -> Callable[ + [campaign_label_service.MutateCampaignLabelsRequest], + Union[ + campaign_label_service.MutateCampaignLabelsResponse, + Awaitable[campaign_label_service.MutateCampaignLabelsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CampaignLabelServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_label_service/transports/grpc.py b/google/ads/googleads/v24/services/services/campaign_label_service/transports/grpc.py new file mode 100644 index 000000000..19c9ee030 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_label_service/transports/grpc.py @@ -0,0 +1,390 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import campaign_label_service +from .base import CampaignLabelServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignLabelService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignLabelService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignLabelServiceGrpcTransport(CampaignLabelServiceTransport): + """gRPC backend transport for CampaignLabelService. + + Service to manage labels on campaigns. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_campaign_labels( + self, + ) -> Callable[ + [campaign_label_service.MutateCampaignLabelsRequest], + campaign_label_service.MutateCampaignLabelsResponse, + ]: + r"""Return a callable for the mutate campaign labels method over gRPC. + + Creates and removes campaign-label relationships. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateCampaignLabelsRequest], + ~.MutateCampaignLabelsResponse]: + 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 "mutate_campaign_labels" not in self._stubs: + self._stubs["mutate_campaign_labels"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignLabelService/MutateCampaignLabels", + request_serializer=campaign_label_service.MutateCampaignLabelsRequest.serialize, + response_deserializer=campaign_label_service.MutateCampaignLabelsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_labels"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CampaignLabelServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_label_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/campaign_label_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..8508711a6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_label_service/transports/grpc_asyncio.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import campaign_label_service +from .base import CampaignLabelServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignLabelService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignLabelService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignLabelServiceGrpcAsyncIOTransport(CampaignLabelServiceTransport): + """gRPC AsyncIO backend transport for CampaignLabelService. + + Service to manage labels on campaigns. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_campaign_labels( + self, + ) -> Callable[ + [campaign_label_service.MutateCampaignLabelsRequest], + Awaitable[campaign_label_service.MutateCampaignLabelsResponse], + ]: + r"""Return a callable for the mutate campaign labels method over gRPC. + + Creates and removes campaign-label relationships. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateCampaignLabelsRequest], + Awaitable[~.MutateCampaignLabelsResponse]]: + 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 "mutate_campaign_labels" not in self._stubs: + self._stubs["mutate_campaign_labels"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignLabelService/MutateCampaignLabels", + request_serializer=campaign_label_service.MutateCampaignLabelsRequest.serialize, + response_deserializer=campaign_label_service.MutateCampaignLabelsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_labels"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_campaign_labels: self._wrap_method( + self.mutate_campaign_labels, + 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" + + +__all__ = ("CampaignLabelServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/__init__.py b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/__init__.py new file mode 100644 index 000000000..c72735a3f --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CampaignLifecycleGoalServiceClient +from .async_client import CampaignLifecycleGoalServiceAsyncClient + +__all__ = ( + "CampaignLifecycleGoalServiceClient", + "CampaignLifecycleGoalServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/async_client.py b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/async_client.py new file mode 100644 index 000000000..202ea7cf8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/async_client.py @@ -0,0 +1,442 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + campaign_lifecycle_goal_service, +) +from .transports.base import ( + CampaignLifecycleGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CampaignLifecycleGoalServiceClient + +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 CampaignLifecycleGoalServiceAsyncClient: + """Service to configure campaign lifecycle goals.""" + + _client: CampaignLifecycleGoalServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CampaignLifecycleGoalServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + CampaignLifecycleGoalServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CampaignLifecycleGoalServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CampaignLifecycleGoalServiceClient._DEFAULT_UNIVERSE + + campaign_path = staticmethod( + CampaignLifecycleGoalServiceClient.campaign_path + ) + parse_campaign_path = staticmethod( + CampaignLifecycleGoalServiceClient.parse_campaign_path + ) + campaign_lifecycle_goal_path = staticmethod( + CampaignLifecycleGoalServiceClient.campaign_lifecycle_goal_path + ) + parse_campaign_lifecycle_goal_path = staticmethod( + CampaignLifecycleGoalServiceClient.parse_campaign_lifecycle_goal_path + ) + common_billing_account_path = staticmethod( + CampaignLifecycleGoalServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CampaignLifecycleGoalServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CampaignLifecycleGoalServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CampaignLifecycleGoalServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CampaignLifecycleGoalServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CampaignLifecycleGoalServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CampaignLifecycleGoalServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CampaignLifecycleGoalServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CampaignLifecycleGoalServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CampaignLifecycleGoalServiceClient.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: + CampaignLifecycleGoalServiceAsyncClient: The constructed client. + """ + return CampaignLifecycleGoalServiceClient.from_service_account_info.__func__(CampaignLifecycleGoalServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CampaignLifecycleGoalServiceAsyncClient: The constructed client. + """ + return CampaignLifecycleGoalServiceClient.from_service_account_file.__func__(CampaignLifecycleGoalServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CampaignLifecycleGoalServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CampaignLifecycleGoalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignLifecycleGoalServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CampaignLifecycleGoalServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CampaignLifecycleGoalServiceTransport, + Callable[..., CampaignLifecycleGoalServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign lifecycle goal 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,CampaignLifecycleGoalServiceTransport,Callable[..., CampaignLifecycleGoalServiceTransport]]]): + 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 CampaignLifecycleGoalServiceTransport 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 = CampaignLifecycleGoalServiceClient( + 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.ads.googleads.v24.services.CampaignLifecycleGoalServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignLifecycleGoalService", + "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.ads.googleads.v24.services.CampaignLifecycleGoalService", + "credentialsType": None, + } + ), + ) + + async def configure_campaign_lifecycle_goals( + self, + request: Optional[ + Union[ + campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[ + campaign_lifecycle_goal_service.CampaignLifecycleGoalOperation + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsResponse + ): + r"""Process the given campaign lifecycle configurations. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ + `CampaignLifecycleGoalConfigError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ConfigureCampaignLifecycleGoalsRequest, dict]]): + The request object. Request message for + [CampaignLifecycleGoalService.ConfigureCampaignLifecycleGoals][google.ads.googleads.v24.services.CampaignLifecycleGoalService.ConfigureCampaignLifecycleGoals]. + customer_id (:class:`str`): + Required. The ID of the customer + performing the upload. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (:class:`google.ads.googleads.v24.services.types.CampaignLifecycleGoalOperation`): + Required. The operation to perform + campaign lifecycle goal update. + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.ConfigureCampaignLifecycleGoalsResponse: + Response message for + [CampaignLifecycleGoalService.ConfigureCampaignLifecycleGoals][google.ads.googleads.v24.services.CampaignLifecycleGoalService.ConfigureCampaignLifecycleGoals]. + + """ + # 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 = [customer_id, operation] + 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, + campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsRequest, + ): + request = campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.configure_campaign_lifecycle_goals + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CampaignLifecycleGoalServiceAsyncClient": + 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__ = ("CampaignLifecycleGoalServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/client.py b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/client.py new file mode 100644 index 000000000..4dc759902 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/client.py @@ -0,0 +1,931 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + campaign_lifecycle_goal_service, +) +from .transports.base import ( + CampaignLifecycleGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CampaignLifecycleGoalServiceGrpcTransport +from .transports.grpc_asyncio import ( + CampaignLifecycleGoalServiceGrpcAsyncIOTransport, +) + + +class CampaignLifecycleGoalServiceClientMeta(type): + """Metaclass for the CampaignLifecycleGoalService 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[CampaignLifecycleGoalServiceTransport]] + _transport_registry["grpc"] = CampaignLifecycleGoalServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CampaignLifecycleGoalServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignLifecycleGoalServiceTransport]: + """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 CampaignLifecycleGoalServiceClient( + metaclass=CampaignLifecycleGoalServiceClientMeta +): + """Service to configure campaign lifecycle goals.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CampaignLifecycleGoalServiceClient: 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: + CampaignLifecycleGoalServiceClient: 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) -> CampaignLifecycleGoalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignLifecycleGoalServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_lifecycle_goal_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign_lifecycle_goal string.""" + return "customers/{customer_id}/campaignLifecycleGoals/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_lifecycle_goal_path(path: str) -> Dict[str, str]: + """Parses a campaign_lifecycle_goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignLifecycleGoals/(?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 = ( + CampaignLifecycleGoalServiceClient._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 = ( + CampaignLifecycleGoalServiceClient._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 + ): + """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 = ( + CampaignLifecycleGoalServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + CampaignLifecycleGoalServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = CampaignLifecycleGoalServiceClient._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 = CampaignLifecycleGoalServiceClient._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): + """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, + CampaignLifecycleGoalServiceTransport, + Callable[..., CampaignLifecycleGoalServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign lifecycle goal 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,CampaignLifecycleGoalServiceTransport,Callable[..., CampaignLifecycleGoalServiceTransport]]]): + 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 CampaignLifecycleGoalServiceTransport 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, + ) = CampaignLifecycleGoalServiceClient._read_environment_variables() + self._client_cert_source = ( + CampaignLifecycleGoalServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CampaignLifecycleGoalServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CampaignLifecycleGoalServiceTransport + ) + if transport_provided: + # transport is a CampaignLifecycleGoalServiceTransport 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( + CampaignLifecycleGoalServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CampaignLifecycleGoalServiceClient._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[CampaignLifecycleGoalServiceTransport], + Callable[..., CampaignLifecycleGoalServiceTransport], + ] = ( + CampaignLifecycleGoalServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CampaignLifecycleGoalServiceTransport], + 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.ads.googleads.v24.services.CampaignLifecycleGoalServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignLifecycleGoalService", + "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.ads.googleads.v24.services.CampaignLifecycleGoalService", + "credentialsType": None, + } + ), + ) + + def configure_campaign_lifecycle_goals( + self, + request: Optional[ + Union[ + campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[ + campaign_lifecycle_goal_service.CampaignLifecycleGoalOperation + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsResponse + ): + r"""Process the given campaign lifecycle configurations. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ + `CampaignLifecycleGoalConfigError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ConfigureCampaignLifecycleGoalsRequest, dict]): + The request object. Request message for + [CampaignLifecycleGoalService.ConfigureCampaignLifecycleGoals][google.ads.googleads.v24.services.CampaignLifecycleGoalService.ConfigureCampaignLifecycleGoals]. + customer_id (str): + Required. The ID of the customer + performing the upload. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (google.ads.googleads.v24.services.types.CampaignLifecycleGoalOperation): + Required. The operation to perform + campaign lifecycle goal update. + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.ConfigureCampaignLifecycleGoalsResponse: + Response message for + [CampaignLifecycleGoalService.ConfigureCampaignLifecycleGoals][google.ads.googleads.v24.services.CampaignLifecycleGoalService.ConfigureCampaignLifecycleGoals]. + + """ + # 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 = [customer_id, operation] + 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, + campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsRequest, + ): + request = campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.configure_campaign_lifecycle_goals + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CampaignLifecycleGoalServiceClient": + 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() + + +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__ = ("CampaignLifecycleGoalServiceClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/README.rst b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/README.rst new file mode 100644 index 000000000..117d51127 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CampaignLifecycleGoalServiceTransport` is the ABC for all transports. +- public child `CampaignLifecycleGoalServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CampaignLifecycleGoalServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCampaignLifecycleGoalServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CampaignLifecycleGoalServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/__init__.py b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/__init__.py new file mode 100644 index 000000000..4f0ec0c11 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CampaignLifecycleGoalServiceTransport +from .grpc import CampaignLifecycleGoalServiceGrpcTransport +from .grpc_asyncio import CampaignLifecycleGoalServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignLifecycleGoalServiceTransport]] +_transport_registry["grpc"] = CampaignLifecycleGoalServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CampaignLifecycleGoalServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CampaignLifecycleGoalServiceTransport", + "CampaignLifecycleGoalServiceGrpcTransport", + "CampaignLifecycleGoalServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/base.py b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/base.py new file mode 100644 index 000000000..411dc2a9c --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + campaign_lifecycle_goal_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 CampaignLifecycleGoalServiceTransport(abc.ABC): + """Abstract transport class for CampaignLifecycleGoalService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.configure_campaign_lifecycle_goals: gapic_v1.method.wrap_method( + self.configure_campaign_lifecycle_goals, + 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 configure_campaign_lifecycle_goals( + self, + ) -> Callable[ + [ + campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsRequest + ], + Union[ + campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsResponse, + Awaitable[ + campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CampaignLifecycleGoalServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/grpc.py b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/grpc.py new file mode 100644 index 000000000..0e59d5f44 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/grpc.py @@ -0,0 +1,395 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + campaign_lifecycle_goal_service, +) +from .base import CampaignLifecycleGoalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignLifecycleGoalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignLifecycleGoalService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignLifecycleGoalServiceGrpcTransport( + CampaignLifecycleGoalServiceTransport +): + """gRPC backend transport for CampaignLifecycleGoalService. + + Service to configure campaign lifecycle goals. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 configure_campaign_lifecycle_goals( + self, + ) -> Callable[ + [ + campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsRequest + ], + campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsResponse, + ]: + r"""Return a callable for the configure campaign lifecycle + goals method over gRPC. + + Process the given campaign lifecycle configurations. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ + `CampaignLifecycleGoalConfigError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ConfigureCampaignLifecycleGoalsRequest], + ~.ConfigureCampaignLifecycleGoalsResponse]: + 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 "configure_campaign_lifecycle_goals" not in self._stubs: + self._stubs["configure_campaign_lifecycle_goals"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignLifecycleGoalService/ConfigureCampaignLifecycleGoals", + request_serializer=campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsRequest.serialize, + response_deserializer=campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsResponse.deserialize, + ) + ) + return self._stubs["configure_campaign_lifecycle_goals"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CampaignLifecycleGoalServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..a9c65374c --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_lifecycle_goal_service/transports/grpc_asyncio.py @@ -0,0 +1,418 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + campaign_lifecycle_goal_service, +) +from .base import CampaignLifecycleGoalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignLifecycleGoalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignLifecycleGoalService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignLifecycleGoalServiceGrpcAsyncIOTransport( + CampaignLifecycleGoalServiceTransport +): + """gRPC AsyncIO backend transport for CampaignLifecycleGoalService. + + Service to configure campaign lifecycle goals. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 configure_campaign_lifecycle_goals( + self, + ) -> Callable[ + [ + campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsRequest + ], + Awaitable[ + campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsResponse + ], + ]: + r"""Return a callable for the configure campaign lifecycle + goals method over gRPC. + + Process the given campaign lifecycle configurations. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ + `CampaignLifecycleGoalConfigError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ConfigureCampaignLifecycleGoalsRequest], + Awaitable[~.ConfigureCampaignLifecycleGoalsResponse]]: + 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 "configure_campaign_lifecycle_goals" not in self._stubs: + self._stubs["configure_campaign_lifecycle_goals"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignLifecycleGoalService/ConfigureCampaignLifecycleGoals", + request_serializer=campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsRequest.serialize, + response_deserializer=campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsResponse.deserialize, + ) + ) + return self._stubs["configure_campaign_lifecycle_goals"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.configure_campaign_lifecycle_goals: self._wrap_method( + self.configure_campaign_lifecycle_goals, + 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" + + +__all__ = ("CampaignLifecycleGoalServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_service/__init__.py b/google/ads/googleads/v24/services/services/campaign_service/__init__.py new file mode 100644 index 000000000..3045495ca --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CampaignServiceClient +from .async_client import CampaignServiceAsyncClient + +__all__ = ( + "CampaignServiceClient", + "CampaignServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/campaign_service/async_client.py b/google/ads/googleads/v24/services/services/campaign_service/async_client.py new file mode 100644 index 000000000..7e5de3bb8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_service/async_client.py @@ -0,0 +1,579 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import campaign_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CampaignServiceTransport, DEFAULT_CLIENT_INFO +from .client import CampaignServiceClient + +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 CampaignServiceAsyncClient: + """Service to manage campaigns.""" + + _client: CampaignServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CampaignServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CampaignServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CampaignServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CampaignServiceClient._DEFAULT_UNIVERSE + + accessible_bidding_strategy_path = staticmethod( + CampaignServiceClient.accessible_bidding_strategy_path + ) + parse_accessible_bidding_strategy_path = staticmethod( + CampaignServiceClient.parse_accessible_bidding_strategy_path + ) + asset_set_path = staticmethod(CampaignServiceClient.asset_set_path) + parse_asset_set_path = staticmethod( + CampaignServiceClient.parse_asset_set_path + ) + bidding_strategy_path = staticmethod( + CampaignServiceClient.bidding_strategy_path + ) + parse_bidding_strategy_path = staticmethod( + CampaignServiceClient.parse_bidding_strategy_path + ) + campaign_path = staticmethod(CampaignServiceClient.campaign_path) + parse_campaign_path = staticmethod( + CampaignServiceClient.parse_campaign_path + ) + campaign_budget_path = staticmethod( + CampaignServiceClient.campaign_budget_path + ) + parse_campaign_budget_path = staticmethod( + CampaignServiceClient.parse_campaign_budget_path + ) + campaign_group_path = staticmethod( + CampaignServiceClient.campaign_group_path + ) + parse_campaign_group_path = staticmethod( + CampaignServiceClient.parse_campaign_group_path + ) + campaign_label_path = staticmethod( + CampaignServiceClient.campaign_label_path + ) + parse_campaign_label_path = staticmethod( + CampaignServiceClient.parse_campaign_label_path + ) + conversion_action_path = staticmethod( + CampaignServiceClient.conversion_action_path + ) + parse_conversion_action_path = staticmethod( + CampaignServiceClient.parse_conversion_action_path + ) + common_billing_account_path = staticmethod( + CampaignServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CampaignServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(CampaignServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + CampaignServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CampaignServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CampaignServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CampaignServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CampaignServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CampaignServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CampaignServiceClient.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: + CampaignServiceAsyncClient: The constructed client. + """ + return CampaignServiceClient.from_service_account_info.__func__(CampaignServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CampaignServiceAsyncClient: The constructed client. + """ + return CampaignServiceClient.from_service_account_file.__func__(CampaignServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CampaignServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CampaignServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CampaignServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CampaignServiceTransport, + Callable[..., CampaignServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign 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,CampaignServiceTransport,Callable[..., CampaignServiceTransport]]]): + 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 CampaignServiceTransport 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 = CampaignServiceClient( + 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.ads.googleads.v24.services.CampaignServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignService", + "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.ads.googleads.v24.services.CampaignService", + "credentialsType": None, + } + ), + ) + + async def mutate_campaigns( + self, + request: Optional[ + Union[campaign_service.MutateCampaignsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_service.CampaignOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_service.MutateCampaignsResponse: + r"""Creates, updates, or removes campaigns. Operation statuses are + returned. + + List of thrown errors: `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `BiddingError <>`__ `BiddingStrategyError <>`__ + `CampaignBudgetError <>`__ `CampaignError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DateRangeError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `ListOperationError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotAllowlistedError <>`__ `NotEmptyError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RegionCodeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SettingError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCampaignsRequest, dict]]): + The request object. Request message for + [CampaignService.MutateCampaigns][google.ads.googleads.v24.services.CampaignService.MutateCampaigns]. + customer_id (:class:`str`): + Required. The ID of the customer + whose campaigns are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CampaignOperation]`): + Required. The list of operations to + perform on individual campaigns. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignsResponse: + Response message for campaign mutate. + """ + # 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 = [customer_id, operations] + 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, campaign_service.MutateCampaignsRequest): + request = campaign_service.MutateCampaignsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_campaigns + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 enable_p_max_brand_guidelines( + self, + request: Optional[ + Union[campaign_service.EnablePMaxBrandGuidelinesRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_service.EnableOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_service.EnablePMaxBrandGuidelinesResponse: + r"""Enables Brand Guidelines for Performance Max campaigns. + + List of thrown errors: `AuthenticationError <>`__ + `AssetError <>`__ `AssetLinkError <>`__ + `AuthorizationError <>`__ `BrandGuidelinesMigrationError <>`__ + `CampaignError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.EnablePMaxBrandGuidelinesRequest, dict]]): + The request object. Request to enable Brand Guidelines + for a Performance Max campaign. + customer_id (:class:`str`): + Required. The ID of the customer + whose campaigns are being enabled. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.EnableOperation]`): + Required. The list of individual + campaign operations. A maximum of 10 + enable operations can be executed in a + request. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.EnablePMaxBrandGuidelinesResponse: + Brand Guidelines campaign enablement + response. + + """ + # 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 = [customer_id, operations] + 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, campaign_service.EnablePMaxBrandGuidelinesRequest + ): + request = campaign_service.EnablePMaxBrandGuidelinesRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.enable_p_max_brand_guidelines + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CampaignServiceAsyncClient": + 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__ = ("CampaignServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_service/client.py b/google/ads/googleads/v24/services/services/campaign_service/client.py new file mode 100644 index 000000000..13224adf1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_service/client.py @@ -0,0 +1,1148 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import campaign_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CampaignServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CampaignServiceGrpcTransport +from .transports.grpc_asyncio import CampaignServiceGrpcAsyncIOTransport + + +class CampaignServiceClientMeta(type): + """Metaclass for the CampaignService 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[CampaignServiceTransport]] + _transport_registry["grpc"] = CampaignServiceGrpcTransport + _transport_registry["grpc_asyncio"] = CampaignServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignServiceTransport]: + """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 CampaignServiceClient(metaclass=CampaignServiceClientMeta): + """Service to manage campaigns.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CampaignServiceClient: 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: + CampaignServiceClient: 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) -> CampaignServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def accessible_bidding_strategy_path( + customer_id: str, + bidding_strategy_id: str, + ) -> str: + """Returns a fully-qualified accessible_bidding_strategy string.""" + return "customers/{customer_id}/accessibleBiddingStrategies/{bidding_strategy_id}".format( + customer_id=customer_id, + bidding_strategy_id=bidding_strategy_id, + ) + + @staticmethod + def parse_accessible_bidding_strategy_path(path: str) -> Dict[str, str]: + """Parses a accessible_bidding_strategy path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/accessibleBiddingStrategies/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_set_path( + customer_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified asset_set string.""" + return "customers/{customer_id}/assetSets/{asset_set_id}".format( + customer_id=customer_id, + asset_set_id=asset_set_id, + ) + + @staticmethod + def parse_asset_set_path(path: str) -> Dict[str, str]: + """Parses a asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetSets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def bidding_strategy_path( + customer_id: str, + bidding_strategy_id: str, + ) -> str: + """Returns a fully-qualified bidding_strategy string.""" + return "customers/{customer_id}/biddingStrategies/{bidding_strategy_id}".format( + customer_id=customer_id, + bidding_strategy_id=bidding_strategy_id, + ) + + @staticmethod + def parse_bidding_strategy_path(path: str) -> Dict[str, str]: + """Parses a bidding_strategy path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/biddingStrategies/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_budget_path( + customer_id: str, + campaign_budget_id: str, + ) -> str: + """Returns a fully-qualified campaign_budget string.""" + return "customers/{customer_id}/campaignBudgets/{campaign_budget_id}".format( + customer_id=customer_id, + campaign_budget_id=campaign_budget_id, + ) + + @staticmethod + def parse_campaign_budget_path(path: str) -> Dict[str, str]: + """Parses a campaign_budget path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignBudgets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_group_path( + customer_id: str, + campaign_group_id: str, + ) -> str: + """Returns a fully-qualified campaign_group string.""" + return ( + "customers/{customer_id}/campaignGroups/{campaign_group_id}".format( + customer_id=customer_id, + campaign_group_id=campaign_group_id, + ) + ) + + @staticmethod + def parse_campaign_group_path(path: str) -> Dict[str, str]: + """Parses a campaign_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_label_path( + customer_id: str, + campaign_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified campaign_label string.""" + return "customers/{customer_id}/campaignLabels/{campaign_id}~{label_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + label_id=label_id, + ) + + @staticmethod + def parse_campaign_label_path(path: str) -> Dict[str, str]: + """Parses a campaign_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignLabels/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_action_path( + customer_id: str, + conversion_action_id: str, + ) -> str: + """Returns a fully-qualified conversion_action string.""" + return "customers/{customer_id}/conversionActions/{conversion_action_id}".format( + customer_id=customer_id, + conversion_action_id=conversion_action_id, + ) + + @staticmethod + def parse_conversion_action_path(path: str) -> Dict[str, str]: + """Parses a conversion_action path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionActions/(?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 = CampaignServiceClient._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 = CampaignServiceClient._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 + ): + """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 = CampaignServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CampaignServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + CampaignServiceClient._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 = CampaignServiceClient._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): + """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, + CampaignServiceTransport, + Callable[..., CampaignServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign 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,CampaignServiceTransport,Callable[..., CampaignServiceTransport]]]): + 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 CampaignServiceTransport 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, + ) = CampaignServiceClient._read_environment_variables() + self._client_cert_source = ( + CampaignServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = CampaignServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CampaignServiceTransport) + if transport_provided: + # transport is a CampaignServiceTransport 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(CampaignServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CampaignServiceClient._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[CampaignServiceTransport], + Callable[..., CampaignServiceTransport], + ] = ( + CampaignServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., CampaignServiceTransport], 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.ads.googleads.v24.services.CampaignServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignService", + "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.ads.googleads.v24.services.CampaignService", + "credentialsType": None, + } + ), + ) + + def mutate_campaigns( + self, + request: Optional[ + Union[campaign_service.MutateCampaignsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_service.CampaignOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_service.MutateCampaignsResponse: + r"""Creates, updates, or removes campaigns. Operation statuses are + returned. + + List of thrown errors: `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `BiddingError <>`__ `BiddingStrategyError <>`__ + `CampaignBudgetError <>`__ `CampaignError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DateRangeError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `ListOperationError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotAllowlistedError <>`__ `NotEmptyError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RegionCodeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SettingError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCampaignsRequest, dict]): + The request object. Request message for + [CampaignService.MutateCampaigns][google.ads.googleads.v24.services.CampaignService.MutateCampaigns]. + customer_id (str): + Required. The ID of the customer + whose campaigns are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignOperation]): + Required. The list of operations to + perform on individual campaigns. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignsResponse: + Response message for campaign mutate. + """ + # 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 = [customer_id, operations] + 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, campaign_service.MutateCampaignsRequest): + request = campaign_service.MutateCampaignsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.mutate_campaigns] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 enable_p_max_brand_guidelines( + self, + request: Optional[ + Union[campaign_service.EnablePMaxBrandGuidelinesRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_service.EnableOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_service.EnablePMaxBrandGuidelinesResponse: + r"""Enables Brand Guidelines for Performance Max campaigns. + + List of thrown errors: `AuthenticationError <>`__ + `AssetError <>`__ `AssetLinkError <>`__ + `AuthorizationError <>`__ `BrandGuidelinesMigrationError <>`__ + `CampaignError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.EnablePMaxBrandGuidelinesRequest, dict]): + The request object. Request to enable Brand Guidelines + for a Performance Max campaign. + customer_id (str): + Required. The ID of the customer + whose campaigns are being enabled. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.EnableOperation]): + Required. The list of individual + campaign operations. A maximum of 10 + enable operations can be executed in a + request. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.EnablePMaxBrandGuidelinesResponse: + Brand Guidelines campaign enablement + response. + + """ + # 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 = [customer_id, operations] + 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, campaign_service.EnablePMaxBrandGuidelinesRequest + ): + request = campaign_service.EnablePMaxBrandGuidelinesRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.enable_p_max_brand_guidelines + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CampaignServiceClient": + 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() + + +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__ = ("CampaignServiceClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_service/transports/README.rst b/google/ads/googleads/v24/services/services/campaign_service/transports/README.rst new file mode 100644 index 000000000..304fd51a7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CampaignServiceTransport` is the ABC for all transports. +- public child `CampaignServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CampaignServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCampaignServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CampaignServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/campaign_service/transports/__init__.py b/google/ads/googleads/v24/services/services/campaign_service/transports/__init__.py new file mode 100644 index 000000000..5f399748c --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CampaignServiceTransport +from .grpc import CampaignServiceGrpcTransport +from .grpc_asyncio import CampaignServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignServiceTransport]] +_transport_registry["grpc"] = CampaignServiceGrpcTransport +_transport_registry["grpc_asyncio"] = CampaignServiceGrpcAsyncIOTransport + +__all__ = ( + "CampaignServiceTransport", + "CampaignServiceGrpcTransport", + "CampaignServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/campaign_service/transports/base.py b/google/ads/googleads/v24/services/services/campaign_service/transports/base.py new file mode 100644 index 000000000..03ec0aab1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_service/transports/base.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import campaign_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 CampaignServiceTransport(abc.ABC): + """Abstract transport class for CampaignService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaigns: gapic_v1.method.wrap_method( + self.mutate_campaigns, + default_timeout=None, + client_info=client_info, + ), + self.enable_p_max_brand_guidelines: gapic_v1.method.wrap_method( + self.enable_p_max_brand_guidelines, + 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 mutate_campaigns( + self, + ) -> Callable[ + [campaign_service.MutateCampaignsRequest], + Union[ + campaign_service.MutateCampaignsResponse, + Awaitable[campaign_service.MutateCampaignsResponse], + ], + ]: + raise NotImplementedError() + + @property + def enable_p_max_brand_guidelines( + self, + ) -> Callable[ + [campaign_service.EnablePMaxBrandGuidelinesRequest], + Union[ + campaign_service.EnablePMaxBrandGuidelinesResponse, + Awaitable[campaign_service.EnablePMaxBrandGuidelinesResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CampaignServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_service/transports/grpc.py b/google/ads/googleads/v24/services/services/campaign_service/transports/grpc.py new file mode 100644 index 000000000..a32f8e7af --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_service/transports/grpc.py @@ -0,0 +1,437 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import campaign_service +from .base import CampaignServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignServiceGrpcTransport(CampaignServiceTransport): + """gRPC backend transport for CampaignService. + + Service to manage campaigns. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_campaigns( + self, + ) -> Callable[ + [campaign_service.MutateCampaignsRequest], + campaign_service.MutateCampaignsResponse, + ]: + r"""Return a callable for the mutate campaigns method over gRPC. + + Creates, updates, or removes campaigns. Operation statuses are + returned. + + List of thrown errors: `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `BiddingError <>`__ `BiddingStrategyError <>`__ + `CampaignBudgetError <>`__ `CampaignError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DateRangeError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `ListOperationError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotAllowlistedError <>`__ `NotEmptyError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RegionCodeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SettingError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateCampaignsRequest], + ~.MutateCampaignsResponse]: + 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 "mutate_campaigns" not in self._stubs: + self._stubs["mutate_campaigns"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignService/MutateCampaigns", + request_serializer=campaign_service.MutateCampaignsRequest.serialize, + response_deserializer=campaign_service.MutateCampaignsResponse.deserialize, + ) + return self._stubs["mutate_campaigns"] + + @property + def enable_p_max_brand_guidelines( + self, + ) -> Callable[ + [campaign_service.EnablePMaxBrandGuidelinesRequest], + campaign_service.EnablePMaxBrandGuidelinesResponse, + ]: + r"""Return a callable for the enable p max brand guidelines method over gRPC. + + Enables Brand Guidelines for Performance Max campaigns. + + List of thrown errors: `AuthenticationError <>`__ + `AssetError <>`__ `AssetLinkError <>`__ + `AuthorizationError <>`__ `BrandGuidelinesMigrationError <>`__ + `CampaignError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Returns: + Callable[[~.EnablePMaxBrandGuidelinesRequest], + ~.EnablePMaxBrandGuidelinesResponse]: + 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 "enable_p_max_brand_guidelines" not in self._stubs: + self._stubs["enable_p_max_brand_guidelines"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignService/EnablePMaxBrandGuidelines", + request_serializer=campaign_service.EnablePMaxBrandGuidelinesRequest.serialize, + response_deserializer=campaign_service.EnablePMaxBrandGuidelinesResponse.deserialize, + ) + ) + return self._stubs["enable_p_max_brand_guidelines"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CampaignServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/campaign_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..54c99e8d1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_service/transports/grpc_asyncio.py @@ -0,0 +1,463 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import campaign_service +from .base import CampaignServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignServiceGrpcAsyncIOTransport(CampaignServiceTransport): + """gRPC AsyncIO backend transport for CampaignService. + + Service to manage campaigns. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_campaigns( + self, + ) -> Callable[ + [campaign_service.MutateCampaignsRequest], + Awaitable[campaign_service.MutateCampaignsResponse], + ]: + r"""Return a callable for the mutate campaigns method over gRPC. + + Creates, updates, or removes campaigns. Operation statuses are + returned. + + List of thrown errors: `AdxError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `BiddingError <>`__ `BiddingStrategyError <>`__ + `CampaignBudgetError <>`__ `CampaignError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DateRangeError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `ListOperationError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotAllowlistedError <>`__ `NotEmptyError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RegionCodeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SettingError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateCampaignsRequest], + Awaitable[~.MutateCampaignsResponse]]: + 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 "mutate_campaigns" not in self._stubs: + self._stubs["mutate_campaigns"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignService/MutateCampaigns", + request_serializer=campaign_service.MutateCampaignsRequest.serialize, + response_deserializer=campaign_service.MutateCampaignsResponse.deserialize, + ) + return self._stubs["mutate_campaigns"] + + @property + def enable_p_max_brand_guidelines( + self, + ) -> Callable[ + [campaign_service.EnablePMaxBrandGuidelinesRequest], + Awaitable[campaign_service.EnablePMaxBrandGuidelinesResponse], + ]: + r"""Return a callable for the enable p max brand guidelines method over gRPC. + + Enables Brand Guidelines for Performance Max campaigns. + + List of thrown errors: `AuthenticationError <>`__ + `AssetError <>`__ `AssetLinkError <>`__ + `AuthorizationError <>`__ `BrandGuidelinesMigrationError <>`__ + `CampaignError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Returns: + Callable[[~.EnablePMaxBrandGuidelinesRequest], + Awaitable[~.EnablePMaxBrandGuidelinesResponse]]: + 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 "enable_p_max_brand_guidelines" not in self._stubs: + self._stubs["enable_p_max_brand_guidelines"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignService/EnablePMaxBrandGuidelines", + request_serializer=campaign_service.EnablePMaxBrandGuidelinesRequest.serialize, + response_deserializer=campaign_service.EnablePMaxBrandGuidelinesResponse.deserialize, + ) + ) + return self._stubs["enable_p_max_brand_guidelines"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_campaigns: self._wrap_method( + self.mutate_campaigns, + default_timeout=None, + client_info=client_info, + ), + self.enable_p_max_brand_guidelines: self._wrap_method( + self.enable_p_max_brand_guidelines, + 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" + + +__all__ = ("CampaignServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_shared_set_service/__init__.py b/google/ads/googleads/v24/services/services/campaign_shared_set_service/__init__.py new file mode 100644 index 000000000..2312c39d3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_shared_set_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CampaignSharedSetServiceClient +from .async_client import CampaignSharedSetServiceAsyncClient + +__all__ = ( + "CampaignSharedSetServiceClient", + "CampaignSharedSetServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/campaign_shared_set_service/async_client.py b/google/ads/googleads/v24/services/services/campaign_shared_set_service/async_client.py new file mode 100644 index 000000000..4fe96c512 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_shared_set_service/async_client.py @@ -0,0 +1,452 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import campaign_shared_set_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CampaignSharedSetServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CampaignSharedSetServiceClient + +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 CampaignSharedSetServiceAsyncClient: + """Service to manage campaign shared sets.""" + + _client: CampaignSharedSetServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CampaignSharedSetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CampaignSharedSetServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CampaignSharedSetServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CampaignSharedSetServiceClient._DEFAULT_UNIVERSE + + campaign_path = staticmethod(CampaignSharedSetServiceClient.campaign_path) + parse_campaign_path = staticmethod( + CampaignSharedSetServiceClient.parse_campaign_path + ) + campaign_shared_set_path = staticmethod( + CampaignSharedSetServiceClient.campaign_shared_set_path + ) + parse_campaign_shared_set_path = staticmethod( + CampaignSharedSetServiceClient.parse_campaign_shared_set_path + ) + shared_set_path = staticmethod( + CampaignSharedSetServiceClient.shared_set_path + ) + parse_shared_set_path = staticmethod( + CampaignSharedSetServiceClient.parse_shared_set_path + ) + common_billing_account_path = staticmethod( + CampaignSharedSetServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CampaignSharedSetServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CampaignSharedSetServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CampaignSharedSetServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CampaignSharedSetServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CampaignSharedSetServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CampaignSharedSetServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CampaignSharedSetServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CampaignSharedSetServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CampaignSharedSetServiceClient.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: + CampaignSharedSetServiceAsyncClient: The constructed client. + """ + return CampaignSharedSetServiceClient.from_service_account_info.__func__(CampaignSharedSetServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CampaignSharedSetServiceAsyncClient: The constructed client. + """ + return CampaignSharedSetServiceClient.from_service_account_file.__func__(CampaignSharedSetServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CampaignSharedSetServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CampaignSharedSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignSharedSetServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CampaignSharedSetServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CampaignSharedSetServiceTransport, + Callable[..., CampaignSharedSetServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign shared set 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,CampaignSharedSetServiceTransport,Callable[..., CampaignSharedSetServiceTransport]]]): + 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 CampaignSharedSetServiceTransport 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 = CampaignSharedSetServiceClient( + 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.ads.googleads.v24.services.CampaignSharedSetServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignSharedSetService", + "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.ads.googleads.v24.services.CampaignSharedSetService", + "credentialsType": None, + } + ), + ) + + async def mutate_campaign_shared_sets( + self, + request: Optional[ + Union[ + campaign_shared_set_service.MutateCampaignSharedSetsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_shared_set_service.CampaignSharedSetOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_shared_set_service.MutateCampaignSharedSetsResponse: + r"""Creates or removes campaign shared sets. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignSharedSetError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCampaignSharedSetsRequest, dict]]): + The request object. Request message for + [CampaignSharedSetService.MutateCampaignSharedSets][google.ads.googleads.v24.services.CampaignSharedSetService.MutateCampaignSharedSets]. + customer_id (:class:`str`): + Required. The ID of the customer + whose campaign shared sets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CampaignSharedSetOperation]`): + Required. The list of operations to + perform on individual campaign shared + sets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignSharedSetsResponse: + Response message for a campaign + shared set mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_shared_set_service.MutateCampaignSharedSetsRequest + ): + request = ( + campaign_shared_set_service.MutateCampaignSharedSetsRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_campaign_shared_sets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CampaignSharedSetServiceAsyncClient": + 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__ = ("CampaignSharedSetServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_shared_set_service/client.py b/google/ads/googleads/v24/services/services/campaign_shared_set_service/client.py new file mode 100644 index 000000000..c6aca0079 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_shared_set_service/client.py @@ -0,0 +1,962 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import campaign_shared_set_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CampaignSharedSetServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CampaignSharedSetServiceGrpcTransport +from .transports.grpc_asyncio import ( + CampaignSharedSetServiceGrpcAsyncIOTransport, +) + + +class CampaignSharedSetServiceClientMeta(type): + """Metaclass for the CampaignSharedSetService 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[CampaignSharedSetServiceTransport]] + _transport_registry["grpc"] = CampaignSharedSetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CampaignSharedSetServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignSharedSetServiceTransport]: + """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 CampaignSharedSetServiceClient( + metaclass=CampaignSharedSetServiceClientMeta +): + """Service to manage campaign shared sets.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CampaignSharedSetServiceClient: 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: + CampaignSharedSetServiceClient: 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) -> CampaignSharedSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignSharedSetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_shared_set_path( + customer_id: str, + campaign_id: str, + shared_set_id: str, + ) -> str: + """Returns a fully-qualified campaign_shared_set string.""" + return "customers/{customer_id}/campaignSharedSets/{campaign_id}~{shared_set_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + shared_set_id=shared_set_id, + ) + + @staticmethod + def parse_campaign_shared_set_path(path: str) -> Dict[str, str]: + """Parses a campaign_shared_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignSharedSets/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def shared_set_path( + customer_id: str, + shared_set_id: str, + ) -> str: + """Returns a fully-qualified shared_set string.""" + return "customers/{customer_id}/sharedSets/{shared_set_id}".format( + customer_id=customer_id, + shared_set_id=shared_set_id, + ) + + @staticmethod + def parse_shared_set_path(path: str) -> Dict[str, str]: + """Parses a shared_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/sharedSets/(?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 = ( + CampaignSharedSetServiceClient._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 = ( + CampaignSharedSetServiceClient._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 + ): + """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 = CampaignSharedSetServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CampaignSharedSetServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = CampaignSharedSetServiceClient._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 = CampaignSharedSetServiceClient._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): + """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, + CampaignSharedSetServiceTransport, + Callable[..., CampaignSharedSetServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the campaign shared set 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,CampaignSharedSetServiceTransport,Callable[..., CampaignSharedSetServiceTransport]]]): + 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 CampaignSharedSetServiceTransport 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, + ) = CampaignSharedSetServiceClient._read_environment_variables() + self._client_cert_source = ( + CampaignSharedSetServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CampaignSharedSetServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CampaignSharedSetServiceTransport + ) + if transport_provided: + # transport is a CampaignSharedSetServiceTransport 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(CampaignSharedSetServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CampaignSharedSetServiceClient._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[CampaignSharedSetServiceTransport], + Callable[..., CampaignSharedSetServiceTransport], + ] = ( + CampaignSharedSetServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CampaignSharedSetServiceTransport], 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.ads.googleads.v24.services.CampaignSharedSetServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CampaignSharedSetService", + "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.ads.googleads.v24.services.CampaignSharedSetService", + "credentialsType": None, + } + ), + ) + + def mutate_campaign_shared_sets( + self, + request: Optional[ + Union[ + campaign_shared_set_service.MutateCampaignSharedSetsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_shared_set_service.CampaignSharedSetOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> campaign_shared_set_service.MutateCampaignSharedSetsResponse: + r"""Creates or removes campaign shared sets. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignSharedSetError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCampaignSharedSetsRequest, dict]): + The request object. Request message for + [CampaignSharedSetService.MutateCampaignSharedSets][google.ads.googleads.v24.services.CampaignSharedSetService.MutateCampaignSharedSets]. + customer_id (str): + Required. The ID of the customer + whose campaign shared sets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignSharedSetOperation]): + Required. The list of operations to + perform on individual campaign shared + sets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCampaignSharedSetsResponse: + Response message for a campaign + shared set mutate. + + """ + # 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 = [customer_id, operations] + 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, campaign_shared_set_service.MutateCampaignSharedSetsRequest + ): + request = ( + campaign_shared_set_service.MutateCampaignSharedSetsRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_campaign_shared_sets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CampaignSharedSetServiceClient": + 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() + + +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__ = ("CampaignSharedSetServiceClient",) diff --git a/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/README.rst b/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/README.rst new file mode 100644 index 000000000..e85964bf7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CampaignSharedSetServiceTransport` is the ABC for all transports. +- public child `CampaignSharedSetServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CampaignSharedSetServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCampaignSharedSetServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CampaignSharedSetServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/__init__.py b/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/__init__.py new file mode 100644 index 000000000..9dfc052a3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CampaignSharedSetServiceTransport +from .grpc import CampaignSharedSetServiceGrpcTransport +from .grpc_asyncio import CampaignSharedSetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignSharedSetServiceTransport]] +_transport_registry["grpc"] = CampaignSharedSetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CampaignSharedSetServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CampaignSharedSetServiceTransport", + "CampaignSharedSetServiceGrpcTransport", + "CampaignSharedSetServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/base.py b/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/base.py new file mode 100644 index 000000000..27fdcc056 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import campaign_shared_set_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 CampaignSharedSetServiceTransport(abc.ABC): + """Abstract transport class for CampaignSharedSetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaign_shared_sets: gapic_v1.method.wrap_method( + self.mutate_campaign_shared_sets, + 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 mutate_campaign_shared_sets( + self, + ) -> Callable[ + [campaign_shared_set_service.MutateCampaignSharedSetsRequest], + Union[ + campaign_shared_set_service.MutateCampaignSharedSetsResponse, + Awaitable[ + campaign_shared_set_service.MutateCampaignSharedSetsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CampaignSharedSetServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/grpc.py b/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/grpc.py new file mode 100644 index 000000000..a6c6067f9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/grpc.py @@ -0,0 +1,394 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import campaign_shared_set_service +from .base import CampaignSharedSetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignSharedSetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignSharedSetService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignSharedSetServiceGrpcTransport(CampaignSharedSetServiceTransport): + """gRPC backend transport for CampaignSharedSetService. + + Service to manage campaign shared sets. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_campaign_shared_sets( + self, + ) -> Callable[ + [campaign_shared_set_service.MutateCampaignSharedSetsRequest], + campaign_shared_set_service.MutateCampaignSharedSetsResponse, + ]: + r"""Return a callable for the mutate campaign shared sets method over gRPC. + + Creates or removes campaign shared sets. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignSharedSetError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateCampaignSharedSetsRequest], + ~.MutateCampaignSharedSetsResponse]: + 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 "mutate_campaign_shared_sets" not in self._stubs: + self._stubs["mutate_campaign_shared_sets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignSharedSetService/MutateCampaignSharedSets", + request_serializer=campaign_shared_set_service.MutateCampaignSharedSetsRequest.serialize, + response_deserializer=campaign_shared_set_service.MutateCampaignSharedSetsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_shared_sets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CampaignSharedSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..3d3babf5d --- /dev/null +++ b/google/ads/googleads/v24/services/services/campaign_shared_set_service/transports/grpc_asyncio.py @@ -0,0 +1,417 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import campaign_shared_set_service +from .base import CampaignSharedSetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CampaignSharedSetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CampaignSharedSetService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CampaignSharedSetServiceGrpcAsyncIOTransport( + CampaignSharedSetServiceTransport +): + """gRPC AsyncIO backend transport for CampaignSharedSetService. + + Service to manage campaign shared sets. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_campaign_shared_sets( + self, + ) -> Callable[ + [campaign_shared_set_service.MutateCampaignSharedSetsRequest], + Awaitable[campaign_shared_set_service.MutateCampaignSharedSetsResponse], + ]: + r"""Return a callable for the mutate campaign shared sets method over gRPC. + + Creates or removes campaign shared sets. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignSharedSetError <>`__ + `ContextError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateCampaignSharedSetsRequest], + Awaitable[~.MutateCampaignSharedSetsResponse]]: + 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 "mutate_campaign_shared_sets" not in self._stubs: + self._stubs["mutate_campaign_shared_sets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CampaignSharedSetService/MutateCampaignSharedSets", + request_serializer=campaign_shared_set_service.MutateCampaignSharedSetsRequest.serialize, + response_deserializer=campaign_shared_set_service.MutateCampaignSharedSetsResponse.deserialize, + ) + ) + return self._stubs["mutate_campaign_shared_sets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_campaign_shared_sets: self._wrap_method( + self.mutate_campaign_shared_sets, + 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" + + +__all__ = ("CampaignSharedSetServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/content_creator_insights_service/__init__.py b/google/ads/googleads/v24/services/services/content_creator_insights_service/__init__.py new file mode 100644 index 000000000..62b915477 --- /dev/null +++ b/google/ads/googleads/v24/services/services/content_creator_insights_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ContentCreatorInsightsServiceClient +from .async_client import ContentCreatorInsightsServiceAsyncClient + +__all__ = ( + "ContentCreatorInsightsServiceClient", + "ContentCreatorInsightsServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/content_creator_insights_service/async_client.py b/google/ads/googleads/v24/services/services/content_creator_insights_service/async_client.py new file mode 100644 index 000000000..8147d59a6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/content_creator_insights_service/async_client.py @@ -0,0 +1,477 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + content_creator_insights_service, +) +from .transports.base import ( + ContentCreatorInsightsServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import ContentCreatorInsightsServiceClient + +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 ContentCreatorInsightsServiceAsyncClient: + """Content Creator Insights Service helps users find information + about YouTube Creators and their content and how these creators + and their audiences can be reached with Google Ads. Accessible + to allowlisted customers only. + """ + + _client: ContentCreatorInsightsServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ContentCreatorInsightsServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + ContentCreatorInsightsServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + ContentCreatorInsightsServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ContentCreatorInsightsServiceClient._DEFAULT_UNIVERSE + + common_billing_account_path = staticmethod( + ContentCreatorInsightsServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ContentCreatorInsightsServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ContentCreatorInsightsServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ContentCreatorInsightsServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ContentCreatorInsightsServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ContentCreatorInsightsServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ContentCreatorInsightsServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ContentCreatorInsightsServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ContentCreatorInsightsServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ContentCreatorInsightsServiceClient.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: + ContentCreatorInsightsServiceAsyncClient: The constructed client. + """ + return ContentCreatorInsightsServiceClient.from_service_account_info.__func__(ContentCreatorInsightsServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ContentCreatorInsightsServiceAsyncClient: The constructed client. + """ + return ContentCreatorInsightsServiceClient.from_service_account_file.__func__(ContentCreatorInsightsServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ContentCreatorInsightsServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ContentCreatorInsightsServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ContentCreatorInsightsServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + ContentCreatorInsightsServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ContentCreatorInsightsServiceTransport, + Callable[..., ContentCreatorInsightsServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the content creator insights 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,ContentCreatorInsightsServiceTransport,Callable[..., ContentCreatorInsightsServiceTransport]]]): + 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 ContentCreatorInsightsServiceTransport 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 = ContentCreatorInsightsServiceClient( + 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.ads.googleads.v24.services.ContentCreatorInsightsServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ContentCreatorInsightsService", + "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.ads.googleads.v24.services.ContentCreatorInsightsService", + "credentialsType": None, + } + ), + ) + + async def generate_creator_insights( + self, + request: Optional[ + Union[ + content_creator_insights_service.GenerateCreatorInsightsRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> content_creator_insights_service.GenerateCreatorInsightsResponse: + r"""Returns insights for a collection of YouTube Creators and + Channels. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateCreatorInsightsRequest, dict]]): + The request object. Request message for + [ContentCreatorInsightsService.GenerateCreatorInsights][google.ads.googleads.v24.services.ContentCreatorInsightsService.GenerateCreatorInsights]. + 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.googleads.v24.services.types.GenerateCreatorInsightsResponse: + Response message for + [ContentCreatorInsightsService.GenerateCreatorInsights][google.ads.googleads.v24.services.ContentCreatorInsightsService.GenerateCreatorInsights]. + + """ + # 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, + content_creator_insights_service.GenerateCreatorInsightsRequest, + ): + request = ( + content_creator_insights_service.GenerateCreatorInsightsRequest( + request + ) + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_creator_insights + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_trending_insights( + self, + request: Optional[ + Union[ + content_creator_insights_service.GenerateTrendingInsightsRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> content_creator_insights_service.GenerateTrendingInsightsResponse: + r"""Returns insights for trending content on YouTube. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateTrendingInsightsRequest, dict]]): + The request object. Request message for + [ContentCreatorInsightsService.GenerateTrendingInsights][google.ads.googleads.v24.services.ContentCreatorInsightsService.GenerateTrendingInsights]. + 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.googleads.v24.services.types.GenerateTrendingInsightsResponse: + Response message for + [ContentCreatorInsightsService.GenerateTrendingInsights][google.ads.googleads.v24.services.ContentCreatorInsightsService.GenerateTrendingInsights]. + + """ + # 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, + content_creator_insights_service.GenerateTrendingInsightsRequest, + ): + request = content_creator_insights_service.GenerateTrendingInsightsRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_trending_insights + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ContentCreatorInsightsServiceAsyncClient": + 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__ = ("ContentCreatorInsightsServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/content_creator_insights_service/client.py b/google/ads/googleads/v24/services/services/content_creator_insights_service/client.py new file mode 100644 index 000000000..34e19cbe9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/content_creator_insights_service/client.py @@ -0,0 +1,937 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + content_creator_insights_service, +) +from .transports.base import ( + ContentCreatorInsightsServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ContentCreatorInsightsServiceGrpcTransport +from .transports.grpc_asyncio import ( + ContentCreatorInsightsServiceGrpcAsyncIOTransport, +) + + +class ContentCreatorInsightsServiceClientMeta(type): + """Metaclass for the ContentCreatorInsightsService 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[ContentCreatorInsightsServiceTransport]] + _transport_registry["grpc"] = ContentCreatorInsightsServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + ContentCreatorInsightsServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ContentCreatorInsightsServiceTransport]: + """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 ContentCreatorInsightsServiceClient( + metaclass=ContentCreatorInsightsServiceClientMeta +): + """Content Creator Insights Service helps users find information + about YouTube Creators and their content and how these creators + and their audiences can be reached with Google Ads. Accessible + to allowlisted customers only. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ContentCreatorInsightsServiceClient: 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: + ContentCreatorInsightsServiceClient: 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) -> ContentCreatorInsightsServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ContentCreatorInsightsServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @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 = ( + ContentCreatorInsightsServiceClient._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 = ( + ContentCreatorInsightsServiceClient._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 + ): + """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 = ( + ContentCreatorInsightsServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + ContentCreatorInsightsServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = ContentCreatorInsightsServiceClient._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 = ContentCreatorInsightsServiceClient._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): + """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, + ContentCreatorInsightsServiceTransport, + Callable[..., ContentCreatorInsightsServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the content creator insights 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,ContentCreatorInsightsServiceTransport,Callable[..., ContentCreatorInsightsServiceTransport]]]): + 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 ContentCreatorInsightsServiceTransport 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, + ) = ContentCreatorInsightsServiceClient._read_environment_variables() + self._client_cert_source = ( + ContentCreatorInsightsServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + ContentCreatorInsightsServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ContentCreatorInsightsServiceTransport + ) + if transport_provided: + # transport is a ContentCreatorInsightsServiceTransport 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( + ContentCreatorInsightsServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ContentCreatorInsightsServiceClient._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[ContentCreatorInsightsServiceTransport], + Callable[..., ContentCreatorInsightsServiceTransport], + ] = ( + ContentCreatorInsightsServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., ContentCreatorInsightsServiceTransport], + 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.ads.googleads.v24.services.ContentCreatorInsightsServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ContentCreatorInsightsService", + "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.ads.googleads.v24.services.ContentCreatorInsightsService", + "credentialsType": None, + } + ), + ) + + def generate_creator_insights( + self, + request: Optional[ + Union[ + content_creator_insights_service.GenerateCreatorInsightsRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> content_creator_insights_service.GenerateCreatorInsightsResponse: + r"""Returns insights for a collection of YouTube Creators and + Channels. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateCreatorInsightsRequest, dict]): + The request object. Request message for + [ContentCreatorInsightsService.GenerateCreatorInsights][google.ads.googleads.v24.services.ContentCreatorInsightsService.GenerateCreatorInsights]. + 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.googleads.v24.services.types.GenerateCreatorInsightsResponse: + Response message for + [ContentCreatorInsightsService.GenerateCreatorInsights][google.ads.googleads.v24.services.ContentCreatorInsightsService.GenerateCreatorInsights]. + + """ + # 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, + content_creator_insights_service.GenerateCreatorInsightsRequest, + ): + request = ( + content_creator_insights_service.GenerateCreatorInsightsRequest( + request + ) + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_creator_insights + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_trending_insights( + self, + request: Optional[ + Union[ + content_creator_insights_service.GenerateTrendingInsightsRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> content_creator_insights_service.GenerateTrendingInsightsResponse: + r"""Returns insights for trending content on YouTube. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateTrendingInsightsRequest, dict]): + The request object. Request message for + [ContentCreatorInsightsService.GenerateTrendingInsights][google.ads.googleads.v24.services.ContentCreatorInsightsService.GenerateTrendingInsights]. + 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.googleads.v24.services.types.GenerateTrendingInsightsResponse: + Response message for + [ContentCreatorInsightsService.GenerateTrendingInsights][google.ads.googleads.v24.services.ContentCreatorInsightsService.GenerateTrendingInsights]. + + """ + # 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, + content_creator_insights_service.GenerateTrendingInsightsRequest, + ): + request = content_creator_insights_service.GenerateTrendingInsightsRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_trending_insights + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "ContentCreatorInsightsServiceClient": + 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() + + +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__ = ("ContentCreatorInsightsServiceClient",) diff --git a/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/README.rst b/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/README.rst new file mode 100644 index 000000000..abd250079 --- /dev/null +++ b/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ContentCreatorInsightsServiceTransport` is the ABC for all transports. +- public child `ContentCreatorInsightsServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ContentCreatorInsightsServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseContentCreatorInsightsServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ContentCreatorInsightsServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/__init__.py b/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/__init__.py new file mode 100644 index 000000000..362907d30 --- /dev/null +++ b/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ContentCreatorInsightsServiceTransport +from .grpc import ContentCreatorInsightsServiceGrpcTransport +from .grpc_asyncio import ContentCreatorInsightsServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ContentCreatorInsightsServiceTransport]] +_transport_registry["grpc"] = ContentCreatorInsightsServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + ContentCreatorInsightsServiceGrpcAsyncIOTransport +) + +__all__ = ( + "ContentCreatorInsightsServiceTransport", + "ContentCreatorInsightsServiceGrpcTransport", + "ContentCreatorInsightsServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/base.py b/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/base.py new file mode 100644 index 000000000..0eb09506b --- /dev/null +++ b/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/base.py @@ -0,0 +1,196 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + content_creator_insights_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 ContentCreatorInsightsServiceTransport(abc.ABC): + """Abstract transport class for ContentCreatorInsightsService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.generate_creator_insights: gapic_v1.method.wrap_method( + self.generate_creator_insights, + default_timeout=None, + client_info=client_info, + ), + self.generate_trending_insights: gapic_v1.method.wrap_method( + self.generate_trending_insights, + 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 generate_creator_insights( + self, + ) -> Callable[ + [content_creator_insights_service.GenerateCreatorInsightsRequest], + Union[ + content_creator_insights_service.GenerateCreatorInsightsResponse, + Awaitable[ + content_creator_insights_service.GenerateCreatorInsightsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def generate_trending_insights( + self, + ) -> Callable[ + [content_creator_insights_service.GenerateTrendingInsightsRequest], + Union[ + content_creator_insights_service.GenerateTrendingInsightsResponse, + Awaitable[ + content_creator_insights_service.GenerateTrendingInsightsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ContentCreatorInsightsServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/grpc.py b/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/grpc.py new file mode 100644 index 000000000..0710f46ea --- /dev/null +++ b/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/grpc.py @@ -0,0 +1,432 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + content_creator_insights_service, +) +from .base import ContentCreatorInsightsServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ContentCreatorInsightsService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ContentCreatorInsightsService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ContentCreatorInsightsServiceGrpcTransport( + ContentCreatorInsightsServiceTransport +): + """gRPC backend transport for ContentCreatorInsightsService. + + Content Creator Insights Service helps users find information + about YouTube Creators and their content and how these creators + and their audiences can be reached with Google Ads. Accessible + to allowlisted customers only. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 generate_creator_insights( + self, + ) -> Callable[ + [content_creator_insights_service.GenerateCreatorInsightsRequest], + content_creator_insights_service.GenerateCreatorInsightsResponse, + ]: + r"""Return a callable for the generate creator insights method over gRPC. + + Returns insights for a collection of YouTube Creators and + Channels. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateCreatorInsightsRequest], + ~.GenerateCreatorInsightsResponse]: + 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 "generate_creator_insights" not in self._stubs: + self._stubs["generate_creator_insights"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ContentCreatorInsightsService/GenerateCreatorInsights", + request_serializer=content_creator_insights_service.GenerateCreatorInsightsRequest.serialize, + response_deserializer=content_creator_insights_service.GenerateCreatorInsightsResponse.deserialize, + ) + ) + return self._stubs["generate_creator_insights"] + + @property + def generate_trending_insights( + self, + ) -> Callable[ + [content_creator_insights_service.GenerateTrendingInsightsRequest], + content_creator_insights_service.GenerateTrendingInsightsResponse, + ]: + r"""Return a callable for the generate trending insights method over gRPC. + + Returns insights for trending content on YouTube. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateTrendingInsightsRequest], + ~.GenerateTrendingInsightsResponse]: + 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 "generate_trending_insights" not in self._stubs: + self._stubs["generate_trending_insights"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ContentCreatorInsightsService/GenerateTrendingInsights", + request_serializer=content_creator_insights_service.GenerateTrendingInsightsRequest.serialize, + response_deserializer=content_creator_insights_service.GenerateTrendingInsightsResponse.deserialize, + ) + ) + return self._stubs["generate_trending_insights"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ContentCreatorInsightsServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..607efc3cd --- /dev/null +++ b/google/ads/googleads/v24/services/services/content_creator_insights_service/transports/grpc_asyncio.py @@ -0,0 +1,462 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + content_creator_insights_service, +) +from .base import ContentCreatorInsightsServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ContentCreatorInsightsService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ContentCreatorInsightsService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ContentCreatorInsightsServiceGrpcAsyncIOTransport( + ContentCreatorInsightsServiceTransport +): + """gRPC AsyncIO backend transport for ContentCreatorInsightsService. + + Content Creator Insights Service helps users find information + about YouTube Creators and their content and how these creators + and their audiences can be reached with Google Ads. Accessible + to allowlisted customers only. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 generate_creator_insights( + self, + ) -> Callable[ + [content_creator_insights_service.GenerateCreatorInsightsRequest], + Awaitable[ + content_creator_insights_service.GenerateCreatorInsightsResponse + ], + ]: + r"""Return a callable for the generate creator insights method over gRPC. + + Returns insights for a collection of YouTube Creators and + Channels. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateCreatorInsightsRequest], + Awaitable[~.GenerateCreatorInsightsResponse]]: + 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 "generate_creator_insights" not in self._stubs: + self._stubs["generate_creator_insights"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ContentCreatorInsightsService/GenerateCreatorInsights", + request_serializer=content_creator_insights_service.GenerateCreatorInsightsRequest.serialize, + response_deserializer=content_creator_insights_service.GenerateCreatorInsightsResponse.deserialize, + ) + ) + return self._stubs["generate_creator_insights"] + + @property + def generate_trending_insights( + self, + ) -> Callable[ + [content_creator_insights_service.GenerateTrendingInsightsRequest], + Awaitable[ + content_creator_insights_service.GenerateTrendingInsightsResponse + ], + ]: + r"""Return a callable for the generate trending insights method over gRPC. + + Returns insights for trending content on YouTube. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateTrendingInsightsRequest], + Awaitable[~.GenerateTrendingInsightsResponse]]: + 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 "generate_trending_insights" not in self._stubs: + self._stubs["generate_trending_insights"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ContentCreatorInsightsService/GenerateTrendingInsights", + request_serializer=content_creator_insights_service.GenerateTrendingInsightsRequest.serialize, + response_deserializer=content_creator_insights_service.GenerateTrendingInsightsResponse.deserialize, + ) + ) + return self._stubs["generate_trending_insights"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.generate_creator_insights: self._wrap_method( + self.generate_creator_insights, + default_timeout=None, + client_info=client_info, + ), + self.generate_trending_insights: self._wrap_method( + self.generate_trending_insights, + 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" + + +__all__ = ("ContentCreatorInsightsServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_action_service/__init__.py b/google/ads/googleads/v24/services/services/conversion_action_service/__init__.py new file mode 100644 index 000000000..4c079ea39 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_action_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ConversionActionServiceClient +from .async_client import ConversionActionServiceAsyncClient + +__all__ = ( + "ConversionActionServiceClient", + "ConversionActionServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/conversion_action_service/async_client.py b/google/ads/googleads/v24/services/services/conversion_action_service/async_client.py new file mode 100644 index 000000000..9e308b4ff --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_action_service/async_client.py @@ -0,0 +1,439 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import conversion_action_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + ConversionActionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import ConversionActionServiceClient + +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 ConversionActionServiceAsyncClient: + """Service to manage conversion actions.""" + + _client: ConversionActionServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ConversionActionServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ConversionActionServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + ConversionActionServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ConversionActionServiceClient._DEFAULT_UNIVERSE + + conversion_action_path = staticmethod( + ConversionActionServiceClient.conversion_action_path + ) + parse_conversion_action_path = staticmethod( + ConversionActionServiceClient.parse_conversion_action_path + ) + customer_path = staticmethod(ConversionActionServiceClient.customer_path) + parse_customer_path = staticmethod( + ConversionActionServiceClient.parse_customer_path + ) + common_billing_account_path = staticmethod( + ConversionActionServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ConversionActionServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ConversionActionServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ConversionActionServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ConversionActionServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ConversionActionServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ConversionActionServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ConversionActionServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ConversionActionServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ConversionActionServiceClient.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: + ConversionActionServiceAsyncClient: The constructed client. + """ + return ConversionActionServiceClient.from_service_account_info.__func__(ConversionActionServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ConversionActionServiceAsyncClient: The constructed client. + """ + return ConversionActionServiceClient.from_service_account_file.__func__(ConversionActionServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ConversionActionServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ConversionActionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ConversionActionServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ConversionActionServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ConversionActionServiceTransport, + Callable[..., ConversionActionServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the conversion action 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,ConversionActionServiceTransport,Callable[..., ConversionActionServiceTransport]]]): + 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 ConversionActionServiceTransport 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 = ConversionActionServiceClient( + 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.ads.googleads.v24.services.ConversionActionServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ConversionActionService", + "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.ads.googleads.v24.services.ConversionActionService", + "credentialsType": None, + } + ), + ) + + async def mutate_conversion_actions( + self, + request: Optional[ + Union[ + conversion_action_service.MutateConversionActionsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[conversion_action_service.ConversionActionOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> conversion_action_service.MutateConversionActionsResponse: + r"""Creates, updates or removes conversion actions. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionActionError <>`__ + `CurrencyCodeError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `StringLengthError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateConversionActionsRequest, dict]]): + The request object. Request message for + [ConversionActionService.MutateConversionActions][google.ads.googleads.v24.services.ConversionActionService.MutateConversionActions]. + customer_id (:class:`str`): + Required. The ID of the customer + whose conversion actions are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.ConversionActionOperation]`): + Required. The list of operations to + perform on individual conversion + actions. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateConversionActionsResponse: + Response message for + [ConversionActionService.MutateConversionActions][google.ads.googleads.v24.services.ConversionActionService.MutateConversionActions]. + + """ + # 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 = [customer_id, operations] + 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, conversion_action_service.MutateConversionActionsRequest + ): + request = conversion_action_service.MutateConversionActionsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_conversion_actions + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ConversionActionServiceAsyncClient": + 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__ = ("ConversionActionServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/conversion_action_service/client.py b/google/ads/googleads/v24/services/services/conversion_action_service/client.py new file mode 100644 index 000000000..94e9a3064 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_action_service/client.py @@ -0,0 +1,928 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import conversion_action_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + ConversionActionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ConversionActionServiceGrpcTransport +from .transports.grpc_asyncio import ConversionActionServiceGrpcAsyncIOTransport + + +class ConversionActionServiceClientMeta(type): + """Metaclass for the ConversionActionService 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[ConversionActionServiceTransport]] + _transport_registry["grpc"] = ConversionActionServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + ConversionActionServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ConversionActionServiceTransport]: + """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 ConversionActionServiceClient( + metaclass=ConversionActionServiceClientMeta +): + """Service to manage conversion actions.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ConversionActionServiceClient: 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: + ConversionActionServiceClient: 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) -> ConversionActionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ConversionActionServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def conversion_action_path( + customer_id: str, + conversion_action_id: str, + ) -> str: + """Returns a fully-qualified conversion_action string.""" + return "customers/{customer_id}/conversionActions/{conversion_action_id}".format( + customer_id=customer_id, + conversion_action_id=conversion_action_id, + ) + + @staticmethod + def parse_conversion_action_path(path: str) -> Dict[str, str]: + """Parses a conversion_action path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionActions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?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 = ( + ConversionActionServiceClient._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 = ( + ConversionActionServiceClient._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 + ): + """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 = ConversionActionServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ConversionActionServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + ConversionActionServiceClient._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 = ConversionActionServiceClient._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): + """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, + ConversionActionServiceTransport, + Callable[..., ConversionActionServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the conversion action 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,ConversionActionServiceTransport,Callable[..., ConversionActionServiceTransport]]]): + 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 ConversionActionServiceTransport 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, + ) = ConversionActionServiceClient._read_environment_variables() + self._client_cert_source = ( + ConversionActionServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + ConversionActionServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ConversionActionServiceTransport + ) + if transport_provided: + # transport is a ConversionActionServiceTransport 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(ConversionActionServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ConversionActionServiceClient._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[ConversionActionServiceTransport], + Callable[..., ConversionActionServiceTransport], + ] = ( + ConversionActionServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., ConversionActionServiceTransport], 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.ads.googleads.v24.services.ConversionActionServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ConversionActionService", + "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.ads.googleads.v24.services.ConversionActionService", + "credentialsType": None, + } + ), + ) + + def mutate_conversion_actions( + self, + request: Optional[ + Union[ + conversion_action_service.MutateConversionActionsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[conversion_action_service.ConversionActionOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> conversion_action_service.MutateConversionActionsResponse: + r"""Creates, updates or removes conversion actions. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionActionError <>`__ + `CurrencyCodeError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateConversionActionsRequest, dict]): + The request object. Request message for + [ConversionActionService.MutateConversionActions][google.ads.googleads.v24.services.ConversionActionService.MutateConversionActions]. + customer_id (str): + Required. The ID of the customer + whose conversion actions are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.ConversionActionOperation]): + Required. The list of operations to + perform on individual conversion + actions. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateConversionActionsResponse: + Response message for + [ConversionActionService.MutateConversionActions][google.ads.googleads.v24.services.ConversionActionService.MutateConversionActions]. + + """ + # 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 = [customer_id, operations] + 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, conversion_action_service.MutateConversionActionsRequest + ): + request = conversion_action_service.MutateConversionActionsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_conversion_actions + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "ConversionActionServiceClient": + 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() + + +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__ = ("ConversionActionServiceClient",) diff --git a/google/ads/googleads/v24/services/services/conversion_action_service/transports/README.rst b/google/ads/googleads/v24/services/services/conversion_action_service/transports/README.rst new file mode 100644 index 000000000..494b8e35e --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_action_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ConversionActionServiceTransport` is the ABC for all transports. +- public child `ConversionActionServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ConversionActionServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseConversionActionServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ConversionActionServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/conversion_action_service/transports/__init__.py b/google/ads/googleads/v24/services/services/conversion_action_service/transports/__init__.py new file mode 100644 index 000000000..4afce0998 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_action_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ConversionActionServiceTransport +from .grpc import ConversionActionServiceGrpcTransport +from .grpc_asyncio import ConversionActionServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ConversionActionServiceTransport]] +_transport_registry["grpc"] = ConversionActionServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + ConversionActionServiceGrpcAsyncIOTransport +) + +__all__ = ( + "ConversionActionServiceTransport", + "ConversionActionServiceGrpcTransport", + "ConversionActionServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/conversion_action_service/transports/base.py b/google/ads/googleads/v24/services/services/conversion_action_service/transports/base.py new file mode 100644 index 000000000..5fc035149 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_action_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import conversion_action_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 ConversionActionServiceTransport(abc.ABC): + """Abstract transport class for ConversionActionService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_conversion_actions: gapic_v1.method.wrap_method( + self.mutate_conversion_actions, + 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 mutate_conversion_actions( + self, + ) -> Callable[ + [conversion_action_service.MutateConversionActionsRequest], + Union[ + conversion_action_service.MutateConversionActionsResponse, + Awaitable[ + conversion_action_service.MutateConversionActionsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ConversionActionServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_action_service/transports/grpc.py b/google/ads/googleads/v24/services/services/conversion_action_service/transports/grpc.py new file mode 100644 index 000000000..badc8d859 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_action_service/transports/grpc.py @@ -0,0 +1,392 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import conversion_action_service +from .base import ConversionActionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ConversionActionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ConversionActionService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ConversionActionServiceGrpcTransport(ConversionActionServiceTransport): + """gRPC backend transport for ConversionActionService. + + Service to manage conversion actions. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_conversion_actions( + self, + ) -> Callable[ + [conversion_action_service.MutateConversionActionsRequest], + conversion_action_service.MutateConversionActionsResponse, + ]: + r"""Return a callable for the mutate conversion actions method over gRPC. + + Creates, updates or removes conversion actions. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionActionError <>`__ + `CurrencyCodeError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateConversionActionsRequest], + ~.MutateConversionActionsResponse]: + 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 "mutate_conversion_actions" not in self._stubs: + self._stubs["mutate_conversion_actions"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionActionService/MutateConversionActions", + request_serializer=conversion_action_service.MutateConversionActionsRequest.serialize, + response_deserializer=conversion_action_service.MutateConversionActionsResponse.deserialize, + ) + ) + return self._stubs["mutate_conversion_actions"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ConversionActionServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_action_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/conversion_action_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..99a7bfd39 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_action_service/transports/grpc_asyncio.py @@ -0,0 +1,415 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import conversion_action_service +from .base import ConversionActionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ConversionActionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ConversionActionService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ConversionActionServiceGrpcAsyncIOTransport( + ConversionActionServiceTransport +): + """gRPC AsyncIO backend transport for ConversionActionService. + + Service to manage conversion actions. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_conversion_actions( + self, + ) -> Callable[ + [conversion_action_service.MutateConversionActionsRequest], + Awaitable[conversion_action_service.MutateConversionActionsResponse], + ]: + r"""Return a callable for the mutate conversion actions method over gRPC. + + Creates, updates or removes conversion actions. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionActionError <>`__ + `CurrencyCodeError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateConversionActionsRequest], + Awaitable[~.MutateConversionActionsResponse]]: + 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 "mutate_conversion_actions" not in self._stubs: + self._stubs["mutate_conversion_actions"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionActionService/MutateConversionActions", + request_serializer=conversion_action_service.MutateConversionActionsRequest.serialize, + response_deserializer=conversion_action_service.MutateConversionActionsResponse.deserialize, + ) + ) + return self._stubs["mutate_conversion_actions"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_conversion_actions: self._wrap_method( + self.mutate_conversion_actions, + 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" + + +__all__ = ("ConversionActionServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/__init__.py b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/__init__.py new file mode 100644 index 000000000..d31dc99d2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ConversionAdjustmentUploadServiceClient +from .async_client import ConversionAdjustmentUploadServiceAsyncClient + +__all__ = ( + "ConversionAdjustmentUploadServiceClient", + "ConversionAdjustmentUploadServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/async_client.py b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/async_client.py new file mode 100644 index 000000000..0ec41d098 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/async_client.py @@ -0,0 +1,462 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + conversion_adjustment_upload_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + ConversionAdjustmentUploadServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import ConversionAdjustmentUploadServiceClient + +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 ConversionAdjustmentUploadServiceAsyncClient: + """Service to upload conversion adjustments.""" + + _client: ConversionAdjustmentUploadServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ConversionAdjustmentUploadServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + ConversionAdjustmentUploadServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + ConversionAdjustmentUploadServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ( + ConversionAdjustmentUploadServiceClient._DEFAULT_UNIVERSE + ) + + common_billing_account_path = staticmethod( + ConversionAdjustmentUploadServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ConversionAdjustmentUploadServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ConversionAdjustmentUploadServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ConversionAdjustmentUploadServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ConversionAdjustmentUploadServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ConversionAdjustmentUploadServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ConversionAdjustmentUploadServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ConversionAdjustmentUploadServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ConversionAdjustmentUploadServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ConversionAdjustmentUploadServiceClient.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: + ConversionAdjustmentUploadServiceAsyncClient: The constructed client. + """ + return ConversionAdjustmentUploadServiceClient.from_service_account_info.__func__(ConversionAdjustmentUploadServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ConversionAdjustmentUploadServiceAsyncClient: The constructed client. + """ + return ConversionAdjustmentUploadServiceClient.from_service_account_file.__func__(ConversionAdjustmentUploadServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ConversionAdjustmentUploadServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ConversionAdjustmentUploadServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ConversionAdjustmentUploadServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + ConversionAdjustmentUploadServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ConversionAdjustmentUploadServiceTransport, + Callable[..., ConversionAdjustmentUploadServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the conversion adjustment upload 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,ConversionAdjustmentUploadServiceTransport,Callable[..., ConversionAdjustmentUploadServiceTransport]]]): + 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 ConversionAdjustmentUploadServiceTransport 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 = ConversionAdjustmentUploadServiceClient( + 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.ads.googleads.v24.services.ConversionAdjustmentUploadServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ConversionAdjustmentUploadService", + "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.ads.googleads.v24.services.ConversionAdjustmentUploadService", + "credentialsType": None, + } + ), + ) + + async def upload_conversion_adjustments( + self, + request: Optional[ + Union[ + conversion_adjustment_upload_service.UploadConversionAdjustmentsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + conversion_adjustments: Optional[ + MutableSequence[ + conversion_adjustment_upload_service.ConversionAdjustment + ] + ] = None, + partial_failure: Optional[bool] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + conversion_adjustment_upload_service.UploadConversionAdjustmentsResponse + ): + r"""Processes the given conversion adjustments. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `PartialFailureError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.UploadConversionAdjustmentsRequest, dict]]): + The request object. Request message for + [ConversionAdjustmentUploadService.UploadConversionAdjustments][google.ads.googleads.v24.services.ConversionAdjustmentUploadService.UploadConversionAdjustments]. + customer_id (:class:`str`): + Required. The ID of the customer + performing the upload. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + conversion_adjustments (:class:`MutableSequence[google.ads.googleads.v24.services.types.ConversionAdjustment]`): + Required. The conversion adjustments + that are being uploaded. + + This corresponds to the ``conversion_adjustments`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + partial_failure (:class:`bool`): + Required. If true, successful + operations will be carried out and + invalid operations will return errors. + If false, all operations will be carried + out in one transaction if and only if + they are all valid. This should always + be set to true. + See + https://developers.google.com/google-ads/api/docs/best-practices/partial-failures + for more information about partial + failure. + + This corresponds to the ``partial_failure`` 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.ads.googleads.v24.services.types.UploadConversionAdjustmentsResponse: + Response message for + [ConversionAdjustmentUploadService.UploadConversionAdjustments][google.ads.googleads.v24.services.ConversionAdjustmentUploadService.UploadConversionAdjustments]. + + """ + # 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 = [ + customer_id, + conversion_adjustments, + partial_failure, + ] + 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, + conversion_adjustment_upload_service.UploadConversionAdjustmentsRequest, + ): + request = conversion_adjustment_upload_service.UploadConversionAdjustmentsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if partial_failure is not None: + request.partial_failure = partial_failure + if conversion_adjustments: + request.conversion_adjustments.extend(conversion_adjustments) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.upload_conversion_adjustments + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__( + self, + ) -> "ConversionAdjustmentUploadServiceAsyncClient": + 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__ = ("ConversionAdjustmentUploadServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/client.py b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/client.py new file mode 100644 index 000000000..9be33b96a --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/client.py @@ -0,0 +1,931 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + conversion_adjustment_upload_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + ConversionAdjustmentUploadServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ConversionAdjustmentUploadServiceGrpcTransport +from .transports.grpc_asyncio import ( + ConversionAdjustmentUploadServiceGrpcAsyncIOTransport, +) + + +class ConversionAdjustmentUploadServiceClientMeta(type): + """Metaclass for the ConversionAdjustmentUploadService 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[ConversionAdjustmentUploadServiceTransport]] + _transport_registry["grpc"] = ConversionAdjustmentUploadServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + ConversionAdjustmentUploadServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ConversionAdjustmentUploadServiceTransport]: + """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 ConversionAdjustmentUploadServiceClient( + metaclass=ConversionAdjustmentUploadServiceClientMeta +): + """Service to upload conversion adjustments.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ConversionAdjustmentUploadServiceClient: 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: + ConversionAdjustmentUploadServiceClient: 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) -> ConversionAdjustmentUploadServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ConversionAdjustmentUploadServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @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 = ( + ConversionAdjustmentUploadServiceClient._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 = ( + ConversionAdjustmentUploadServiceClient._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 + ): + """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 = ( + ConversionAdjustmentUploadServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + ConversionAdjustmentUploadServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = ConversionAdjustmentUploadServiceClient._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 = ( + ConversionAdjustmentUploadServiceClient._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): + """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, + ConversionAdjustmentUploadServiceTransport, + Callable[..., ConversionAdjustmentUploadServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the conversion adjustment upload 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,ConversionAdjustmentUploadServiceTransport,Callable[..., ConversionAdjustmentUploadServiceTransport]]]): + 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 ConversionAdjustmentUploadServiceTransport 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, + ) = ( + ConversionAdjustmentUploadServiceClient._read_environment_variables() + ) + self._client_cert_source = ( + ConversionAdjustmentUploadServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + ConversionAdjustmentUploadServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ConversionAdjustmentUploadServiceTransport + ) + if transport_provided: + # transport is a ConversionAdjustmentUploadServiceTransport 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( + ConversionAdjustmentUploadServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ConversionAdjustmentUploadServiceClient._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[ConversionAdjustmentUploadServiceTransport], + Callable[..., ConversionAdjustmentUploadServiceTransport], + ] = ( + ConversionAdjustmentUploadServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., ConversionAdjustmentUploadServiceTransport], + 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.ads.googleads.v24.services.ConversionAdjustmentUploadServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ConversionAdjustmentUploadService", + "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.ads.googleads.v24.services.ConversionAdjustmentUploadService", + "credentialsType": None, + } + ), + ) + + def upload_conversion_adjustments( + self, + request: Optional[ + Union[ + conversion_adjustment_upload_service.UploadConversionAdjustmentsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + conversion_adjustments: Optional[ + MutableSequence[ + conversion_adjustment_upload_service.ConversionAdjustment + ] + ] = None, + partial_failure: Optional[bool] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + conversion_adjustment_upload_service.UploadConversionAdjustmentsResponse + ): + r"""Processes the given conversion adjustments. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `PartialFailureError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.UploadConversionAdjustmentsRequest, dict]): + The request object. Request message for + [ConversionAdjustmentUploadService.UploadConversionAdjustments][google.ads.googleads.v24.services.ConversionAdjustmentUploadService.UploadConversionAdjustments]. + customer_id (str): + Required. The ID of the customer + performing the upload. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + conversion_adjustments (MutableSequence[google.ads.googleads.v24.services.types.ConversionAdjustment]): + Required. The conversion adjustments + that are being uploaded. + + This corresponds to the ``conversion_adjustments`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + partial_failure (bool): + Required. If true, successful + operations will be carried out and + invalid operations will return errors. + If false, all operations will be carried + out in one transaction if and only if + they are all valid. This should always + be set to true. + See + https://developers.google.com/google-ads/api/docs/best-practices/partial-failures + for more information about partial + failure. + + This corresponds to the ``partial_failure`` 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.ads.googleads.v24.services.types.UploadConversionAdjustmentsResponse: + Response message for + [ConversionAdjustmentUploadService.UploadConversionAdjustments][google.ads.googleads.v24.services.ConversionAdjustmentUploadService.UploadConversionAdjustments]. + + """ + # 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 = [ + customer_id, + conversion_adjustments, + partial_failure, + ] + 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, + conversion_adjustment_upload_service.UploadConversionAdjustmentsRequest, + ): + request = conversion_adjustment_upload_service.UploadConversionAdjustmentsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if conversion_adjustments is not None: + request.conversion_adjustments = conversion_adjustments + if partial_failure is not None: + request.partial_failure = partial_failure + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.upload_conversion_adjustments + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "ConversionAdjustmentUploadServiceClient": + 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() + + +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__ = ("ConversionAdjustmentUploadServiceClient",) diff --git a/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/README.rst b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/README.rst new file mode 100644 index 000000000..e7350ab5c --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ConversionAdjustmentUploadServiceTransport` is the ABC for all transports. +- public child `ConversionAdjustmentUploadServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ConversionAdjustmentUploadServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseConversionAdjustmentUploadServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ConversionAdjustmentUploadServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/__init__.py b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/__init__.py new file mode 100644 index 000000000..44f58dfac --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ConversionAdjustmentUploadServiceTransport +from .grpc import ConversionAdjustmentUploadServiceGrpcTransport +from .grpc_asyncio import ConversionAdjustmentUploadServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ConversionAdjustmentUploadServiceTransport]] +_transport_registry["grpc"] = ConversionAdjustmentUploadServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + ConversionAdjustmentUploadServiceGrpcAsyncIOTransport +) + +__all__ = ( + "ConversionAdjustmentUploadServiceTransport", + "ConversionAdjustmentUploadServiceGrpcTransport", + "ConversionAdjustmentUploadServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/base.py b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/base.py new file mode 100644 index 000000000..91aa11fcd --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + conversion_adjustment_upload_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 ConversionAdjustmentUploadServiceTransport(abc.ABC): + """Abstract transport class for ConversionAdjustmentUploadService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.upload_conversion_adjustments: gapic_v1.method.wrap_method( + self.upload_conversion_adjustments, + 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 upload_conversion_adjustments( + self, + ) -> Callable[ + [ + conversion_adjustment_upload_service.UploadConversionAdjustmentsRequest + ], + Union[ + conversion_adjustment_upload_service.UploadConversionAdjustmentsResponse, + Awaitable[ + conversion_adjustment_upload_service.UploadConversionAdjustmentsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ConversionAdjustmentUploadServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/grpc.py b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/grpc.py new file mode 100644 index 000000000..c08bd981d --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/grpc.py @@ -0,0 +1,397 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + conversion_adjustment_upload_service, +) +from .base import ( + ConversionAdjustmentUploadServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.ConversionAdjustmentUploadService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ConversionAdjustmentUploadService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ConversionAdjustmentUploadServiceGrpcTransport( + ConversionAdjustmentUploadServiceTransport +): + """gRPC backend transport for ConversionAdjustmentUploadService. + + Service to upload conversion adjustments. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 upload_conversion_adjustments( + self, + ) -> Callable[ + [ + conversion_adjustment_upload_service.UploadConversionAdjustmentsRequest + ], + conversion_adjustment_upload_service.UploadConversionAdjustmentsResponse, + ]: + r"""Return a callable for the upload conversion adjustments method over gRPC. + + Processes the given conversion adjustments. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `PartialFailureError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.UploadConversionAdjustmentsRequest], + ~.UploadConversionAdjustmentsResponse]: + 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 "upload_conversion_adjustments" not in self._stubs: + self._stubs["upload_conversion_adjustments"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionAdjustmentUploadService/UploadConversionAdjustments", + request_serializer=conversion_adjustment_upload_service.UploadConversionAdjustmentsRequest.serialize, + response_deserializer=conversion_adjustment_upload_service.UploadConversionAdjustmentsResponse.deserialize, + ) + ) + return self._stubs["upload_conversion_adjustments"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ConversionAdjustmentUploadServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..83096ad9a --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_adjustment_upload_service/transports/grpc_asyncio.py @@ -0,0 +1,420 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + conversion_adjustment_upload_service, +) +from .base import ( + ConversionAdjustmentUploadServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.ConversionAdjustmentUploadService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ConversionAdjustmentUploadService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ConversionAdjustmentUploadServiceGrpcAsyncIOTransport( + ConversionAdjustmentUploadServiceTransport +): + """gRPC AsyncIO backend transport for ConversionAdjustmentUploadService. + + Service to upload conversion adjustments. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 upload_conversion_adjustments( + self, + ) -> Callable[ + [ + conversion_adjustment_upload_service.UploadConversionAdjustmentsRequest + ], + Awaitable[ + conversion_adjustment_upload_service.UploadConversionAdjustmentsResponse + ], + ]: + r"""Return a callable for the upload conversion adjustments method over gRPC. + + Processes the given conversion adjustments. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `PartialFailureError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.UploadConversionAdjustmentsRequest], + Awaitable[~.UploadConversionAdjustmentsResponse]]: + 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 "upload_conversion_adjustments" not in self._stubs: + self._stubs["upload_conversion_adjustments"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionAdjustmentUploadService/UploadConversionAdjustments", + request_serializer=conversion_adjustment_upload_service.UploadConversionAdjustmentsRequest.serialize, + response_deserializer=conversion_adjustment_upload_service.UploadConversionAdjustmentsResponse.deserialize, + ) + ) + return self._stubs["upload_conversion_adjustments"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.upload_conversion_adjustments: self._wrap_method( + self.upload_conversion_adjustments, + 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" + + +__all__ = ("ConversionAdjustmentUploadServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_custom_variable_service/__init__.py b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/__init__.py new file mode 100644 index 000000000..776ebcbf4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ConversionCustomVariableServiceClient +from .async_client import ConversionCustomVariableServiceAsyncClient + +__all__ = ( + "ConversionCustomVariableServiceClient", + "ConversionCustomVariableServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/conversion_custom_variable_service/async_client.py b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/async_client.py new file mode 100644 index 000000000..e19ac9eb4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/async_client.py @@ -0,0 +1,450 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + conversion_custom_variable_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + ConversionCustomVariableServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import ConversionCustomVariableServiceClient + +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 ConversionCustomVariableServiceAsyncClient: + """Service to manage conversion custom variables.""" + + _client: ConversionCustomVariableServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ConversionCustomVariableServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + ConversionCustomVariableServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + ConversionCustomVariableServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ConversionCustomVariableServiceClient._DEFAULT_UNIVERSE + + conversion_custom_variable_path = staticmethod( + ConversionCustomVariableServiceClient.conversion_custom_variable_path + ) + parse_conversion_custom_variable_path = staticmethod( + ConversionCustomVariableServiceClient.parse_conversion_custom_variable_path + ) + customer_path = staticmethod( + ConversionCustomVariableServiceClient.customer_path + ) + parse_customer_path = staticmethod( + ConversionCustomVariableServiceClient.parse_customer_path + ) + common_billing_account_path = staticmethod( + ConversionCustomVariableServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ConversionCustomVariableServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ConversionCustomVariableServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ConversionCustomVariableServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ConversionCustomVariableServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ConversionCustomVariableServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ConversionCustomVariableServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ConversionCustomVariableServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ConversionCustomVariableServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ConversionCustomVariableServiceClient.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: + ConversionCustomVariableServiceAsyncClient: The constructed client. + """ + return ConversionCustomVariableServiceClient.from_service_account_info.__func__(ConversionCustomVariableServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ConversionCustomVariableServiceAsyncClient: The constructed client. + """ + return ConversionCustomVariableServiceClient.from_service_account_file.__func__(ConversionCustomVariableServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ConversionCustomVariableServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ConversionCustomVariableServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ConversionCustomVariableServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + ConversionCustomVariableServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ConversionCustomVariableServiceTransport, + Callable[..., ConversionCustomVariableServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the conversion custom variable 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,ConversionCustomVariableServiceTransport,Callable[..., ConversionCustomVariableServiceTransport]]]): + 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 ConversionCustomVariableServiceTransport 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 = ConversionCustomVariableServiceClient( + 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.ads.googleads.v24.services.ConversionCustomVariableServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ConversionCustomVariableService", + "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.ads.googleads.v24.services.ConversionCustomVariableService", + "credentialsType": None, + } + ), + ) + + async def mutate_conversion_custom_variables( + self, + request: Optional[ + Union[ + conversion_custom_variable_service.MutateConversionCustomVariablesRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + conversion_custom_variable_service.ConversionCustomVariableOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + conversion_custom_variable_service.MutateConversionCustomVariablesResponse + ): + r"""Creates or updates conversion custom variables. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionCustomVariableError <>`__ + `DatabaseError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateConversionCustomVariablesRequest, dict]]): + The request object. Request message for + [ConversionCustomVariableService.MutateConversionCustomVariables][google.ads.googleads.v24.services.ConversionCustomVariableService.MutateConversionCustomVariables]. + customer_id (:class:`str`): + Required. The ID of the customer + whose conversion custom variables are + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.ConversionCustomVariableOperation]`): + Required. The list of operations to + perform on individual conversion custom + variables. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateConversionCustomVariablesResponse: + Response message for + [ConversionCustomVariableService.MutateConversionCustomVariables][google.ads.googleads.v24.services.ConversionCustomVariableService.MutateConversionCustomVariables]. + + """ + # 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 = [customer_id, operations] + 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, + conversion_custom_variable_service.MutateConversionCustomVariablesRequest, + ): + request = conversion_custom_variable_service.MutateConversionCustomVariablesRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_conversion_custom_variables + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ConversionCustomVariableServiceAsyncClient": + 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__ = ("ConversionCustomVariableServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/conversion_custom_variable_service/client.py b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/client.py new file mode 100644 index 000000000..416f683ca --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/client.py @@ -0,0 +1,944 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + conversion_custom_variable_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + ConversionCustomVariableServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ConversionCustomVariableServiceGrpcTransport +from .transports.grpc_asyncio import ( + ConversionCustomVariableServiceGrpcAsyncIOTransport, +) + + +class ConversionCustomVariableServiceClientMeta(type): + """Metaclass for the ConversionCustomVariableService 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[ConversionCustomVariableServiceTransport]] + _transport_registry["grpc"] = ConversionCustomVariableServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + ConversionCustomVariableServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ConversionCustomVariableServiceTransport]: + """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 ConversionCustomVariableServiceClient( + metaclass=ConversionCustomVariableServiceClientMeta +): + """Service to manage conversion custom variables.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ConversionCustomVariableServiceClient: 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: + ConversionCustomVariableServiceClient: 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) -> ConversionCustomVariableServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ConversionCustomVariableServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def conversion_custom_variable_path( + customer_id: str, + conversion_custom_variable_id: str, + ) -> str: + """Returns a fully-qualified conversion_custom_variable string.""" + return "customers/{customer_id}/conversionCustomVariables/{conversion_custom_variable_id}".format( + customer_id=customer_id, + conversion_custom_variable_id=conversion_custom_variable_id, + ) + + @staticmethod + def parse_conversion_custom_variable_path(path: str) -> Dict[str, str]: + """Parses a conversion_custom_variable path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionCustomVariables/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?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 = ( + ConversionCustomVariableServiceClient._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 = ( + ConversionCustomVariableServiceClient._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 + ): + """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 = ( + ConversionCustomVariableServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + ConversionCustomVariableServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = ConversionCustomVariableServiceClient._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 = ( + ConversionCustomVariableServiceClient._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): + """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, + ConversionCustomVariableServiceTransport, + Callable[..., ConversionCustomVariableServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the conversion custom variable 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,ConversionCustomVariableServiceTransport,Callable[..., ConversionCustomVariableServiceTransport]]]): + 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 ConversionCustomVariableServiceTransport 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, + ) = ConversionCustomVariableServiceClient._read_environment_variables() + self._client_cert_source = ( + ConversionCustomVariableServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + ConversionCustomVariableServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ConversionCustomVariableServiceTransport + ) + if transport_provided: + # transport is a ConversionCustomVariableServiceTransport 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( + ConversionCustomVariableServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ConversionCustomVariableServiceClient._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[ConversionCustomVariableServiceTransport], + Callable[..., ConversionCustomVariableServiceTransport], + ] = ( + ConversionCustomVariableServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., ConversionCustomVariableServiceTransport], + 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.ads.googleads.v24.services.ConversionCustomVariableServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ConversionCustomVariableService", + "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.ads.googleads.v24.services.ConversionCustomVariableService", + "credentialsType": None, + } + ), + ) + + def mutate_conversion_custom_variables( + self, + request: Optional[ + Union[ + conversion_custom_variable_service.MutateConversionCustomVariablesRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + conversion_custom_variable_service.ConversionCustomVariableOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + conversion_custom_variable_service.MutateConversionCustomVariablesResponse + ): + r"""Creates or updates conversion custom variables. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionCustomVariableError <>`__ + `DatabaseError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateConversionCustomVariablesRequest, dict]): + The request object. Request message for + [ConversionCustomVariableService.MutateConversionCustomVariables][google.ads.googleads.v24.services.ConversionCustomVariableService.MutateConversionCustomVariables]. + customer_id (str): + Required. The ID of the customer + whose conversion custom variables are + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.ConversionCustomVariableOperation]): + Required. The list of operations to + perform on individual conversion custom + variables. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateConversionCustomVariablesResponse: + Response message for + [ConversionCustomVariableService.MutateConversionCustomVariables][google.ads.googleads.v24.services.ConversionCustomVariableService.MutateConversionCustomVariables]. + + """ + # 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 = [customer_id, operations] + 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, + conversion_custom_variable_service.MutateConversionCustomVariablesRequest, + ): + request = conversion_custom_variable_service.MutateConversionCustomVariablesRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_conversion_custom_variables + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "ConversionCustomVariableServiceClient": + 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() + + +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__ = ("ConversionCustomVariableServiceClient",) diff --git a/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/README.rst b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/README.rst new file mode 100644 index 000000000..2ba67ff48 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ConversionCustomVariableServiceTransport` is the ABC for all transports. +- public child `ConversionCustomVariableServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ConversionCustomVariableServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseConversionCustomVariableServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ConversionCustomVariableServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/__init__.py b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/__init__.py new file mode 100644 index 000000000..8d77916e9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ConversionCustomVariableServiceTransport +from .grpc import ConversionCustomVariableServiceGrpcTransport +from .grpc_asyncio import ConversionCustomVariableServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ConversionCustomVariableServiceTransport]] +_transport_registry["grpc"] = ConversionCustomVariableServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + ConversionCustomVariableServiceGrpcAsyncIOTransport +) + +__all__ = ( + "ConversionCustomVariableServiceTransport", + "ConversionCustomVariableServiceGrpcTransport", + "ConversionCustomVariableServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/base.py b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/base.py new file mode 100644 index 000000000..098ef6259 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + conversion_custom_variable_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 ConversionCustomVariableServiceTransport(abc.ABC): + """Abstract transport class for ConversionCustomVariableService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_conversion_custom_variables: gapic_v1.method.wrap_method( + self.mutate_conversion_custom_variables, + 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 mutate_conversion_custom_variables( + self, + ) -> Callable[ + [ + conversion_custom_variable_service.MutateConversionCustomVariablesRequest + ], + Union[ + conversion_custom_variable_service.MutateConversionCustomVariablesResponse, + Awaitable[ + conversion_custom_variable_service.MutateConversionCustomVariablesResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ConversionCustomVariableServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/grpc.py b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/grpc.py new file mode 100644 index 000000000..1a381b940 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/grpc.py @@ -0,0 +1,396 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + conversion_custom_variable_service, +) +from .base import ConversionCustomVariableServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ConversionCustomVariableService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ConversionCustomVariableService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ConversionCustomVariableServiceGrpcTransport( + ConversionCustomVariableServiceTransport +): + """gRPC backend transport for ConversionCustomVariableService. + + Service to manage conversion custom variables. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_conversion_custom_variables( + self, + ) -> Callable[ + [ + conversion_custom_variable_service.MutateConversionCustomVariablesRequest + ], + conversion_custom_variable_service.MutateConversionCustomVariablesResponse, + ]: + r"""Return a callable for the mutate conversion custom + variables method over gRPC. + + Creates or updates conversion custom variables. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionCustomVariableError <>`__ + `DatabaseError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateConversionCustomVariablesRequest], + ~.MutateConversionCustomVariablesResponse]: + 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 "mutate_conversion_custom_variables" not in self._stubs: + self._stubs["mutate_conversion_custom_variables"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionCustomVariableService/MutateConversionCustomVariables", + request_serializer=conversion_custom_variable_service.MutateConversionCustomVariablesRequest.serialize, + response_deserializer=conversion_custom_variable_service.MutateConversionCustomVariablesResponse.deserialize, + ) + ) + return self._stubs["mutate_conversion_custom_variables"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ConversionCustomVariableServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..13faece78 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_custom_variable_service/transports/grpc_asyncio.py @@ -0,0 +1,419 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + conversion_custom_variable_service, +) +from .base import ConversionCustomVariableServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ConversionCustomVariableService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ConversionCustomVariableService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ConversionCustomVariableServiceGrpcAsyncIOTransport( + ConversionCustomVariableServiceTransport +): + """gRPC AsyncIO backend transport for ConversionCustomVariableService. + + Service to manage conversion custom variables. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_conversion_custom_variables( + self, + ) -> Callable[ + [ + conversion_custom_variable_service.MutateConversionCustomVariablesRequest + ], + Awaitable[ + conversion_custom_variable_service.MutateConversionCustomVariablesResponse + ], + ]: + r"""Return a callable for the mutate conversion custom + variables method over gRPC. + + Creates or updates conversion custom variables. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionCustomVariableError <>`__ + `DatabaseError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateConversionCustomVariablesRequest], + Awaitable[~.MutateConversionCustomVariablesResponse]]: + 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 "mutate_conversion_custom_variables" not in self._stubs: + self._stubs["mutate_conversion_custom_variables"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionCustomVariableService/MutateConversionCustomVariables", + request_serializer=conversion_custom_variable_service.MutateConversionCustomVariablesRequest.serialize, + response_deserializer=conversion_custom_variable_service.MutateConversionCustomVariablesResponse.deserialize, + ) + ) + return self._stubs["mutate_conversion_custom_variables"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_conversion_custom_variables: self._wrap_method( + self.mutate_conversion_custom_variables, + 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" + + +__all__ = ("ConversionCustomVariableServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/__init__.py b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/__init__.py new file mode 100644 index 000000000..1d419e3f5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ConversionGoalCampaignConfigServiceClient +from .async_client import ConversionGoalCampaignConfigServiceAsyncClient + +__all__ = ( + "ConversionGoalCampaignConfigServiceClient", + "ConversionGoalCampaignConfigServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/async_client.py b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/async_client.py new file mode 100644 index 000000000..a036f8522 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/async_client.py @@ -0,0 +1,456 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + conversion_goal_campaign_config_service, +) +from .transports.base import ( + ConversionGoalCampaignConfigServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import ConversionGoalCampaignConfigServiceClient + +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 ConversionGoalCampaignConfigServiceAsyncClient: + """Service to manage conversion goal campaign config.""" + + _client: ConversionGoalCampaignConfigServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ( + ConversionGoalCampaignConfigServiceClient.DEFAULT_ENDPOINT + ) + DEFAULT_MTLS_ENDPOINT = ( + ConversionGoalCampaignConfigServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + ConversionGoalCampaignConfigServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ( + ConversionGoalCampaignConfigServiceClient._DEFAULT_UNIVERSE + ) + + campaign_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.campaign_path + ) + parse_campaign_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.parse_campaign_path + ) + conversion_goal_campaign_config_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.conversion_goal_campaign_config_path + ) + parse_conversion_goal_campaign_config_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.parse_conversion_goal_campaign_config_path + ) + custom_conversion_goal_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.custom_conversion_goal_path + ) + parse_custom_conversion_goal_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.parse_custom_conversion_goal_path + ) + common_billing_account_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ConversionGoalCampaignConfigServiceClient.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: + ConversionGoalCampaignConfigServiceAsyncClient: The constructed client. + """ + return ConversionGoalCampaignConfigServiceClient.from_service_account_info.__func__(ConversionGoalCampaignConfigServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ConversionGoalCampaignConfigServiceAsyncClient: The constructed client. + """ + return ConversionGoalCampaignConfigServiceClient.from_service_account_file.__func__(ConversionGoalCampaignConfigServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ConversionGoalCampaignConfigServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ConversionGoalCampaignConfigServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ConversionGoalCampaignConfigServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + ConversionGoalCampaignConfigServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ConversionGoalCampaignConfigServiceTransport, + Callable[..., ConversionGoalCampaignConfigServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the conversion goal campaign 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,ConversionGoalCampaignConfigServiceTransport,Callable[..., ConversionGoalCampaignConfigServiceTransport]]]): + 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 ConversionGoalCampaignConfigServiceTransport 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 = ConversionGoalCampaignConfigServiceClient( + 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.ads.googleads.v24.services.ConversionGoalCampaignConfigServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ConversionGoalCampaignConfigService", + "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.ads.googleads.v24.services.ConversionGoalCampaignConfigService", + "credentialsType": None, + } + ), + ) + + async def mutate_conversion_goal_campaign_configs( + self, + request: Optional[ + Union[ + conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + conversion_goal_campaign_config_service.ConversionGoalCampaignConfigOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsResponse + ): + r"""Creates, updates or removes conversion goal campaign + config. Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateConversionGoalCampaignConfigsRequest, dict]]): + The request object. Request message for + [ConversionGoalCampaignConfigService.MutateConversionGoalCampaignConfigs][google.ads.googleads.v24.services.ConversionGoalCampaignConfigService.MutateConversionGoalCampaignConfigs]. + customer_id (:class:`str`): + Required. The ID of the customer + whose custom conversion goals are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.ConversionGoalCampaignConfigOperation]`): + Required. The list of operations to + perform on individual conversion goal + campaign config. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateConversionGoalCampaignConfigsResponse: + Response message for a conversion + goal campaign config mutate. + + """ + # 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 = [customer_id, operations] + 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, + conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsRequest, + ): + request = conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_conversion_goal_campaign_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__( + self, + ) -> "ConversionGoalCampaignConfigServiceAsyncClient": + 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__ = ("ConversionGoalCampaignConfigServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/client.py b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/client.py new file mode 100644 index 000000000..ac4abe3e5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/client.py @@ -0,0 +1,967 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + conversion_goal_campaign_config_service, +) +from .transports.base import ( + ConversionGoalCampaignConfigServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ConversionGoalCampaignConfigServiceGrpcTransport +from .transports.grpc_asyncio import ( + ConversionGoalCampaignConfigServiceGrpcAsyncIOTransport, +) + + +class ConversionGoalCampaignConfigServiceClientMeta(type): + """Metaclass for the ConversionGoalCampaignConfigService 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[ConversionGoalCampaignConfigServiceTransport]] + _transport_registry["grpc"] = ( + ConversionGoalCampaignConfigServiceGrpcTransport + ) + _transport_registry["grpc_asyncio"] = ( + ConversionGoalCampaignConfigServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ConversionGoalCampaignConfigServiceTransport]: + """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 ConversionGoalCampaignConfigServiceClient( + metaclass=ConversionGoalCampaignConfigServiceClientMeta +): + """Service to manage conversion goal campaign config.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ConversionGoalCampaignConfigServiceClient: 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: + ConversionGoalCampaignConfigServiceClient: 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) -> ConversionGoalCampaignConfigServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ConversionGoalCampaignConfigServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_goal_campaign_config_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified conversion_goal_campaign_config string.""" + return "customers/{customer_id}/conversionGoalCampaignConfigs/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_conversion_goal_campaign_config_path(path: str) -> Dict[str, str]: + """Parses a conversion_goal_campaign_config path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionGoalCampaignConfigs/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def custom_conversion_goal_path( + customer_id: str, + goal_id: str, + ) -> str: + """Returns a fully-qualified custom_conversion_goal string.""" + return "customers/{customer_id}/customConversionGoals/{goal_id}".format( + customer_id=customer_id, + goal_id=goal_id, + ) + + @staticmethod + def parse_custom_conversion_goal_path(path: str) -> Dict[str, str]: + """Parses a custom_conversion_goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customConversionGoals/(?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 = ( + ConversionGoalCampaignConfigServiceClient._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 = ( + ConversionGoalCampaignConfigServiceClient._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 + ): + """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 = ( + ConversionGoalCampaignConfigServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + ConversionGoalCampaignConfigServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = ConversionGoalCampaignConfigServiceClient._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 = ( + ConversionGoalCampaignConfigServiceClient._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): + """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, + ConversionGoalCampaignConfigServiceTransport, + Callable[..., ConversionGoalCampaignConfigServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the conversion goal campaign 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,ConversionGoalCampaignConfigServiceTransport,Callable[..., ConversionGoalCampaignConfigServiceTransport]]]): + 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 ConversionGoalCampaignConfigServiceTransport 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, + ) = ( + ConversionGoalCampaignConfigServiceClient._read_environment_variables() + ) + self._client_cert_source = ( + ConversionGoalCampaignConfigServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + ConversionGoalCampaignConfigServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ConversionGoalCampaignConfigServiceTransport + ) + if transport_provided: + # transport is a ConversionGoalCampaignConfigServiceTransport 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( + ConversionGoalCampaignConfigServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ConversionGoalCampaignConfigServiceClient._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[ConversionGoalCampaignConfigServiceTransport], + Callable[..., ConversionGoalCampaignConfigServiceTransport], + ] = ( + ConversionGoalCampaignConfigServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., ConversionGoalCampaignConfigServiceTransport], + 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.ads.googleads.v24.services.ConversionGoalCampaignConfigServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ConversionGoalCampaignConfigService", + "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.ads.googleads.v24.services.ConversionGoalCampaignConfigService", + "credentialsType": None, + } + ), + ) + + def mutate_conversion_goal_campaign_configs( + self, + request: Optional[ + Union[ + conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + conversion_goal_campaign_config_service.ConversionGoalCampaignConfigOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsResponse + ): + r"""Creates, updates or removes conversion goal campaign + config. Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateConversionGoalCampaignConfigsRequest, dict]): + The request object. Request message for + [ConversionGoalCampaignConfigService.MutateConversionGoalCampaignConfigs][google.ads.googleads.v24.services.ConversionGoalCampaignConfigService.MutateConversionGoalCampaignConfigs]. + customer_id (str): + Required. The ID of the customer + whose custom conversion goals are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.ConversionGoalCampaignConfigOperation]): + Required. The list of operations to + perform on individual conversion goal + campaign config. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateConversionGoalCampaignConfigsResponse: + Response message for a conversion + goal campaign config mutate. + + """ + # 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 = [customer_id, operations] + 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, + conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsRequest, + ): + request = conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_conversion_goal_campaign_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "ConversionGoalCampaignConfigServiceClient": + 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() + + +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__ = ("ConversionGoalCampaignConfigServiceClient",) diff --git a/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/README.rst b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/README.rst new file mode 100644 index 000000000..1bb2d288a --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ConversionGoalCampaignConfigServiceTransport` is the ABC for all transports. +- public child `ConversionGoalCampaignConfigServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ConversionGoalCampaignConfigServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseConversionGoalCampaignConfigServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ConversionGoalCampaignConfigServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/__init__.py b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/__init__.py new file mode 100644 index 000000000..14583c22c --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/__init__.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ConversionGoalCampaignConfigServiceTransport +from .grpc import ConversionGoalCampaignConfigServiceGrpcTransport +from .grpc_asyncio import ( + ConversionGoalCampaignConfigServiceGrpcAsyncIOTransport, +) + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ConversionGoalCampaignConfigServiceTransport]] +_transport_registry["grpc"] = ConversionGoalCampaignConfigServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + ConversionGoalCampaignConfigServiceGrpcAsyncIOTransport +) + +__all__ = ( + "ConversionGoalCampaignConfigServiceTransport", + "ConversionGoalCampaignConfigServiceGrpcTransport", + "ConversionGoalCampaignConfigServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/base.py b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/base.py new file mode 100644 index 000000000..08f7a94a9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + conversion_goal_campaign_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 ConversionGoalCampaignConfigServiceTransport(abc.ABC): + """Abstract transport class for ConversionGoalCampaignConfigService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_conversion_goal_campaign_configs: gapic_v1.method.wrap_method( + self.mutate_conversion_goal_campaign_configs, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def mutate_conversion_goal_campaign_configs( + self, + ) -> Callable[ + [ + conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsRequest + ], + Union[ + conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsResponse, + Awaitable[ + conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ConversionGoalCampaignConfigServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/grpc.py b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/grpc.py new file mode 100644 index 000000000..38cedcd6d --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/grpc.py @@ -0,0 +1,394 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + conversion_goal_campaign_config_service, +) +from .base import ( + ConversionGoalCampaignConfigServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.ConversionGoalCampaignConfigService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ConversionGoalCampaignConfigService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ConversionGoalCampaignConfigServiceGrpcTransport( + ConversionGoalCampaignConfigServiceTransport +): + """gRPC backend transport for ConversionGoalCampaignConfigService. + + Service to manage conversion goal campaign config. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_conversion_goal_campaign_configs( + self, + ) -> Callable[ + [ + conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsRequest + ], + conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsResponse, + ]: + r"""Return a callable for the mutate conversion goal + campaign configs method over gRPC. + + Creates, updates or removes conversion goal campaign + config. Operation statuses are returned. + + Returns: + Callable[[~.MutateConversionGoalCampaignConfigsRequest], + ~.MutateConversionGoalCampaignConfigsResponse]: + 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 "mutate_conversion_goal_campaign_configs" not in self._stubs: + self._stubs["mutate_conversion_goal_campaign_configs"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionGoalCampaignConfigService/MutateConversionGoalCampaignConfigs", + request_serializer=conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsRequest.serialize, + response_deserializer=conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsResponse.deserialize, + ) + ) + return self._stubs["mutate_conversion_goal_campaign_configs"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ConversionGoalCampaignConfigServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..643f8240c --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_goal_campaign_config_service/transports/grpc_asyncio.py @@ -0,0 +1,417 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + conversion_goal_campaign_config_service, +) +from .base import ( + ConversionGoalCampaignConfigServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.ConversionGoalCampaignConfigService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ConversionGoalCampaignConfigService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ConversionGoalCampaignConfigServiceGrpcAsyncIOTransport( + ConversionGoalCampaignConfigServiceTransport +): + """gRPC AsyncIO backend transport for ConversionGoalCampaignConfigService. + + Service to manage conversion goal campaign config. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_conversion_goal_campaign_configs( + self, + ) -> Callable[ + [ + conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsRequest + ], + Awaitable[ + conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsResponse + ], + ]: + r"""Return a callable for the mutate conversion goal + campaign configs method over gRPC. + + Creates, updates or removes conversion goal campaign + config. Operation statuses are returned. + + Returns: + Callable[[~.MutateConversionGoalCampaignConfigsRequest], + Awaitable[~.MutateConversionGoalCampaignConfigsResponse]]: + 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 "mutate_conversion_goal_campaign_configs" not in self._stubs: + self._stubs["mutate_conversion_goal_campaign_configs"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionGoalCampaignConfigService/MutateConversionGoalCampaignConfigs", + request_serializer=conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsRequest.serialize, + response_deserializer=conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsResponse.deserialize, + ) + ) + return self._stubs["mutate_conversion_goal_campaign_configs"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_conversion_goal_campaign_configs: self._wrap_method( + self.mutate_conversion_goal_campaign_configs, + 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" + + +__all__ = ("ConversionGoalCampaignConfigServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_upload_service/__init__.py b/google/ads/googleads/v24/services/services/conversion_upload_service/__init__.py new file mode 100644 index 000000000..107e0d3bc --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_upload_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ConversionUploadServiceClient +from .async_client import ConversionUploadServiceAsyncClient + +__all__ = ( + "ConversionUploadServiceClient", + "ConversionUploadServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/conversion_upload_service/async_client.py b/google/ads/googleads/v24/services/services/conversion_upload_service/async_client.py new file mode 100644 index 000000000..e2e7ec129 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_upload_service/async_client.py @@ -0,0 +1,570 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import conversion_upload_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + ConversionUploadServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import ConversionUploadServiceClient + +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 ConversionUploadServiceAsyncClient: + """Service to upload conversions.""" + + _client: ConversionUploadServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ConversionUploadServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ConversionUploadServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + ConversionUploadServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ConversionUploadServiceClient._DEFAULT_UNIVERSE + + conversion_custom_variable_path = staticmethod( + ConversionUploadServiceClient.conversion_custom_variable_path + ) + parse_conversion_custom_variable_path = staticmethod( + ConversionUploadServiceClient.parse_conversion_custom_variable_path + ) + common_billing_account_path = staticmethod( + ConversionUploadServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ConversionUploadServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ConversionUploadServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ConversionUploadServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ConversionUploadServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ConversionUploadServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ConversionUploadServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ConversionUploadServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ConversionUploadServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ConversionUploadServiceClient.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: + ConversionUploadServiceAsyncClient: The constructed client. + """ + return ConversionUploadServiceClient.from_service_account_info.__func__(ConversionUploadServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ConversionUploadServiceAsyncClient: The constructed client. + """ + return ConversionUploadServiceClient.from_service_account_file.__func__(ConversionUploadServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ConversionUploadServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ConversionUploadServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ConversionUploadServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ConversionUploadServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ConversionUploadServiceTransport, + Callable[..., ConversionUploadServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the conversion upload 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,ConversionUploadServiceTransport,Callable[..., ConversionUploadServiceTransport]]]): + 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 ConversionUploadServiceTransport 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 = ConversionUploadServiceClient( + 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.ads.googleads.v24.services.ConversionUploadServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ConversionUploadService", + "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.ads.googleads.v24.services.ConversionUploadService", + "credentialsType": None, + } + ), + ) + + async def upload_click_conversions( + self, + request: Optional[ + Union[conversion_upload_service.UploadClickConversionsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + conversions: Optional[ + MutableSequence[conversion_upload_service.ClickConversion] + ] = None, + partial_failure: Optional[bool] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> conversion_upload_service.UploadClickConversionsResponse: + r"""Processes the given click conversions. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionUploadError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `PartialFailureError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.UploadClickConversionsRequest, dict]]): + The request object. Request message for + [ConversionUploadService.UploadClickConversions][google.ads.googleads.v24.services.ConversionUploadService.UploadClickConversions]. + customer_id (:class:`str`): + Required. The ID of the customer + performing the upload. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + conversions (:class:`MutableSequence[google.ads.googleads.v24.services.types.ClickConversion]`): + Required. The conversions that are + being uploaded. + + This corresponds to the ``conversions`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + partial_failure (:class:`bool`): + Required. If ``true``, successful operations will be + carried out and invalid operations will return errors. + If ``false``, all operations will be carried out in one + transaction if and only if they are all valid. This + should always be set to ``true``. + + See `Best practices for partial + failures `__. + + This corresponds to the ``partial_failure`` 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.ads.googleads.v24.services.types.UploadClickConversionsResponse: + Response message for + [ConversionUploadService.UploadClickConversions][google.ads.googleads.v24.services.ConversionUploadService.UploadClickConversions]. + + """ + # 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 = [customer_id, conversions, partial_failure] + 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, conversion_upload_service.UploadClickConversionsRequest + ): + request = conversion_upload_service.UploadClickConversionsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if partial_failure is not None: + request.partial_failure = partial_failure + if conversions: + request.conversions.extend(conversions) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.upload_click_conversions + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 upload_call_conversions( + self, + request: Optional[ + Union[conversion_upload_service.UploadCallConversionsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + conversions: Optional[ + MutableSequence[conversion_upload_service.CallConversion] + ] = None, + partial_failure: Optional[bool] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> conversion_upload_service.UploadCallConversionsResponse: + r"""Processes the given call conversions. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `PartialFailureError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.UploadCallConversionsRequest, dict]]): + The request object. Request message for + [ConversionUploadService.UploadCallConversions][google.ads.googleads.v24.services.ConversionUploadService.UploadCallConversions]. + customer_id (:class:`str`): + Required. The ID of the customer + performing the upload. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + conversions (:class:`MutableSequence[google.ads.googleads.v24.services.types.CallConversion]`): + Required. The conversions that are + being uploaded. + + This corresponds to the ``conversions`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + partial_failure (:class:`bool`): + Required. If ``true``, successful operations will be + carried out and invalid operations will return errors. + If ``false``, all operations will be carried out in one + transaction if and only if they are all valid. + + This should always be set to ``true``. + + See `Best practices for partial + failures `__. + + This corresponds to the ``partial_failure`` 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.ads.googleads.v24.services.types.UploadCallConversionsResponse: + Response message for + [ConversionUploadService.UploadCallConversions][google.ads.googleads.v24.services.ConversionUploadService.UploadCallConversions]. + + """ + # 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 = [customer_id, conversions, partial_failure] + 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, conversion_upload_service.UploadCallConversionsRequest + ): + request = conversion_upload_service.UploadCallConversionsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if partial_failure is not None: + request.partial_failure = partial_failure + if conversions: + request.conversions.extend(conversions) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.upload_call_conversions + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ConversionUploadServiceAsyncClient": + 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__ = ("ConversionUploadServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/conversion_upload_service/client.py b/google/ads/googleads/v24/services/services/conversion_upload_service/client.py new file mode 100644 index 000000000..978dd2840 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_upload_service/client.py @@ -0,0 +1,1047 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import conversion_upload_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + ConversionUploadServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ConversionUploadServiceGrpcTransport +from .transports.grpc_asyncio import ConversionUploadServiceGrpcAsyncIOTransport + + +class ConversionUploadServiceClientMeta(type): + """Metaclass for the ConversionUploadService 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[ConversionUploadServiceTransport]] + _transport_registry["grpc"] = ConversionUploadServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + ConversionUploadServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ConversionUploadServiceTransport]: + """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 ConversionUploadServiceClient( + metaclass=ConversionUploadServiceClientMeta +): + """Service to upload conversions.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ConversionUploadServiceClient: 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: + ConversionUploadServiceClient: 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) -> ConversionUploadServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ConversionUploadServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def conversion_custom_variable_path( + customer_id: str, + conversion_custom_variable_id: str, + ) -> str: + """Returns a fully-qualified conversion_custom_variable string.""" + return "customers/{customer_id}/conversionCustomVariables/{conversion_custom_variable_id}".format( + customer_id=customer_id, + conversion_custom_variable_id=conversion_custom_variable_id, + ) + + @staticmethod + def parse_conversion_custom_variable_path(path: str) -> Dict[str, str]: + """Parses a conversion_custom_variable path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionCustomVariables/(?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 = ( + ConversionUploadServiceClient._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 = ( + ConversionUploadServiceClient._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 + ): + """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 = ConversionUploadServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ConversionUploadServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + ConversionUploadServiceClient._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 = ConversionUploadServiceClient._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): + """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, + ConversionUploadServiceTransport, + Callable[..., ConversionUploadServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the conversion upload 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,ConversionUploadServiceTransport,Callable[..., ConversionUploadServiceTransport]]]): + 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 ConversionUploadServiceTransport 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, + ) = ConversionUploadServiceClient._read_environment_variables() + self._client_cert_source = ( + ConversionUploadServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + ConversionUploadServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ConversionUploadServiceTransport + ) + if transport_provided: + # transport is a ConversionUploadServiceTransport 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(ConversionUploadServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ConversionUploadServiceClient._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[ConversionUploadServiceTransport], + Callable[..., ConversionUploadServiceTransport], + ] = ( + ConversionUploadServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., ConversionUploadServiceTransport], 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.ads.googleads.v24.services.ConversionUploadServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ConversionUploadService", + "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.ads.googleads.v24.services.ConversionUploadService", + "credentialsType": None, + } + ), + ) + + def upload_click_conversions( + self, + request: Optional[ + Union[conversion_upload_service.UploadClickConversionsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + conversions: Optional[ + MutableSequence[conversion_upload_service.ClickConversion] + ] = None, + partial_failure: Optional[bool] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> conversion_upload_service.UploadClickConversionsResponse: + r"""Processes the given click conversions. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionUploadError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `PartialFailureError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.UploadClickConversionsRequest, dict]): + The request object. Request message for + [ConversionUploadService.UploadClickConversions][google.ads.googleads.v24.services.ConversionUploadService.UploadClickConversions]. + customer_id (str): + Required. The ID of the customer + performing the upload. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + conversions (MutableSequence[google.ads.googleads.v24.services.types.ClickConversion]): + Required. The conversions that are + being uploaded. + + This corresponds to the ``conversions`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + partial_failure (bool): + Required. If ``true``, successful operations will be + carried out and invalid operations will return errors. + If ``false``, all operations will be carried out in one + transaction if and only if they are all valid. This + should always be set to ``true``. + + See `Best practices for partial + failures `__. + + This corresponds to the ``partial_failure`` 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.ads.googleads.v24.services.types.UploadClickConversionsResponse: + Response message for + [ConversionUploadService.UploadClickConversions][google.ads.googleads.v24.services.ConversionUploadService.UploadClickConversions]. + + """ + # 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 = [customer_id, conversions, partial_failure] + 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, conversion_upload_service.UploadClickConversionsRequest + ): + request = conversion_upload_service.UploadClickConversionsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if conversions is not None: + request.conversions = conversions + if partial_failure is not None: + request.partial_failure = partial_failure + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.upload_click_conversions + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 upload_call_conversions( + self, + request: Optional[ + Union[conversion_upload_service.UploadCallConversionsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + conversions: Optional[ + MutableSequence[conversion_upload_service.CallConversion] + ] = None, + partial_failure: Optional[bool] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> conversion_upload_service.UploadCallConversionsResponse: + r"""Processes the given call conversions. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `PartialFailureError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.UploadCallConversionsRequest, dict]): + The request object. Request message for + [ConversionUploadService.UploadCallConversions][google.ads.googleads.v24.services.ConversionUploadService.UploadCallConversions]. + customer_id (str): + Required. The ID of the customer + performing the upload. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + conversions (MutableSequence[google.ads.googleads.v24.services.types.CallConversion]): + Required. The conversions that are + being uploaded. + + This corresponds to the ``conversions`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + partial_failure (bool): + Required. If ``true``, successful operations will be + carried out and invalid operations will return errors. + If ``false``, all operations will be carried out in one + transaction if and only if they are all valid. + + This should always be set to ``true``. + + See `Best practices for partial + failures `__. + + This corresponds to the ``partial_failure`` 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.ads.googleads.v24.services.types.UploadCallConversionsResponse: + Response message for + [ConversionUploadService.UploadCallConversions][google.ads.googleads.v24.services.ConversionUploadService.UploadCallConversions]. + + """ + # 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 = [customer_id, conversions, partial_failure] + 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, conversion_upload_service.UploadCallConversionsRequest + ): + request = conversion_upload_service.UploadCallConversionsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if conversions is not None: + request.conversions = conversions + if partial_failure is not None: + request.partial_failure = partial_failure + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.upload_call_conversions + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "ConversionUploadServiceClient": + 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() + + +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__ = ("ConversionUploadServiceClient",) diff --git a/google/ads/googleads/v24/services/services/conversion_upload_service/transports/README.rst b/google/ads/googleads/v24/services/services/conversion_upload_service/transports/README.rst new file mode 100644 index 000000000..367cbdcd5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_upload_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ConversionUploadServiceTransport` is the ABC for all transports. +- public child `ConversionUploadServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ConversionUploadServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseConversionUploadServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ConversionUploadServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/conversion_upload_service/transports/__init__.py b/google/ads/googleads/v24/services/services/conversion_upload_service/transports/__init__.py new file mode 100644 index 000000000..e792cf278 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_upload_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ConversionUploadServiceTransport +from .grpc import ConversionUploadServiceGrpcTransport +from .grpc_asyncio import ConversionUploadServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ConversionUploadServiceTransport]] +_transport_registry["grpc"] = ConversionUploadServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + ConversionUploadServiceGrpcAsyncIOTransport +) + +__all__ = ( + "ConversionUploadServiceTransport", + "ConversionUploadServiceGrpcTransport", + "ConversionUploadServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/conversion_upload_service/transports/base.py b/google/ads/googleads/v24/services/services/conversion_upload_service/transports/base.py new file mode 100644 index 000000000..19a2bf87d --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_upload_service/transports/base.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import conversion_upload_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 ConversionUploadServiceTransport(abc.ABC): + """Abstract transport class for ConversionUploadService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.upload_click_conversions: gapic_v1.method.wrap_method( + self.upload_click_conversions, + default_timeout=None, + client_info=client_info, + ), + self.upload_call_conversions: gapic_v1.method.wrap_method( + self.upload_call_conversions, + 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 upload_click_conversions( + self, + ) -> Callable[ + [conversion_upload_service.UploadClickConversionsRequest], + Union[ + conversion_upload_service.UploadClickConversionsResponse, + Awaitable[conversion_upload_service.UploadClickConversionsResponse], + ], + ]: + raise NotImplementedError() + + @property + def upload_call_conversions( + self, + ) -> Callable[ + [conversion_upload_service.UploadCallConversionsRequest], + Union[ + conversion_upload_service.UploadCallConversionsResponse, + Awaitable[conversion_upload_service.UploadCallConversionsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ConversionUploadServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_upload_service/transports/grpc.py b/google/ads/googleads/v24/services/services/conversion_upload_service/transports/grpc.py new file mode 100644 index 000000000..20491e23f --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_upload_service/transports/grpc.py @@ -0,0 +1,424 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import conversion_upload_service +from .base import ConversionUploadServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ConversionUploadService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ConversionUploadService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ConversionUploadServiceGrpcTransport(ConversionUploadServiceTransport): + """gRPC backend transport for ConversionUploadService. + + Service to upload conversions. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 upload_click_conversions( + self, + ) -> Callable[ + [conversion_upload_service.UploadClickConversionsRequest], + conversion_upload_service.UploadClickConversionsResponse, + ]: + r"""Return a callable for the upload click conversions method over gRPC. + + Processes the given click conversions. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionUploadError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `PartialFailureError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.UploadClickConversionsRequest], + ~.UploadClickConversionsResponse]: + 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 "upload_click_conversions" not in self._stubs: + self._stubs["upload_click_conversions"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionUploadService/UploadClickConversions", + request_serializer=conversion_upload_service.UploadClickConversionsRequest.serialize, + response_deserializer=conversion_upload_service.UploadClickConversionsResponse.deserialize, + ) + ) + return self._stubs["upload_click_conversions"] + + @property + def upload_call_conversions( + self, + ) -> Callable[ + [conversion_upload_service.UploadCallConversionsRequest], + conversion_upload_service.UploadCallConversionsResponse, + ]: + r"""Return a callable for the upload call conversions method over gRPC. + + Processes the given call conversions. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `PartialFailureError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.UploadCallConversionsRequest], + ~.UploadCallConversionsResponse]: + 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 "upload_call_conversions" not in self._stubs: + self._stubs["upload_call_conversions"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionUploadService/UploadCallConversions", + request_serializer=conversion_upload_service.UploadCallConversionsRequest.serialize, + response_deserializer=conversion_upload_service.UploadCallConversionsResponse.deserialize, + ) + ) + return self._stubs["upload_call_conversions"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ConversionUploadServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_upload_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/conversion_upload_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..d3cbc3c25 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_upload_service/transports/grpc_asyncio.py @@ -0,0 +1,452 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import conversion_upload_service +from .base import ConversionUploadServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ConversionUploadService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ConversionUploadService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ConversionUploadServiceGrpcAsyncIOTransport( + ConversionUploadServiceTransport +): + """gRPC AsyncIO backend transport for ConversionUploadService. + + Service to upload conversions. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 upload_click_conversions( + self, + ) -> Callable[ + [conversion_upload_service.UploadClickConversionsRequest], + Awaitable[conversion_upload_service.UploadClickConversionsResponse], + ]: + r"""Return a callable for the upload click conversions method over gRPC. + + Processes the given click conversions. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionUploadError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `PartialFailureError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.UploadClickConversionsRequest], + Awaitable[~.UploadClickConversionsResponse]]: + 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 "upload_click_conversions" not in self._stubs: + self._stubs["upload_click_conversions"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionUploadService/UploadClickConversions", + request_serializer=conversion_upload_service.UploadClickConversionsRequest.serialize, + response_deserializer=conversion_upload_service.UploadClickConversionsResponse.deserialize, + ) + ) + return self._stubs["upload_click_conversions"] + + @property + def upload_call_conversions( + self, + ) -> Callable[ + [conversion_upload_service.UploadCallConversionsRequest], + Awaitable[conversion_upload_service.UploadCallConversionsResponse], + ]: + r"""Return a callable for the upload call conversions method over gRPC. + + Processes the given call conversions. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `PartialFailureError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.UploadCallConversionsRequest], + Awaitable[~.UploadCallConversionsResponse]]: + 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 "upload_call_conversions" not in self._stubs: + self._stubs["upload_call_conversions"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionUploadService/UploadCallConversions", + request_serializer=conversion_upload_service.UploadCallConversionsRequest.serialize, + response_deserializer=conversion_upload_service.UploadCallConversionsResponse.deserialize, + ) + ) + return self._stubs["upload_call_conversions"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.upload_click_conversions: self._wrap_method( + self.upload_click_conversions, + default_timeout=None, + client_info=client_info, + ), + self.upload_call_conversions: self._wrap_method( + self.upload_call_conversions, + 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" + + +__all__ = ("ConversionUploadServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_service/__init__.py b/google/ads/googleads/v24/services/services/conversion_value_rule_service/__init__.py new file mode 100644 index 000000000..a95457fac --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ConversionValueRuleServiceClient +from .async_client import ConversionValueRuleServiceAsyncClient + +__all__ = ( + "ConversionValueRuleServiceClient", + "ConversionValueRuleServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_service/async_client.py b/google/ads/googleads/v24/services/services/conversion_value_rule_service/async_client.py new file mode 100644 index 000000000..0f21e3a13 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_service/async_client.py @@ -0,0 +1,459 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + conversion_value_rule_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + ConversionValueRuleServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import ConversionValueRuleServiceClient + +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 ConversionValueRuleServiceAsyncClient: + """Service to manage conversion value rules.""" + + _client: ConversionValueRuleServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ConversionValueRuleServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + ConversionValueRuleServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + ConversionValueRuleServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ConversionValueRuleServiceClient._DEFAULT_UNIVERSE + + conversion_value_rule_path = staticmethod( + ConversionValueRuleServiceClient.conversion_value_rule_path + ) + parse_conversion_value_rule_path = staticmethod( + ConversionValueRuleServiceClient.parse_conversion_value_rule_path + ) + customer_path = staticmethod(ConversionValueRuleServiceClient.customer_path) + parse_customer_path = staticmethod( + ConversionValueRuleServiceClient.parse_customer_path + ) + geo_target_constant_path = staticmethod( + ConversionValueRuleServiceClient.geo_target_constant_path + ) + parse_geo_target_constant_path = staticmethod( + ConversionValueRuleServiceClient.parse_geo_target_constant_path + ) + user_interest_path = staticmethod( + ConversionValueRuleServiceClient.user_interest_path + ) + parse_user_interest_path = staticmethod( + ConversionValueRuleServiceClient.parse_user_interest_path + ) + user_list_path = staticmethod( + ConversionValueRuleServiceClient.user_list_path + ) + parse_user_list_path = staticmethod( + ConversionValueRuleServiceClient.parse_user_list_path + ) + common_billing_account_path = staticmethod( + ConversionValueRuleServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ConversionValueRuleServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ConversionValueRuleServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ConversionValueRuleServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ConversionValueRuleServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ConversionValueRuleServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ConversionValueRuleServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ConversionValueRuleServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ConversionValueRuleServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ConversionValueRuleServiceClient.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: + ConversionValueRuleServiceAsyncClient: The constructed client. + """ + return ConversionValueRuleServiceClient.from_service_account_info.__func__(ConversionValueRuleServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ConversionValueRuleServiceAsyncClient: The constructed client. + """ + return ConversionValueRuleServiceClient.from_service_account_file.__func__(ConversionValueRuleServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ConversionValueRuleServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ConversionValueRuleServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ConversionValueRuleServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ConversionValueRuleServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ConversionValueRuleServiceTransport, + Callable[..., ConversionValueRuleServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the conversion value rule 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,ConversionValueRuleServiceTransport,Callable[..., ConversionValueRuleServiceTransport]]]): + 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 ConversionValueRuleServiceTransport 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 = ConversionValueRuleServiceClient( + 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.ads.googleads.v24.services.ConversionValueRuleServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ConversionValueRuleService", + "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.ads.googleads.v24.services.ConversionValueRuleService", + "credentialsType": None, + } + ), + ) + + async def mutate_conversion_value_rules( + self, + request: Optional[ + Union[ + conversion_value_rule_service.MutateConversionValueRulesRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + conversion_value_rule_service.ConversionValueRuleOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> conversion_value_rule_service.MutateConversionValueRulesResponse: + r"""Creates, updates, or removes conversion value rules. + Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateConversionValueRulesRequest, dict]]): + The request object. Request message for + [ConversionValueRuleService.MutateConversionValueRules][google.ads.googleads.v24.services.ConversionValueRuleService.MutateConversionValueRules]. + customer_id (:class:`str`): + Required. The ID of the customer + whose conversion value rules are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.ConversionValueRuleOperation]`): + Required. The list of operations to + perform on individual conversion value + rules. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateConversionValueRulesResponse: + Response message for + [ConversionValueRuleService.MutateConversionValueRules][google.ads.googleads.v24.services.ConversionValueRuleService.MutateConversionValueRules]. + + """ + # 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 = [customer_id, operations] + 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, + conversion_value_rule_service.MutateConversionValueRulesRequest, + ): + request = ( + conversion_value_rule_service.MutateConversionValueRulesRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_conversion_value_rules + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ConversionValueRuleServiceAsyncClient": + 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__ = ("ConversionValueRuleServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_service/client.py b/google/ads/googleads/v24/services/services/conversion_value_rule_service/client.py new file mode 100644 index 000000000..4450bc4ad --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_service/client.py @@ -0,0 +1,992 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + conversion_value_rule_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + ConversionValueRuleServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ConversionValueRuleServiceGrpcTransport +from .transports.grpc_asyncio import ( + ConversionValueRuleServiceGrpcAsyncIOTransport, +) + + +class ConversionValueRuleServiceClientMeta(type): + """Metaclass for the ConversionValueRuleService 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[ConversionValueRuleServiceTransport]] + _transport_registry["grpc"] = ConversionValueRuleServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + ConversionValueRuleServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ConversionValueRuleServiceTransport]: + """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 ConversionValueRuleServiceClient( + metaclass=ConversionValueRuleServiceClientMeta +): + """Service to manage conversion value rules.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ConversionValueRuleServiceClient: 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: + ConversionValueRuleServiceClient: 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) -> ConversionValueRuleServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ConversionValueRuleServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def conversion_value_rule_path( + customer_id: str, + conversion_value_rule_id: str, + ) -> str: + """Returns a fully-qualified conversion_value_rule string.""" + return "customers/{customer_id}/conversionValueRules/{conversion_value_rule_id}".format( + customer_id=customer_id, + conversion_value_rule_id=conversion_value_rule_id, + ) + + @staticmethod + def parse_conversion_value_rule_path(path: str) -> Dict[str, str]: + """Parses a conversion_value_rule path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionValueRules/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def geo_target_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified geo_target_constant string.""" + return "geoTargetConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_geo_target_constant_path(path: str) -> Dict[str, str]: + """Parses a geo_target_constant path into its component segments.""" + m = re.match(r"^geoTargetConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def user_interest_path( + customer_id: str, + user_interest_id: str, + ) -> str: + """Returns a fully-qualified user_interest string.""" + return ( + "customers/{customer_id}/userInterests/{user_interest_id}".format( + customer_id=customer_id, + user_interest_id=user_interest_id, + ) + ) + + @staticmethod + def parse_user_interest_path(path: str) -> Dict[str, str]: + """Parses a user_interest path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/userInterests/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def user_list_path( + customer_id: str, + user_list_id: str, + ) -> str: + """Returns a fully-qualified user_list string.""" + return "customers/{customer_id}/userLists/{user_list_id}".format( + customer_id=customer_id, + user_list_id=user_list_id, + ) + + @staticmethod + def parse_user_list_path(path: str) -> Dict[str, str]: + """Parses a user_list path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/userLists/(?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 = ( + ConversionValueRuleServiceClient._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 = ( + ConversionValueRuleServiceClient._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 + ): + """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 = ( + ConversionValueRuleServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + ConversionValueRuleServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = ConversionValueRuleServiceClient._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 = ConversionValueRuleServiceClient._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): + """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, + ConversionValueRuleServiceTransport, + Callable[..., ConversionValueRuleServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the conversion value rule 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,ConversionValueRuleServiceTransport,Callable[..., ConversionValueRuleServiceTransport]]]): + 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 ConversionValueRuleServiceTransport 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, + ) = ConversionValueRuleServiceClient._read_environment_variables() + self._client_cert_source = ( + ConversionValueRuleServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + ConversionValueRuleServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ConversionValueRuleServiceTransport + ) + if transport_provided: + # transport is a ConversionValueRuleServiceTransport 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( + ConversionValueRuleServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ConversionValueRuleServiceClient._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[ConversionValueRuleServiceTransport], + Callable[..., ConversionValueRuleServiceTransport], + ] = ( + ConversionValueRuleServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., ConversionValueRuleServiceTransport], + 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.ads.googleads.v24.services.ConversionValueRuleServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ConversionValueRuleService", + "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.ads.googleads.v24.services.ConversionValueRuleService", + "credentialsType": None, + } + ), + ) + + def mutate_conversion_value_rules( + self, + request: Optional[ + Union[ + conversion_value_rule_service.MutateConversionValueRulesRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + conversion_value_rule_service.ConversionValueRuleOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> conversion_value_rule_service.MutateConversionValueRulesResponse: + r"""Creates, updates, or removes conversion value rules. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateConversionValueRulesRequest, dict]): + The request object. Request message for + [ConversionValueRuleService.MutateConversionValueRules][google.ads.googleads.v24.services.ConversionValueRuleService.MutateConversionValueRules]. + customer_id (str): + Required. The ID of the customer + whose conversion value rules are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.ConversionValueRuleOperation]): + Required. The list of operations to + perform on individual conversion value + rules. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateConversionValueRulesResponse: + Response message for + [ConversionValueRuleService.MutateConversionValueRules][google.ads.googleads.v24.services.ConversionValueRuleService.MutateConversionValueRules]. + + """ + # 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 = [customer_id, operations] + 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, + conversion_value_rule_service.MutateConversionValueRulesRequest, + ): + request = ( + conversion_value_rule_service.MutateConversionValueRulesRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_conversion_value_rules + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "ConversionValueRuleServiceClient": + 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() + + +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__ = ("ConversionValueRuleServiceClient",) diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/README.rst b/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/README.rst new file mode 100644 index 000000000..a00255c24 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ConversionValueRuleServiceTransport` is the ABC for all transports. +- public child `ConversionValueRuleServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ConversionValueRuleServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseConversionValueRuleServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ConversionValueRuleServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/__init__.py b/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/__init__.py new file mode 100644 index 000000000..8dc26f250 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ConversionValueRuleServiceTransport +from .grpc import ConversionValueRuleServiceGrpcTransport +from .grpc_asyncio import ConversionValueRuleServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ConversionValueRuleServiceTransport]] +_transport_registry["grpc"] = ConversionValueRuleServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + ConversionValueRuleServiceGrpcAsyncIOTransport +) + +__all__ = ( + "ConversionValueRuleServiceTransport", + "ConversionValueRuleServiceGrpcTransport", + "ConversionValueRuleServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/base.py b/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/base.py new file mode 100644 index 000000000..6b8539b19 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + conversion_value_rule_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 ConversionValueRuleServiceTransport(abc.ABC): + """Abstract transport class for ConversionValueRuleService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_conversion_value_rules: gapic_v1.method.wrap_method( + self.mutate_conversion_value_rules, + 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 mutate_conversion_value_rules( + self, + ) -> Callable[ + [conversion_value_rule_service.MutateConversionValueRulesRequest], + Union[ + conversion_value_rule_service.MutateConversionValueRulesResponse, + Awaitable[ + conversion_value_rule_service.MutateConversionValueRulesResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ConversionValueRuleServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/grpc.py b/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/grpc.py new file mode 100644 index 000000000..b46488e85 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/grpc.py @@ -0,0 +1,388 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + conversion_value_rule_service, +) +from .base import ConversionValueRuleServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ConversionValueRuleService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ConversionValueRuleService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ConversionValueRuleServiceGrpcTransport( + ConversionValueRuleServiceTransport +): + """gRPC backend transport for ConversionValueRuleService. + + Service to manage conversion value rules. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_conversion_value_rules( + self, + ) -> Callable[ + [conversion_value_rule_service.MutateConversionValueRulesRequest], + conversion_value_rule_service.MutateConversionValueRulesResponse, + ]: + r"""Return a callable for the mutate conversion value rules method over gRPC. + + Creates, updates, or removes conversion value rules. + Operation statuses are returned. + + Returns: + Callable[[~.MutateConversionValueRulesRequest], + ~.MutateConversionValueRulesResponse]: + 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 "mutate_conversion_value_rules" not in self._stubs: + self._stubs["mutate_conversion_value_rules"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionValueRuleService/MutateConversionValueRules", + request_serializer=conversion_value_rule_service.MutateConversionValueRulesRequest.serialize, + response_deserializer=conversion_value_rule_service.MutateConversionValueRulesResponse.deserialize, + ) + ) + return self._stubs["mutate_conversion_value_rules"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ConversionValueRuleServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..593af94c1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_service/transports/grpc_asyncio.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + conversion_value_rule_service, +) +from .base import ConversionValueRuleServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ConversionValueRuleService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ConversionValueRuleService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ConversionValueRuleServiceGrpcAsyncIOTransport( + ConversionValueRuleServiceTransport +): + """gRPC AsyncIO backend transport for ConversionValueRuleService. + + Service to manage conversion value rules. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_conversion_value_rules( + self, + ) -> Callable[ + [conversion_value_rule_service.MutateConversionValueRulesRequest], + Awaitable[ + conversion_value_rule_service.MutateConversionValueRulesResponse + ], + ]: + r"""Return a callable for the mutate conversion value rules method over gRPC. + + Creates, updates, or removes conversion value rules. + Operation statuses are returned. + + Returns: + Callable[[~.MutateConversionValueRulesRequest], + Awaitable[~.MutateConversionValueRulesResponse]]: + 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 "mutate_conversion_value_rules" not in self._stubs: + self._stubs["mutate_conversion_value_rules"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionValueRuleService/MutateConversionValueRules", + request_serializer=conversion_value_rule_service.MutateConversionValueRulesRequest.serialize, + response_deserializer=conversion_value_rule_service.MutateConversionValueRulesResponse.deserialize, + ) + ) + return self._stubs["mutate_conversion_value_rules"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_conversion_value_rules: self._wrap_method( + self.mutate_conversion_value_rules, + 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" + + +__all__ = ("ConversionValueRuleServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/__init__.py b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/__init__.py new file mode 100644 index 000000000..42a290c23 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ConversionValueRuleSetServiceClient +from .async_client import ConversionValueRuleSetServiceAsyncClient + +__all__ = ( + "ConversionValueRuleSetServiceClient", + "ConversionValueRuleSetServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/async_client.py b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/async_client.py new file mode 100644 index 000000000..ab7c5b1cf --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/async_client.py @@ -0,0 +1,457 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + conversion_value_rule_set_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + ConversionValueRuleSetServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import ConversionValueRuleSetServiceClient + +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 ConversionValueRuleSetServiceAsyncClient: + """Service to manage conversion value rule sets.""" + + _client: ConversionValueRuleSetServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ConversionValueRuleSetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + ConversionValueRuleSetServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + ConversionValueRuleSetServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ConversionValueRuleSetServiceClient._DEFAULT_UNIVERSE + + campaign_path = staticmethod( + ConversionValueRuleSetServiceClient.campaign_path + ) + parse_campaign_path = staticmethod( + ConversionValueRuleSetServiceClient.parse_campaign_path + ) + conversion_value_rule_path = staticmethod( + ConversionValueRuleSetServiceClient.conversion_value_rule_path + ) + parse_conversion_value_rule_path = staticmethod( + ConversionValueRuleSetServiceClient.parse_conversion_value_rule_path + ) + conversion_value_rule_set_path = staticmethod( + ConversionValueRuleSetServiceClient.conversion_value_rule_set_path + ) + parse_conversion_value_rule_set_path = staticmethod( + ConversionValueRuleSetServiceClient.parse_conversion_value_rule_set_path + ) + customer_path = staticmethod( + ConversionValueRuleSetServiceClient.customer_path + ) + parse_customer_path = staticmethod( + ConversionValueRuleSetServiceClient.parse_customer_path + ) + common_billing_account_path = staticmethod( + ConversionValueRuleSetServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ConversionValueRuleSetServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ConversionValueRuleSetServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ConversionValueRuleSetServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ConversionValueRuleSetServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ConversionValueRuleSetServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ConversionValueRuleSetServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ConversionValueRuleSetServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ConversionValueRuleSetServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ConversionValueRuleSetServiceClient.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: + ConversionValueRuleSetServiceAsyncClient: The constructed client. + """ + return ConversionValueRuleSetServiceClient.from_service_account_info.__func__(ConversionValueRuleSetServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ConversionValueRuleSetServiceAsyncClient: The constructed client. + """ + return ConversionValueRuleSetServiceClient.from_service_account_file.__func__(ConversionValueRuleSetServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ConversionValueRuleSetServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ConversionValueRuleSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ConversionValueRuleSetServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + ConversionValueRuleSetServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ConversionValueRuleSetServiceTransport, + Callable[..., ConversionValueRuleSetServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the conversion value rule set 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,ConversionValueRuleSetServiceTransport,Callable[..., ConversionValueRuleSetServiceTransport]]]): + 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 ConversionValueRuleSetServiceTransport 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 = ConversionValueRuleSetServiceClient( + 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.ads.googleads.v24.services.ConversionValueRuleSetServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ConversionValueRuleSetService", + "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.ads.googleads.v24.services.ConversionValueRuleSetService", + "credentialsType": None, + } + ), + ) + + async def mutate_conversion_value_rule_sets( + self, + request: Optional[ + Union[ + conversion_value_rule_set_service.MutateConversionValueRuleSetsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + conversion_value_rule_set_service.ConversionValueRuleSetOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + conversion_value_rule_set_service.MutateConversionValueRuleSetsResponse + ): + r"""Creates, updates or removes conversion value rule + sets. Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateConversionValueRuleSetsRequest, dict]]): + The request object. Request message for + [ConversionValueRuleSetService.MutateConversionValueRuleSets][google.ads.googleads.v24.services.ConversionValueRuleSetService.MutateConversionValueRuleSets]. + customer_id (:class:`str`): + Required. The ID of the customer + whose conversion value rule sets are + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.ConversionValueRuleSetOperation]`): + Required. The list of operations to + perform on individual conversion value + rule sets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateConversionValueRuleSetsResponse: + Response message for + [ConversionValueRuleSetService.MutateConversionValueRuleSets][google.ads.googleads.v24.services.ConversionValueRuleSetService.MutateConversionValueRuleSets]. + + """ + # 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 = [customer_id, operations] + 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, + conversion_value_rule_set_service.MutateConversionValueRuleSetsRequest, + ): + request = conversion_value_rule_set_service.MutateConversionValueRuleSetsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_conversion_value_rule_sets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ConversionValueRuleSetServiceAsyncClient": + 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__ = ("ConversionValueRuleSetServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/client.py b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/client.py new file mode 100644 index 000000000..9221e45dc --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/client.py @@ -0,0 +1,977 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + conversion_value_rule_set_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + ConversionValueRuleSetServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ConversionValueRuleSetServiceGrpcTransport +from .transports.grpc_asyncio import ( + ConversionValueRuleSetServiceGrpcAsyncIOTransport, +) + + +class ConversionValueRuleSetServiceClientMeta(type): + """Metaclass for the ConversionValueRuleSetService 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[ConversionValueRuleSetServiceTransport]] + _transport_registry["grpc"] = ConversionValueRuleSetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + ConversionValueRuleSetServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ConversionValueRuleSetServiceTransport]: + """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 ConversionValueRuleSetServiceClient( + metaclass=ConversionValueRuleSetServiceClientMeta +): + """Service to manage conversion value rule sets.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ConversionValueRuleSetServiceClient: 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: + ConversionValueRuleSetServiceClient: 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) -> ConversionValueRuleSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ConversionValueRuleSetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_value_rule_path( + customer_id: str, + conversion_value_rule_id: str, + ) -> str: + """Returns a fully-qualified conversion_value_rule string.""" + return "customers/{customer_id}/conversionValueRules/{conversion_value_rule_id}".format( + customer_id=customer_id, + conversion_value_rule_id=conversion_value_rule_id, + ) + + @staticmethod + def parse_conversion_value_rule_path(path: str) -> Dict[str, str]: + """Parses a conversion_value_rule path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionValueRules/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_value_rule_set_path( + customer_id: str, + conversion_value_rule_set_id: str, + ) -> str: + """Returns a fully-qualified conversion_value_rule_set string.""" + return "customers/{customer_id}/conversionValueRuleSets/{conversion_value_rule_set_id}".format( + customer_id=customer_id, + conversion_value_rule_set_id=conversion_value_rule_set_id, + ) + + @staticmethod + def parse_conversion_value_rule_set_path(path: str) -> Dict[str, str]: + """Parses a conversion_value_rule_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionValueRuleSets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?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 = ( + ConversionValueRuleSetServiceClient._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 = ( + ConversionValueRuleSetServiceClient._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 + ): + """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 = ( + ConversionValueRuleSetServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + ConversionValueRuleSetServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = ConversionValueRuleSetServiceClient._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 = ConversionValueRuleSetServiceClient._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): + """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, + ConversionValueRuleSetServiceTransport, + Callable[..., ConversionValueRuleSetServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the conversion value rule set 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,ConversionValueRuleSetServiceTransport,Callable[..., ConversionValueRuleSetServiceTransport]]]): + 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 ConversionValueRuleSetServiceTransport 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, + ) = ConversionValueRuleSetServiceClient._read_environment_variables() + self._client_cert_source = ( + ConversionValueRuleSetServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + ConversionValueRuleSetServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ConversionValueRuleSetServiceTransport + ) + if transport_provided: + # transport is a ConversionValueRuleSetServiceTransport 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( + ConversionValueRuleSetServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ConversionValueRuleSetServiceClient._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[ConversionValueRuleSetServiceTransport], + Callable[..., ConversionValueRuleSetServiceTransport], + ] = ( + ConversionValueRuleSetServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., ConversionValueRuleSetServiceTransport], + 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.ads.googleads.v24.services.ConversionValueRuleSetServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ConversionValueRuleSetService", + "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.ads.googleads.v24.services.ConversionValueRuleSetService", + "credentialsType": None, + } + ), + ) + + def mutate_conversion_value_rule_sets( + self, + request: Optional[ + Union[ + conversion_value_rule_set_service.MutateConversionValueRuleSetsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + conversion_value_rule_set_service.ConversionValueRuleSetOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + conversion_value_rule_set_service.MutateConversionValueRuleSetsResponse + ): + r"""Creates, updates or removes conversion value rule + sets. Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateConversionValueRuleSetsRequest, dict]): + The request object. Request message for + [ConversionValueRuleSetService.MutateConversionValueRuleSets][google.ads.googleads.v24.services.ConversionValueRuleSetService.MutateConversionValueRuleSets]. + customer_id (str): + Required. The ID of the customer + whose conversion value rule sets are + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.ConversionValueRuleSetOperation]): + Required. The list of operations to + perform on individual conversion value + rule sets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateConversionValueRuleSetsResponse: + Response message for + [ConversionValueRuleSetService.MutateConversionValueRuleSets][google.ads.googleads.v24.services.ConversionValueRuleSetService.MutateConversionValueRuleSets]. + + """ + # 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 = [customer_id, operations] + 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, + conversion_value_rule_set_service.MutateConversionValueRuleSetsRequest, + ): + request = conversion_value_rule_set_service.MutateConversionValueRuleSetsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_conversion_value_rule_sets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "ConversionValueRuleSetServiceClient": + 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() + + +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__ = ("ConversionValueRuleSetServiceClient",) diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/README.rst b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/README.rst new file mode 100644 index 000000000..977400874 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ConversionValueRuleSetServiceTransport` is the ABC for all transports. +- public child `ConversionValueRuleSetServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ConversionValueRuleSetServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseConversionValueRuleSetServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ConversionValueRuleSetServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/__init__.py b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/__init__.py new file mode 100644 index 000000000..2e7885ec4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ConversionValueRuleSetServiceTransport +from .grpc import ConversionValueRuleSetServiceGrpcTransport +from .grpc_asyncio import ConversionValueRuleSetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ConversionValueRuleSetServiceTransport]] +_transport_registry["grpc"] = ConversionValueRuleSetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + ConversionValueRuleSetServiceGrpcAsyncIOTransport +) + +__all__ = ( + "ConversionValueRuleSetServiceTransport", + "ConversionValueRuleSetServiceGrpcTransport", + "ConversionValueRuleSetServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/base.py b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/base.py new file mode 100644 index 000000000..e2ed11211 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + conversion_value_rule_set_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 ConversionValueRuleSetServiceTransport(abc.ABC): + """Abstract transport class for ConversionValueRuleSetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_conversion_value_rule_sets: gapic_v1.method.wrap_method( + self.mutate_conversion_value_rule_sets, + 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 mutate_conversion_value_rule_sets( + self, + ) -> Callable[ + [ + conversion_value_rule_set_service.MutateConversionValueRuleSetsRequest + ], + Union[ + conversion_value_rule_set_service.MutateConversionValueRuleSetsResponse, + Awaitable[ + conversion_value_rule_set_service.MutateConversionValueRuleSetsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ConversionValueRuleSetServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/grpc.py b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/grpc.py new file mode 100644 index 000000000..721988b8f --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/grpc.py @@ -0,0 +1,391 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + conversion_value_rule_set_service, +) +from .base import ConversionValueRuleSetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ConversionValueRuleSetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ConversionValueRuleSetService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ConversionValueRuleSetServiceGrpcTransport( + ConversionValueRuleSetServiceTransport +): + """gRPC backend transport for ConversionValueRuleSetService. + + Service to manage conversion value rule sets. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_conversion_value_rule_sets( + self, + ) -> Callable[ + [ + conversion_value_rule_set_service.MutateConversionValueRuleSetsRequest + ], + conversion_value_rule_set_service.MutateConversionValueRuleSetsResponse, + ]: + r"""Return a callable for the mutate conversion value rule + sets method over gRPC. + + Creates, updates or removes conversion value rule + sets. Operation statuses are returned. + + Returns: + Callable[[~.MutateConversionValueRuleSetsRequest], + ~.MutateConversionValueRuleSetsResponse]: + 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 "mutate_conversion_value_rule_sets" not in self._stubs: + self._stubs["mutate_conversion_value_rule_sets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionValueRuleSetService/MutateConversionValueRuleSets", + request_serializer=conversion_value_rule_set_service.MutateConversionValueRuleSetsRequest.serialize, + response_deserializer=conversion_value_rule_set_service.MutateConversionValueRuleSetsResponse.deserialize, + ) + ) + return self._stubs["mutate_conversion_value_rule_sets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ConversionValueRuleSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..8168b2954 --- /dev/null +++ b/google/ads/googleads/v24/services/services/conversion_value_rule_set_service/transports/grpc_asyncio.py @@ -0,0 +1,414 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + conversion_value_rule_set_service, +) +from .base import ConversionValueRuleSetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ConversionValueRuleSetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ConversionValueRuleSetService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ConversionValueRuleSetServiceGrpcAsyncIOTransport( + ConversionValueRuleSetServiceTransport +): + """gRPC AsyncIO backend transport for ConversionValueRuleSetService. + + Service to manage conversion value rule sets. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_conversion_value_rule_sets( + self, + ) -> Callable[ + [ + conversion_value_rule_set_service.MutateConversionValueRuleSetsRequest + ], + Awaitable[ + conversion_value_rule_set_service.MutateConversionValueRuleSetsResponse + ], + ]: + r"""Return a callable for the mutate conversion value rule + sets method over gRPC. + + Creates, updates or removes conversion value rule + sets. Operation statuses are returned. + + Returns: + Callable[[~.MutateConversionValueRuleSetsRequest], + Awaitable[~.MutateConversionValueRuleSetsResponse]]: + 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 "mutate_conversion_value_rule_sets" not in self._stubs: + self._stubs["mutate_conversion_value_rule_sets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ConversionValueRuleSetService/MutateConversionValueRuleSets", + request_serializer=conversion_value_rule_set_service.MutateConversionValueRuleSetsRequest.serialize, + response_deserializer=conversion_value_rule_set_service.MutateConversionValueRuleSetsResponse.deserialize, + ) + ) + return self._stubs["mutate_conversion_value_rule_sets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_conversion_value_rule_sets: self._wrap_method( + self.mutate_conversion_value_rule_sets, + 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" + + +__all__ = ("ConversionValueRuleSetServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/custom_audience_service/__init__.py b/google/ads/googleads/v24/services/services/custom_audience_service/__init__.py new file mode 100644 index 000000000..c1a8a24c2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_audience_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomAudienceServiceClient +from .async_client import CustomAudienceServiceAsyncClient + +__all__ = ( + "CustomAudienceServiceClient", + "CustomAudienceServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/custom_audience_service/async_client.py b/google/ads/googleads/v24/services/services/custom_audience_service/async_client.py new file mode 100644 index 000000000..b03ace8d6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_audience_service/async_client.py @@ -0,0 +1,428 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import custom_audience_service +from .transports.base import CustomAudienceServiceTransport, DEFAULT_CLIENT_INFO +from .client import CustomAudienceServiceClient + +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 CustomAudienceServiceAsyncClient: + """Service to manage custom audiences.""" + + _client: CustomAudienceServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomAudienceServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CustomAudienceServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomAudienceServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomAudienceServiceClient._DEFAULT_UNIVERSE + + custom_audience_path = staticmethod( + CustomAudienceServiceClient.custom_audience_path + ) + parse_custom_audience_path = staticmethod( + CustomAudienceServiceClient.parse_custom_audience_path + ) + common_billing_account_path = staticmethod( + CustomAudienceServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomAudienceServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomAudienceServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomAudienceServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomAudienceServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomAudienceServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomAudienceServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomAudienceServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomAudienceServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomAudienceServiceClient.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: + CustomAudienceServiceAsyncClient: The constructed client. + """ + return CustomAudienceServiceClient.from_service_account_info.__func__(CustomAudienceServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomAudienceServiceAsyncClient: The constructed client. + """ + return CustomAudienceServiceClient.from_service_account_file.__func__(CustomAudienceServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomAudienceServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomAudienceServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomAudienceServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CustomAudienceServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomAudienceServiceTransport, + Callable[..., CustomAudienceServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the custom audience 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,CustomAudienceServiceTransport,Callable[..., CustomAudienceServiceTransport]]]): + 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 CustomAudienceServiceTransport 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 = CustomAudienceServiceClient( + 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.ads.googleads.v24.services.CustomAudienceServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomAudienceService", + "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.ads.googleads.v24.services.CustomAudienceService", + "credentialsType": None, + } + ), + ) + + async def mutate_custom_audiences( + self, + request: Optional[ + Union[custom_audience_service.MutateCustomAudiencesRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[custom_audience_service.CustomAudienceOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> custom_audience_service.MutateCustomAudiencesResponse: + r"""Creates or updates custom audiences. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CustomAudienceError <>`__ + `CustomInterestError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `OperationAccessDeniedError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomAudiencesRequest, dict]]): + The request object. Request message for + [CustomAudienceService.MutateCustomAudiences][google.ads.googleads.v24.services.CustomAudienceService.MutateCustomAudiences]. + customer_id (:class:`str`): + Required. The ID of the customer + whose custom audiences are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CustomAudienceOperation]`): + Required. The list of operations to + perform on individual custom audiences. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomAudiencesResponse: + Response message for custom audience + mutate. + + """ + # 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 = [customer_id, operations] + 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, custom_audience_service.MutateCustomAudiencesRequest + ): + request = custom_audience_service.MutateCustomAudiencesRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_custom_audiences + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomAudienceServiceAsyncClient": + 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__ = ("CustomAudienceServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/custom_audience_service/client.py b/google/ads/googleads/v24/services/services/custom_audience_service/client.py new file mode 100644 index 000000000..57533348e --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_audience_service/client.py @@ -0,0 +1,904 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import custom_audience_service +from .transports.base import CustomAudienceServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CustomAudienceServiceGrpcTransport +from .transports.grpc_asyncio import CustomAudienceServiceGrpcAsyncIOTransport + + +class CustomAudienceServiceClientMeta(type): + """Metaclass for the CustomAudienceService 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[CustomAudienceServiceTransport]] + _transport_registry["grpc"] = CustomAudienceServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CustomAudienceServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomAudienceServiceTransport]: + """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 CustomAudienceServiceClient(metaclass=CustomAudienceServiceClientMeta): + """Service to manage custom audiences.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomAudienceServiceClient: 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: + CustomAudienceServiceClient: 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) -> CustomAudienceServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomAudienceServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def custom_audience_path( + customer_id: str, + custom_audience_id: str, + ) -> str: + """Returns a fully-qualified custom_audience string.""" + return "customers/{customer_id}/customAudiences/{custom_audience_id}".format( + customer_id=customer_id, + custom_audience_id=custom_audience_id, + ) + + @staticmethod + def parse_custom_audience_path(path: str) -> Dict[str, str]: + """Parses a custom_audience path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customAudiences/(?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 = ( + CustomAudienceServiceClient._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 = ( + CustomAudienceServiceClient._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 + ): + """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 = CustomAudienceServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CustomAudienceServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + CustomAudienceServiceClient._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 = CustomAudienceServiceClient._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): + """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, + CustomAudienceServiceTransport, + Callable[..., CustomAudienceServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the custom audience 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,CustomAudienceServiceTransport,Callable[..., CustomAudienceServiceTransport]]]): + 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 CustomAudienceServiceTransport 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, + ) = CustomAudienceServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomAudienceServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CustomAudienceServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomAudienceServiceTransport + ) + if transport_provided: + # transport is a CustomAudienceServiceTransport 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(CustomAudienceServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomAudienceServiceClient._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[CustomAudienceServiceTransport], + Callable[..., CustomAudienceServiceTransport], + ] = ( + CustomAudienceServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomAudienceServiceTransport], 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.ads.googleads.v24.services.CustomAudienceServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomAudienceService", + "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.ads.googleads.v24.services.CustomAudienceService", + "credentialsType": None, + } + ), + ) + + def mutate_custom_audiences( + self, + request: Optional[ + Union[custom_audience_service.MutateCustomAudiencesRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[custom_audience_service.CustomAudienceOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> custom_audience_service.MutateCustomAudiencesResponse: + r"""Creates or updates custom audiences. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CustomAudienceError <>`__ + `CustomInterestError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `OperationAccessDeniedError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomAudiencesRequest, dict]): + The request object. Request message for + [CustomAudienceService.MutateCustomAudiences][google.ads.googleads.v24.services.CustomAudienceService.MutateCustomAudiences]. + customer_id (str): + Required. The ID of the customer + whose custom audiences are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomAudienceOperation]): + Required. The list of operations to + perform on individual custom audiences. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomAudiencesResponse: + Response message for custom audience + mutate. + + """ + # 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 = [customer_id, operations] + 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, custom_audience_service.MutateCustomAudiencesRequest + ): + request = custom_audience_service.MutateCustomAudiencesRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_custom_audiences + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomAudienceServiceClient": + 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() + + +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__ = ("CustomAudienceServiceClient",) diff --git a/google/ads/googleads/v24/services/services/custom_audience_service/transports/README.rst b/google/ads/googleads/v24/services/services/custom_audience_service/transports/README.rst new file mode 100644 index 000000000..7ad486360 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_audience_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomAudienceServiceTransport` is the ABC for all transports. +- public child `CustomAudienceServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomAudienceServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomAudienceServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomAudienceServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/custom_audience_service/transports/__init__.py b/google/ads/googleads/v24/services/services/custom_audience_service/transports/__init__.py new file mode 100644 index 000000000..4cdb3c259 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_audience_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomAudienceServiceTransport +from .grpc import CustomAudienceServiceGrpcTransport +from .grpc_asyncio import CustomAudienceServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomAudienceServiceTransport]] +_transport_registry["grpc"] = CustomAudienceServiceGrpcTransport +_transport_registry["grpc_asyncio"] = CustomAudienceServiceGrpcAsyncIOTransport + +__all__ = ( + "CustomAudienceServiceTransport", + "CustomAudienceServiceGrpcTransport", + "CustomAudienceServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/custom_audience_service/transports/base.py b/google/ads/googleads/v24/services/services/custom_audience_service/transports/base.py new file mode 100644 index 000000000..6c8f674e2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_audience_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import custom_audience_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 CustomAudienceServiceTransport(abc.ABC): + """Abstract transport class for CustomAudienceService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_custom_audiences: gapic_v1.method.wrap_method( + self.mutate_custom_audiences, + 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 mutate_custom_audiences( + self, + ) -> Callable[ + [custom_audience_service.MutateCustomAudiencesRequest], + Union[ + custom_audience_service.MutateCustomAudiencesResponse, + Awaitable[custom_audience_service.MutateCustomAudiencesResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomAudienceServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/custom_audience_service/transports/grpc.py b/google/ads/googleads/v24/services/services/custom_audience_service/transports/grpc.py new file mode 100644 index 000000000..6a34e0056 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_audience_service/transports/grpc.py @@ -0,0 +1,392 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import custom_audience_service +from .base import CustomAudienceServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomAudienceService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomAudienceService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomAudienceServiceGrpcTransport(CustomAudienceServiceTransport): + """gRPC backend transport for CustomAudienceService. + + Service to manage custom audiences. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_custom_audiences( + self, + ) -> Callable[ + [custom_audience_service.MutateCustomAudiencesRequest], + custom_audience_service.MutateCustomAudiencesResponse, + ]: + r"""Return a callable for the mutate custom audiences method over gRPC. + + Creates or updates custom audiences. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CustomAudienceError <>`__ + `CustomInterestError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `OperationAccessDeniedError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomAudiencesRequest], + ~.MutateCustomAudiencesResponse]: + 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 "mutate_custom_audiences" not in self._stubs: + self._stubs["mutate_custom_audiences"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomAudienceService/MutateCustomAudiences", + request_serializer=custom_audience_service.MutateCustomAudiencesRequest.serialize, + response_deserializer=custom_audience_service.MutateCustomAudiencesResponse.deserialize, + ) + ) + return self._stubs["mutate_custom_audiences"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomAudienceServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/custom_audience_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/custom_audience_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..f2af8c862 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_audience_service/transports/grpc_asyncio.py @@ -0,0 +1,413 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import custom_audience_service +from .base import CustomAudienceServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomAudienceService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomAudienceService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomAudienceServiceGrpcAsyncIOTransport(CustomAudienceServiceTransport): + """gRPC AsyncIO backend transport for CustomAudienceService. + + Service to manage custom audiences. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_custom_audiences( + self, + ) -> Callable[ + [custom_audience_service.MutateCustomAudiencesRequest], + Awaitable[custom_audience_service.MutateCustomAudiencesResponse], + ]: + r"""Return a callable for the mutate custom audiences method over gRPC. + + Creates or updates custom audiences. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CustomAudienceError <>`__ + `CustomInterestError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `OperationAccessDeniedError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomAudiencesRequest], + Awaitable[~.MutateCustomAudiencesResponse]]: + 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 "mutate_custom_audiences" not in self._stubs: + self._stubs["mutate_custom_audiences"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomAudienceService/MutateCustomAudiences", + request_serializer=custom_audience_service.MutateCustomAudiencesRequest.serialize, + response_deserializer=custom_audience_service.MutateCustomAudiencesResponse.deserialize, + ) + ) + return self._stubs["mutate_custom_audiences"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_custom_audiences: self._wrap_method( + self.mutate_custom_audiences, + 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" + + +__all__ = ("CustomAudienceServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/custom_conversion_goal_service/__init__.py b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/__init__.py new file mode 100644 index 000000000..4250c0cd2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomConversionGoalServiceClient +from .async_client import CustomConversionGoalServiceAsyncClient + +__all__ = ( + "CustomConversionGoalServiceClient", + "CustomConversionGoalServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/custom_conversion_goal_service/async_client.py b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/async_client.py new file mode 100644 index 000000000..805f23aec --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/async_client.py @@ -0,0 +1,440 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + custom_conversion_goal_service, +) +from .transports.base import ( + CustomConversionGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CustomConversionGoalServiceClient + +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 CustomConversionGoalServiceAsyncClient: + """Service to manage custom conversion goal.""" + + _client: CustomConversionGoalServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomConversionGoalServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + CustomConversionGoalServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomConversionGoalServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomConversionGoalServiceClient._DEFAULT_UNIVERSE + + conversion_action_path = staticmethod( + CustomConversionGoalServiceClient.conversion_action_path + ) + parse_conversion_action_path = staticmethod( + CustomConversionGoalServiceClient.parse_conversion_action_path + ) + custom_conversion_goal_path = staticmethod( + CustomConversionGoalServiceClient.custom_conversion_goal_path + ) + parse_custom_conversion_goal_path = staticmethod( + CustomConversionGoalServiceClient.parse_custom_conversion_goal_path + ) + common_billing_account_path = staticmethod( + CustomConversionGoalServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomConversionGoalServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomConversionGoalServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomConversionGoalServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomConversionGoalServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomConversionGoalServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomConversionGoalServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomConversionGoalServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomConversionGoalServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomConversionGoalServiceClient.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: + CustomConversionGoalServiceAsyncClient: The constructed client. + """ + return CustomConversionGoalServiceClient.from_service_account_info.__func__(CustomConversionGoalServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomConversionGoalServiceAsyncClient: The constructed client. + """ + return CustomConversionGoalServiceClient.from_service_account_file.__func__(CustomConversionGoalServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomConversionGoalServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomConversionGoalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomConversionGoalServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CustomConversionGoalServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomConversionGoalServiceTransport, + Callable[..., CustomConversionGoalServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the custom conversion goal 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,CustomConversionGoalServiceTransport,Callable[..., CustomConversionGoalServiceTransport]]]): + 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 CustomConversionGoalServiceTransport 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 = CustomConversionGoalServiceClient( + 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.ads.googleads.v24.services.CustomConversionGoalServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomConversionGoalService", + "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.ads.googleads.v24.services.CustomConversionGoalService", + "credentialsType": None, + } + ), + ) + + async def mutate_custom_conversion_goals( + self, + request: Optional[ + Union[ + custom_conversion_goal_service.MutateCustomConversionGoalsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + custom_conversion_goal_service.CustomConversionGoalOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> custom_conversion_goal_service.MutateCustomConversionGoalsResponse: + r"""Creates, updates or removes custom conversion goals. + Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomConversionGoalsRequest, dict]]): + The request object. Request message for + [CustomConversionGoalService.MutateCustomConversionGoals][google.ads.googleads.v24.services.CustomConversionGoalService.MutateCustomConversionGoals]. + customer_id (:class:`str`): + Required. The ID of the customer + whose custom conversion goals are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CustomConversionGoalOperation]`): + Required. The list of operations to + perform on individual custom conversion + goal. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomConversionGoalsResponse: + Response message for a custom + conversion goal mutate. + + """ + # 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 = [customer_id, operations] + 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, + custom_conversion_goal_service.MutateCustomConversionGoalsRequest, + ): + request = custom_conversion_goal_service.MutateCustomConversionGoalsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_custom_conversion_goals + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomConversionGoalServiceAsyncClient": + 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__ = ("CustomConversionGoalServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/custom_conversion_goal_service/client.py b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/client.py new file mode 100644 index 000000000..9267e08e7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/client.py @@ -0,0 +1,937 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + custom_conversion_goal_service, +) +from .transports.base import ( + CustomConversionGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomConversionGoalServiceGrpcTransport +from .transports.grpc_asyncio import ( + CustomConversionGoalServiceGrpcAsyncIOTransport, +) + + +class CustomConversionGoalServiceClientMeta(type): + """Metaclass for the CustomConversionGoalService 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[CustomConversionGoalServiceTransport]] + _transport_registry["grpc"] = CustomConversionGoalServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CustomConversionGoalServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomConversionGoalServiceTransport]: + """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 CustomConversionGoalServiceClient( + metaclass=CustomConversionGoalServiceClientMeta +): + """Service to manage custom conversion goal.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomConversionGoalServiceClient: 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: + CustomConversionGoalServiceClient: 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) -> CustomConversionGoalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomConversionGoalServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def conversion_action_path( + customer_id: str, + conversion_action_id: str, + ) -> str: + """Returns a fully-qualified conversion_action string.""" + return "customers/{customer_id}/conversionActions/{conversion_action_id}".format( + customer_id=customer_id, + conversion_action_id=conversion_action_id, + ) + + @staticmethod + def parse_conversion_action_path(path: str) -> Dict[str, str]: + """Parses a conversion_action path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionActions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def custom_conversion_goal_path( + customer_id: str, + goal_id: str, + ) -> str: + """Returns a fully-qualified custom_conversion_goal string.""" + return "customers/{customer_id}/customConversionGoals/{goal_id}".format( + customer_id=customer_id, + goal_id=goal_id, + ) + + @staticmethod + def parse_custom_conversion_goal_path(path: str) -> Dict[str, str]: + """Parses a custom_conversion_goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customConversionGoals/(?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 = ( + CustomConversionGoalServiceClient._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 = ( + CustomConversionGoalServiceClient._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 + ): + """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 = ( + CustomConversionGoalServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + CustomConversionGoalServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = CustomConversionGoalServiceClient._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 = CustomConversionGoalServiceClient._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): + """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, + CustomConversionGoalServiceTransport, + Callable[..., CustomConversionGoalServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the custom conversion goal 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,CustomConversionGoalServiceTransport,Callable[..., CustomConversionGoalServiceTransport]]]): + 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 CustomConversionGoalServiceTransport 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, + ) = CustomConversionGoalServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomConversionGoalServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CustomConversionGoalServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomConversionGoalServiceTransport + ) + if transport_provided: + # transport is a CustomConversionGoalServiceTransport 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( + CustomConversionGoalServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomConversionGoalServiceClient._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[CustomConversionGoalServiceTransport], + Callable[..., CustomConversionGoalServiceTransport], + ] = ( + CustomConversionGoalServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomConversionGoalServiceTransport], + 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.ads.googleads.v24.services.CustomConversionGoalServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomConversionGoalService", + "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.ads.googleads.v24.services.CustomConversionGoalService", + "credentialsType": None, + } + ), + ) + + def mutate_custom_conversion_goals( + self, + request: Optional[ + Union[ + custom_conversion_goal_service.MutateCustomConversionGoalsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + custom_conversion_goal_service.CustomConversionGoalOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> custom_conversion_goal_service.MutateCustomConversionGoalsResponse: + r"""Creates, updates or removes custom conversion goals. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomConversionGoalsRequest, dict]): + The request object. Request message for + [CustomConversionGoalService.MutateCustomConversionGoals][google.ads.googleads.v24.services.CustomConversionGoalService.MutateCustomConversionGoals]. + customer_id (str): + Required. The ID of the customer + whose custom conversion goals are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomConversionGoalOperation]): + Required. The list of operations to + perform on individual custom conversion + goal. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomConversionGoalsResponse: + Response message for a custom + conversion goal mutate. + + """ + # 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 = [customer_id, operations] + 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, + custom_conversion_goal_service.MutateCustomConversionGoalsRequest, + ): + request = custom_conversion_goal_service.MutateCustomConversionGoalsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_custom_conversion_goals + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomConversionGoalServiceClient": + 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() + + +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__ = ("CustomConversionGoalServiceClient",) diff --git a/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/README.rst b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/README.rst new file mode 100644 index 000000000..e1acacf90 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomConversionGoalServiceTransport` is the ABC for all transports. +- public child `CustomConversionGoalServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomConversionGoalServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomConversionGoalServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomConversionGoalServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/__init__.py b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/__init__.py new file mode 100644 index 000000000..c1ada6df8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomConversionGoalServiceTransport +from .grpc import CustomConversionGoalServiceGrpcTransport +from .grpc_asyncio import CustomConversionGoalServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomConversionGoalServiceTransport]] +_transport_registry["grpc"] = CustomConversionGoalServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CustomConversionGoalServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CustomConversionGoalServiceTransport", + "CustomConversionGoalServiceGrpcTransport", + "CustomConversionGoalServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/base.py b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/base.py new file mode 100644 index 000000000..8437f7c58 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + custom_conversion_goal_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 CustomConversionGoalServiceTransport(abc.ABC): + """Abstract transport class for CustomConversionGoalService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_custom_conversion_goals: gapic_v1.method.wrap_method( + self.mutate_custom_conversion_goals, + 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 mutate_custom_conversion_goals( + self, + ) -> Callable[ + [custom_conversion_goal_service.MutateCustomConversionGoalsRequest], + Union[ + custom_conversion_goal_service.MutateCustomConversionGoalsResponse, + Awaitable[ + custom_conversion_goal_service.MutateCustomConversionGoalsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomConversionGoalServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/grpc.py b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/grpc.py new file mode 100644 index 000000000..a351c5e97 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/grpc.py @@ -0,0 +1,388 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + custom_conversion_goal_service, +) +from .base import CustomConversionGoalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomConversionGoalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomConversionGoalService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomConversionGoalServiceGrpcTransport( + CustomConversionGoalServiceTransport +): + """gRPC backend transport for CustomConversionGoalService. + + Service to manage custom conversion goal. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_custom_conversion_goals( + self, + ) -> Callable[ + [custom_conversion_goal_service.MutateCustomConversionGoalsRequest], + custom_conversion_goal_service.MutateCustomConversionGoalsResponse, + ]: + r"""Return a callable for the mutate custom conversion goals method over gRPC. + + Creates, updates or removes custom conversion goals. + Operation statuses are returned. + + Returns: + Callable[[~.MutateCustomConversionGoalsRequest], + ~.MutateCustomConversionGoalsResponse]: + 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 "mutate_custom_conversion_goals" not in self._stubs: + self._stubs["mutate_custom_conversion_goals"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomConversionGoalService/MutateCustomConversionGoals", + request_serializer=custom_conversion_goal_service.MutateCustomConversionGoalsRequest.serialize, + response_deserializer=custom_conversion_goal_service.MutateCustomConversionGoalsResponse.deserialize, + ) + ) + return self._stubs["mutate_custom_conversion_goals"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomConversionGoalServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..f754c3bd6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_conversion_goal_service/transports/grpc_asyncio.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + custom_conversion_goal_service, +) +from .base import CustomConversionGoalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomConversionGoalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomConversionGoalService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomConversionGoalServiceGrpcAsyncIOTransport( + CustomConversionGoalServiceTransport +): + """gRPC AsyncIO backend transport for CustomConversionGoalService. + + Service to manage custom conversion goal. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_custom_conversion_goals( + self, + ) -> Callable[ + [custom_conversion_goal_service.MutateCustomConversionGoalsRequest], + Awaitable[ + custom_conversion_goal_service.MutateCustomConversionGoalsResponse + ], + ]: + r"""Return a callable for the mutate custom conversion goals method over gRPC. + + Creates, updates or removes custom conversion goals. + Operation statuses are returned. + + Returns: + Callable[[~.MutateCustomConversionGoalsRequest], + Awaitable[~.MutateCustomConversionGoalsResponse]]: + 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 "mutate_custom_conversion_goals" not in self._stubs: + self._stubs["mutate_custom_conversion_goals"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomConversionGoalService/MutateCustomConversionGoals", + request_serializer=custom_conversion_goal_service.MutateCustomConversionGoalsRequest.serialize, + response_deserializer=custom_conversion_goal_service.MutateCustomConversionGoalsResponse.deserialize, + ) + ) + return self._stubs["mutate_custom_conversion_goals"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_custom_conversion_goals: self._wrap_method( + self.mutate_custom_conversion_goals, + 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" + + +__all__ = ("CustomConversionGoalServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/custom_interest_service/__init__.py b/google/ads/googleads/v24/services/services/custom_interest_service/__init__.py new file mode 100644 index 000000000..5d7dba298 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_interest_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomInterestServiceClient +from .async_client import CustomInterestServiceAsyncClient + +__all__ = ( + "CustomInterestServiceClient", + "CustomInterestServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/custom_interest_service/async_client.py b/google/ads/googleads/v24/services/services/custom_interest_service/async_client.py new file mode 100644 index 000000000..d145e6b41 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_interest_service/async_client.py @@ -0,0 +1,427 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import custom_interest_service +from .transports.base import CustomInterestServiceTransport, DEFAULT_CLIENT_INFO +from .client import CustomInterestServiceClient + +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 CustomInterestServiceAsyncClient: + """Service to manage custom interests.""" + + _client: CustomInterestServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomInterestServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CustomInterestServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomInterestServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomInterestServiceClient._DEFAULT_UNIVERSE + + custom_interest_path = staticmethod( + CustomInterestServiceClient.custom_interest_path + ) + parse_custom_interest_path = staticmethod( + CustomInterestServiceClient.parse_custom_interest_path + ) + common_billing_account_path = staticmethod( + CustomInterestServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomInterestServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomInterestServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomInterestServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomInterestServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomInterestServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomInterestServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomInterestServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomInterestServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomInterestServiceClient.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: + CustomInterestServiceAsyncClient: The constructed client. + """ + return CustomInterestServiceClient.from_service_account_info.__func__(CustomInterestServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomInterestServiceAsyncClient: The constructed client. + """ + return CustomInterestServiceClient.from_service_account_file.__func__(CustomInterestServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomInterestServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomInterestServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomInterestServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CustomInterestServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomInterestServiceTransport, + Callable[..., CustomInterestServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the custom interest 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,CustomInterestServiceTransport,Callable[..., CustomInterestServiceTransport]]]): + 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 CustomInterestServiceTransport 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 = CustomInterestServiceClient( + 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.ads.googleads.v24.services.CustomInterestServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomInterestService", + "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.ads.googleads.v24.services.CustomInterestService", + "credentialsType": None, + } + ), + ) + + async def mutate_custom_interests( + self, + request: Optional[ + Union[custom_interest_service.MutateCustomInterestsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[custom_interest_service.CustomInterestOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> custom_interest_service.MutateCustomInterestsResponse: + r"""Creates or updates custom interests. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CriterionError <>`__ + `CustomInterestError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ + `RequestError <>`__ `StringLengthError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomInterestsRequest, dict]]): + The request object. Request message for + [CustomInterestService.MutateCustomInterests][google.ads.googleads.v24.services.CustomInterestService.MutateCustomInterests]. + customer_id (:class:`str`): + Required. The ID of the customer + whose custom interests are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CustomInterestOperation]`): + Required. The list of operations to + perform on individual custom interests. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomInterestsResponse: + Response message for custom interest + mutate. + + """ + # 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 = [customer_id, operations] + 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, custom_interest_service.MutateCustomInterestsRequest + ): + request = custom_interest_service.MutateCustomInterestsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_custom_interests + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomInterestServiceAsyncClient": + 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__ = ("CustomInterestServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/custom_interest_service/client.py b/google/ads/googleads/v24/services/services/custom_interest_service/client.py new file mode 100644 index 000000000..8d7455f57 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_interest_service/client.py @@ -0,0 +1,903 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import custom_interest_service +from .transports.base import CustomInterestServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CustomInterestServiceGrpcTransport +from .transports.grpc_asyncio import CustomInterestServiceGrpcAsyncIOTransport + + +class CustomInterestServiceClientMeta(type): + """Metaclass for the CustomInterestService 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[CustomInterestServiceTransport]] + _transport_registry["grpc"] = CustomInterestServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CustomInterestServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomInterestServiceTransport]: + """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 CustomInterestServiceClient(metaclass=CustomInterestServiceClientMeta): + """Service to manage custom interests.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomInterestServiceClient: 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: + CustomInterestServiceClient: 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) -> CustomInterestServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomInterestServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def custom_interest_path( + customer_id: str, + custom_interest_id: str, + ) -> str: + """Returns a fully-qualified custom_interest string.""" + return "customers/{customer_id}/customInterests/{custom_interest_id}".format( + customer_id=customer_id, + custom_interest_id=custom_interest_id, + ) + + @staticmethod + def parse_custom_interest_path(path: str) -> Dict[str, str]: + """Parses a custom_interest path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customInterests/(?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 = ( + CustomInterestServiceClient._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 = ( + CustomInterestServiceClient._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 + ): + """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 = CustomInterestServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CustomInterestServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + CustomInterestServiceClient._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 = CustomInterestServiceClient._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): + """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, + CustomInterestServiceTransport, + Callable[..., CustomInterestServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the custom interest 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,CustomInterestServiceTransport,Callable[..., CustomInterestServiceTransport]]]): + 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 CustomInterestServiceTransport 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, + ) = CustomInterestServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomInterestServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CustomInterestServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomInterestServiceTransport + ) + if transport_provided: + # transport is a CustomInterestServiceTransport 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(CustomInterestServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomInterestServiceClient._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[CustomInterestServiceTransport], + Callable[..., CustomInterestServiceTransport], + ] = ( + CustomInterestServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomInterestServiceTransport], 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.ads.googleads.v24.services.CustomInterestServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomInterestService", + "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.ads.googleads.v24.services.CustomInterestService", + "credentialsType": None, + } + ), + ) + + def mutate_custom_interests( + self, + request: Optional[ + Union[custom_interest_service.MutateCustomInterestsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[custom_interest_service.CustomInterestOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> custom_interest_service.MutateCustomInterestsResponse: + r"""Creates or updates custom interests. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CriterionError <>`__ + `CustomInterestError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ + `RequestError <>`__ `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomInterestsRequest, dict]): + The request object. Request message for + [CustomInterestService.MutateCustomInterests][google.ads.googleads.v24.services.CustomInterestService.MutateCustomInterests]. + customer_id (str): + Required. The ID of the customer + whose custom interests are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomInterestOperation]): + Required. The list of operations to + perform on individual custom interests. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomInterestsResponse: + Response message for custom interest + mutate. + + """ + # 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 = [customer_id, operations] + 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, custom_interest_service.MutateCustomInterestsRequest + ): + request = custom_interest_service.MutateCustomInterestsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_custom_interests + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomInterestServiceClient": + 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() + + +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__ = ("CustomInterestServiceClient",) diff --git a/google/ads/googleads/v24/services/services/custom_interest_service/transports/README.rst b/google/ads/googleads/v24/services/services/custom_interest_service/transports/README.rst new file mode 100644 index 000000000..079cbc36c --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_interest_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomInterestServiceTransport` is the ABC for all transports. +- public child `CustomInterestServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomInterestServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomInterestServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomInterestServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/custom_interest_service/transports/__init__.py b/google/ads/googleads/v24/services/services/custom_interest_service/transports/__init__.py new file mode 100644 index 000000000..19665f8a4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_interest_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomInterestServiceTransport +from .grpc import CustomInterestServiceGrpcTransport +from .grpc_asyncio import CustomInterestServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomInterestServiceTransport]] +_transport_registry["grpc"] = CustomInterestServiceGrpcTransport +_transport_registry["grpc_asyncio"] = CustomInterestServiceGrpcAsyncIOTransport + +__all__ = ( + "CustomInterestServiceTransport", + "CustomInterestServiceGrpcTransport", + "CustomInterestServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/custom_interest_service/transports/base.py b/google/ads/googleads/v24/services/services/custom_interest_service/transports/base.py new file mode 100644 index 000000000..7f1bbf932 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_interest_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import custom_interest_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 CustomInterestServiceTransport(abc.ABC): + """Abstract transport class for CustomInterestService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_custom_interests: gapic_v1.method.wrap_method( + self.mutate_custom_interests, + 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 mutate_custom_interests( + self, + ) -> Callable[ + [custom_interest_service.MutateCustomInterestsRequest], + Union[ + custom_interest_service.MutateCustomInterestsResponse, + Awaitable[custom_interest_service.MutateCustomInterestsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomInterestServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/custom_interest_service/transports/grpc.py b/google/ads/googleads/v24/services/services/custom_interest_service/transports/grpc.py new file mode 100644 index 000000000..c71687c59 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_interest_service/transports/grpc.py @@ -0,0 +1,391 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import custom_interest_service +from .base import CustomInterestServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomInterestService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomInterestService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomInterestServiceGrpcTransport(CustomInterestServiceTransport): + """gRPC backend transport for CustomInterestService. + + Service to manage custom interests. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_custom_interests( + self, + ) -> Callable[ + [custom_interest_service.MutateCustomInterestsRequest], + custom_interest_service.MutateCustomInterestsResponse, + ]: + r"""Return a callable for the mutate custom interests method over gRPC. + + Creates or updates custom interests. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CriterionError <>`__ + `CustomInterestError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ + `RequestError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateCustomInterestsRequest], + ~.MutateCustomInterestsResponse]: + 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 "mutate_custom_interests" not in self._stubs: + self._stubs["mutate_custom_interests"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomInterestService/MutateCustomInterests", + request_serializer=custom_interest_service.MutateCustomInterestsRequest.serialize, + response_deserializer=custom_interest_service.MutateCustomInterestsResponse.deserialize, + ) + ) + return self._stubs["mutate_custom_interests"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomInterestServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/custom_interest_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/custom_interest_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..a54a99cd1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/custom_interest_service/transports/grpc_asyncio.py @@ -0,0 +1,412 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import custom_interest_service +from .base import CustomInterestServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomInterestService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomInterestService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomInterestServiceGrpcAsyncIOTransport(CustomInterestServiceTransport): + """gRPC AsyncIO backend transport for CustomInterestService. + + Service to manage custom interests. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_custom_interests( + self, + ) -> Callable[ + [custom_interest_service.MutateCustomInterestsRequest], + Awaitable[custom_interest_service.MutateCustomInterestsResponse], + ]: + r"""Return a callable for the mutate custom interests method over gRPC. + + Creates or updates custom interests. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CriterionError <>`__ + `CustomInterestError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ + `RequestError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateCustomInterestsRequest], + Awaitable[~.MutateCustomInterestsResponse]]: + 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 "mutate_custom_interests" not in self._stubs: + self._stubs["mutate_custom_interests"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomInterestService/MutateCustomInterests", + request_serializer=custom_interest_service.MutateCustomInterestsRequest.serialize, + response_deserializer=custom_interest_service.MutateCustomInterestsResponse.deserialize, + ) + ) + return self._stubs["mutate_custom_interests"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_custom_interests: self._wrap_method( + self.mutate_custom_interests, + 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" + + +__all__ = ("CustomInterestServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_asset_service/__init__.py b/google/ads/googleads/v24/services/services/customer_asset_service/__init__.py new file mode 100644 index 000000000..85d3225f1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomerAssetServiceClient +from .async_client import CustomerAssetServiceAsyncClient + +__all__ = ( + "CustomerAssetServiceClient", + "CustomerAssetServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/customer_asset_service/async_client.py b/google/ads/googleads/v24/services/services/customer_asset_service/async_client.py new file mode 100644 index 000000000..1f7adcb1d --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_service/async_client.py @@ -0,0 +1,428 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import customer_asset_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CustomerAssetServiceTransport, DEFAULT_CLIENT_INFO +from .client import CustomerAssetServiceClient + +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 CustomerAssetServiceAsyncClient: + """Service to manage customer assets.""" + + _client: CustomerAssetServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomerAssetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CustomerAssetServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomerAssetServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomerAssetServiceClient._DEFAULT_UNIVERSE + + asset_path = staticmethod(CustomerAssetServiceClient.asset_path) + parse_asset_path = staticmethod(CustomerAssetServiceClient.parse_asset_path) + customer_asset_path = staticmethod( + CustomerAssetServiceClient.customer_asset_path + ) + parse_customer_asset_path = staticmethod( + CustomerAssetServiceClient.parse_customer_asset_path + ) + common_billing_account_path = staticmethod( + CustomerAssetServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomerAssetServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomerAssetServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomerAssetServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomerAssetServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomerAssetServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomerAssetServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomerAssetServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomerAssetServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomerAssetServiceClient.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: + CustomerAssetServiceAsyncClient: The constructed client. + """ + return CustomerAssetServiceClient.from_service_account_info.__func__(CustomerAssetServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomerAssetServiceAsyncClient: The constructed client. + """ + return CustomerAssetServiceClient.from_service_account_file.__func__(CustomerAssetServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomerAssetServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomerAssetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerAssetServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CustomerAssetServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomerAssetServiceTransport, + Callable[..., CustomerAssetServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer asset 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,CustomerAssetServiceTransport,Callable[..., CustomerAssetServiceTransport]]]): + 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 CustomerAssetServiceTransport 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 = CustomerAssetServiceClient( + 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.ads.googleads.v24.services.CustomerAssetServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerAssetService", + "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.ads.googleads.v24.services.CustomerAssetService", + "credentialsType": None, + } + ), + ) + + async def mutate_customer_assets( + self, + request: Optional[ + Union[customer_asset_service.MutateCustomerAssetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[customer_asset_service.CustomerAssetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_asset_service.MutateCustomerAssetsResponse: + r"""Creates, updates, or removes customer assets. Operation statuses + are returned. + + List of thrown errors: `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomerAssetsRequest, dict]]): + The request object. Request message for + [CustomerAssetService.MutateCustomerAssets][google.ads.googleads.v24.services.CustomerAssetService.MutateCustomerAssets]. + customer_id (:class:`str`): + Required. The ID of the customer + whose customer assets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CustomerAssetOperation]`): + Required. The list of operations to + perform on individual customer assets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomerAssetsResponse: + Response message for a customer asset + mutate. + + """ + # 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 = [customer_id, operations] + 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, customer_asset_service.MutateCustomerAssetsRequest + ): + request = customer_asset_service.MutateCustomerAssetsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_customer_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomerAssetServiceAsyncClient": + 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__ = ("CustomerAssetServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/customer_asset_service/client.py b/google/ads/googleads/v24/services/services/customer_asset_service/client.py new file mode 100644 index 000000000..921b8f914 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_service/client.py @@ -0,0 +1,921 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import customer_asset_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CustomerAssetServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CustomerAssetServiceGrpcTransport +from .transports.grpc_asyncio import CustomerAssetServiceGrpcAsyncIOTransport + + +class CustomerAssetServiceClientMeta(type): + """Metaclass for the CustomerAssetService 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[CustomerAssetServiceTransport]] + _transport_registry["grpc"] = CustomerAssetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CustomerAssetServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerAssetServiceTransport]: + """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 CustomerAssetServiceClient(metaclass=CustomerAssetServiceClientMeta): + """Service to manage customer assets.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomerAssetServiceClient: 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: + CustomerAssetServiceClient: 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) -> CustomerAssetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerAssetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def asset_path( + customer_id: str, + asset_id: str, + ) -> str: + """Returns a fully-qualified asset string.""" + return "customers/{customer_id}/assets/{asset_id}".format( + customer_id=customer_id, + asset_id=asset_id, + ) + + @staticmethod + def parse_asset_path(path: str) -> Dict[str, str]: + """Parses a asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assets/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_asset_path( + customer_id: str, + asset_id: str, + field_type: str, + ) -> str: + """Returns a fully-qualified customer_asset string.""" + return "customers/{customer_id}/customerAssets/{asset_id}~{field_type}".format( + customer_id=customer_id, + asset_id=asset_id, + field_type=field_type, + ) + + @staticmethod + def parse_customer_asset_path(path: str) -> Dict[str, str]: + """Parses a customer_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerAssets/(?P.+?)~(?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 = ( + CustomerAssetServiceClient._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 = ( + CustomerAssetServiceClient._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 + ): + """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 = CustomerAssetServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CustomerAssetServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + CustomerAssetServiceClient._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 = CustomerAssetServiceClient._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): + """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, + CustomerAssetServiceTransport, + Callable[..., CustomerAssetServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer asset 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,CustomerAssetServiceTransport,Callable[..., CustomerAssetServiceTransport]]]): + 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 CustomerAssetServiceTransport 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, + ) = CustomerAssetServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomerAssetServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = CustomerAssetServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomerAssetServiceTransport + ) + if transport_provided: + # transport is a CustomerAssetServiceTransport 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(CustomerAssetServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomerAssetServiceClient._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[CustomerAssetServiceTransport], + Callable[..., CustomerAssetServiceTransport], + ] = ( + CustomerAssetServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomerAssetServiceTransport], 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.ads.googleads.v24.services.CustomerAssetServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerAssetService", + "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.ads.googleads.v24.services.CustomerAssetService", + "credentialsType": None, + } + ), + ) + + def mutate_customer_assets( + self, + request: Optional[ + Union[customer_asset_service.MutateCustomerAssetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[customer_asset_service.CustomerAssetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_asset_service.MutateCustomerAssetsResponse: + r"""Creates, updates, or removes customer assets. Operation statuses + are returned. + + List of thrown errors: `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomerAssetsRequest, dict]): + The request object. Request message for + [CustomerAssetService.MutateCustomerAssets][google.ads.googleads.v24.services.CustomerAssetService.MutateCustomerAssets]. + customer_id (str): + Required. The ID of the customer + whose customer assets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomerAssetOperation]): + Required. The list of operations to + perform on individual customer assets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomerAssetsResponse: + Response message for a customer asset + mutate. + + """ + # 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 = [customer_id, operations] + 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, customer_asset_service.MutateCustomerAssetsRequest + ): + request = customer_asset_service.MutateCustomerAssetsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_customer_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomerAssetServiceClient": + 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() + + +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__ = ("CustomerAssetServiceClient",) diff --git a/google/ads/googleads/v24/services/services/customer_asset_service/transports/README.rst b/google/ads/googleads/v24/services/services/customer_asset_service/transports/README.rst new file mode 100644 index 000000000..addce769a --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomerAssetServiceTransport` is the ABC for all transports. +- public child `CustomerAssetServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomerAssetServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomerAssetServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomerAssetServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/customer_asset_service/transports/__init__.py b/google/ads/googleads/v24/services/services/customer_asset_service/transports/__init__.py new file mode 100644 index 000000000..b336e5790 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomerAssetServiceTransport +from .grpc import CustomerAssetServiceGrpcTransport +from .grpc_asyncio import CustomerAssetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerAssetServiceTransport]] +_transport_registry["grpc"] = CustomerAssetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = CustomerAssetServiceGrpcAsyncIOTransport + +__all__ = ( + "CustomerAssetServiceTransport", + "CustomerAssetServiceGrpcTransport", + "CustomerAssetServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customer_asset_service/transports/base.py b/google/ads/googleads/v24/services/services/customer_asset_service/transports/base.py new file mode 100644 index 000000000..38b8a183f --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import customer_asset_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 CustomerAssetServiceTransport(abc.ABC): + """Abstract transport class for CustomerAssetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customer_assets: gapic_v1.method.wrap_method( + self.mutate_customer_assets, + 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 mutate_customer_assets( + self, + ) -> Callable[ + [customer_asset_service.MutateCustomerAssetsRequest], + Union[ + customer_asset_service.MutateCustomerAssetsResponse, + Awaitable[customer_asset_service.MutateCustomerAssetsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomerAssetServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_asset_service/transports/grpc.py b/google/ads/googleads/v24/services/services/customer_asset_service/transports/grpc.py new file mode 100644 index 000000000..9c259acae --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_service/transports/grpc.py @@ -0,0 +1,389 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import customer_asset_service +from .base import CustomerAssetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerAssetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerAssetService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerAssetServiceGrpcTransport(CustomerAssetServiceTransport): + """gRPC backend transport for CustomerAssetService. + + Service to manage customer assets. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_customer_assets( + self, + ) -> Callable[ + [customer_asset_service.MutateCustomerAssetsRequest], + customer_asset_service.MutateCustomerAssetsResponse, + ]: + r"""Return a callable for the mutate customer assets method over gRPC. + + Creates, updates, or removes customer assets. Operation statuses + are returned. + + List of thrown errors: `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomerAssetsRequest], + ~.MutateCustomerAssetsResponse]: + 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 "mutate_customer_assets" not in self._stubs: + self._stubs["mutate_customer_assets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerAssetService/MutateCustomerAssets", + request_serializer=customer_asset_service.MutateCustomerAssetsRequest.serialize, + response_deserializer=customer_asset_service.MutateCustomerAssetsResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_assets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomerAssetServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_asset_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/customer_asset_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..e3487c116 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_service/transports/grpc_asyncio.py @@ -0,0 +1,410 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import customer_asset_service +from .base import CustomerAssetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerAssetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerAssetService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerAssetServiceGrpcAsyncIOTransport(CustomerAssetServiceTransport): + """gRPC AsyncIO backend transport for CustomerAssetService. + + Service to manage customer assets. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_customer_assets( + self, + ) -> Callable[ + [customer_asset_service.MutateCustomerAssetsRequest], + Awaitable[customer_asset_service.MutateCustomerAssetsResponse], + ]: + r"""Return a callable for the mutate customer assets method over gRPC. + + Creates, updates, or removes customer assets. Operation statuses + are returned. + + List of thrown errors: `AssetLinkError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomerAssetsRequest], + Awaitable[~.MutateCustomerAssetsResponse]]: + 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 "mutate_customer_assets" not in self._stubs: + self._stubs["mutate_customer_assets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerAssetService/MutateCustomerAssets", + request_serializer=customer_asset_service.MutateCustomerAssetsRequest.serialize, + response_deserializer=customer_asset_service.MutateCustomerAssetsResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_assets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_customer_assets: self._wrap_method( + self.mutate_customer_assets, + 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" + + +__all__ = ("CustomerAssetServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_asset_set_service/__init__.py b/google/ads/googleads/v24/services/services/customer_asset_set_service/__init__.py new file mode 100644 index 000000000..b9a164dd4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_set_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomerAssetSetServiceClient +from .async_client import CustomerAssetSetServiceAsyncClient + +__all__ = ( + "CustomerAssetSetServiceClient", + "CustomerAssetSetServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/customer_asset_set_service/async_client.py b/google/ads/googleads/v24/services/services/customer_asset_set_service/async_client.py new file mode 100644 index 000000000..3284f583d --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_set_service/async_client.py @@ -0,0 +1,437 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import customer_asset_set_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CustomerAssetSetServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CustomerAssetSetServiceClient + +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 CustomerAssetSetServiceAsyncClient: + """Service to manage customer asset set""" + + _client: CustomerAssetSetServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomerAssetSetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CustomerAssetSetServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomerAssetSetServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomerAssetSetServiceClient._DEFAULT_UNIVERSE + + asset_set_path = staticmethod(CustomerAssetSetServiceClient.asset_set_path) + parse_asset_set_path = staticmethod( + CustomerAssetSetServiceClient.parse_asset_set_path + ) + customer_path = staticmethod(CustomerAssetSetServiceClient.customer_path) + parse_customer_path = staticmethod( + CustomerAssetSetServiceClient.parse_customer_path + ) + customer_asset_set_path = staticmethod( + CustomerAssetSetServiceClient.customer_asset_set_path + ) + parse_customer_asset_set_path = staticmethod( + CustomerAssetSetServiceClient.parse_customer_asset_set_path + ) + common_billing_account_path = staticmethod( + CustomerAssetSetServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomerAssetSetServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomerAssetSetServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomerAssetSetServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomerAssetSetServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomerAssetSetServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomerAssetSetServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomerAssetSetServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomerAssetSetServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomerAssetSetServiceClient.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: + CustomerAssetSetServiceAsyncClient: The constructed client. + """ + return CustomerAssetSetServiceClient.from_service_account_info.__func__(CustomerAssetSetServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomerAssetSetServiceAsyncClient: The constructed client. + """ + return CustomerAssetSetServiceClient.from_service_account_file.__func__(CustomerAssetSetServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomerAssetSetServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomerAssetSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerAssetSetServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CustomerAssetSetServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomerAssetSetServiceTransport, + Callable[..., CustomerAssetSetServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer asset set 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,CustomerAssetSetServiceTransport,Callable[..., CustomerAssetSetServiceTransport]]]): + 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 CustomerAssetSetServiceTransport 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 = CustomerAssetSetServiceClient( + 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.ads.googleads.v24.services.CustomerAssetSetServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerAssetSetService", + "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.ads.googleads.v24.services.CustomerAssetSetService", + "credentialsType": None, + } + ), + ) + + async def mutate_customer_asset_sets( + self, + request: Optional[ + Union[ + customer_asset_set_service.MutateCustomerAssetSetsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + customer_asset_set_service.CustomerAssetSetOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_asset_set_service.MutateCustomerAssetSetsResponse: + r"""Creates, or removes customer asset sets. Operation + statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomerAssetSetsRequest, dict]]): + The request object. Request message for + [CustomerAssetSetService.MutateCustomerAssetSets][google.ads.googleads.v24.services.CustomerAssetSetService.MutateCustomerAssetSets]. + customer_id (:class:`str`): + Required. The ID of the customer + whose customer asset sets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CustomerAssetSetOperation]`): + Required. The list of operations to + perform on individual customer asset + sets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomerAssetSetsResponse: + Response message for a customer asset + set mutate. + + """ + # 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 = [customer_id, operations] + 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, customer_asset_set_service.MutateCustomerAssetSetsRequest + ): + request = customer_asset_set_service.MutateCustomerAssetSetsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_customer_asset_sets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomerAssetSetServiceAsyncClient": + 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__ = ("CustomerAssetSetServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/customer_asset_set_service/client.py b/google/ads/googleads/v24/services/services/customer_asset_set_service/client.py new file mode 100644 index 000000000..d8b0bf029 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_set_service/client.py @@ -0,0 +1,944 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import customer_asset_set_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CustomerAssetSetServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerAssetSetServiceGrpcTransport +from .transports.grpc_asyncio import CustomerAssetSetServiceGrpcAsyncIOTransport + + +class CustomerAssetSetServiceClientMeta(type): + """Metaclass for the CustomerAssetSetService 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[CustomerAssetSetServiceTransport]] + _transport_registry["grpc"] = CustomerAssetSetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CustomerAssetSetServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerAssetSetServiceTransport]: + """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 CustomerAssetSetServiceClient( + metaclass=CustomerAssetSetServiceClientMeta +): + """Service to manage customer asset set""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomerAssetSetServiceClient: 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: + CustomerAssetSetServiceClient: 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) -> CustomerAssetSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerAssetSetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def asset_set_path( + customer_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified asset_set string.""" + return "customers/{customer_id}/assetSets/{asset_set_id}".format( + customer_id=customer_id, + asset_set_id=asset_set_id, + ) + + @staticmethod + def parse_asset_set_path(path: str) -> Dict[str, str]: + """Parses a asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetSets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def customer_asset_set_path( + customer_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified customer_asset_set string.""" + return ( + "customers/{customer_id}/customerAssetSets/{asset_set_id}".format( + customer_id=customer_id, + asset_set_id=asset_set_id, + ) + ) + + @staticmethod + def parse_customer_asset_set_path(path: str) -> Dict[str, str]: + """Parses a customer_asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerAssetSets/(?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 = ( + CustomerAssetSetServiceClient._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 = ( + CustomerAssetSetServiceClient._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 + ): + """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 = CustomerAssetSetServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CustomerAssetSetServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + CustomerAssetSetServiceClient._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 = CustomerAssetSetServiceClient._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): + """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, + CustomerAssetSetServiceTransport, + Callable[..., CustomerAssetSetServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer asset set 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,CustomerAssetSetServiceTransport,Callable[..., CustomerAssetSetServiceTransport]]]): + 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 CustomerAssetSetServiceTransport 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, + ) = CustomerAssetSetServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomerAssetSetServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CustomerAssetSetServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomerAssetSetServiceTransport + ) + if transport_provided: + # transport is a CustomerAssetSetServiceTransport 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(CustomerAssetSetServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomerAssetSetServiceClient._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[CustomerAssetSetServiceTransport], + Callable[..., CustomerAssetSetServiceTransport], + ] = ( + CustomerAssetSetServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomerAssetSetServiceTransport], 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.ads.googleads.v24.services.CustomerAssetSetServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerAssetSetService", + "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.ads.googleads.v24.services.CustomerAssetSetService", + "credentialsType": None, + } + ), + ) + + def mutate_customer_asset_sets( + self, + request: Optional[ + Union[ + customer_asset_set_service.MutateCustomerAssetSetsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + customer_asset_set_service.CustomerAssetSetOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_asset_set_service.MutateCustomerAssetSetsResponse: + r"""Creates, or removes customer asset sets. Operation + statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomerAssetSetsRequest, dict]): + The request object. Request message for + [CustomerAssetSetService.MutateCustomerAssetSets][google.ads.googleads.v24.services.CustomerAssetSetService.MutateCustomerAssetSets]. + customer_id (str): + Required. The ID of the customer + whose customer asset sets are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomerAssetSetOperation]): + Required. The list of operations to + perform on individual customer asset + sets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomerAssetSetsResponse: + Response message for a customer asset + set mutate. + + """ + # 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 = [customer_id, operations] + 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, customer_asset_set_service.MutateCustomerAssetSetsRequest + ): + request = customer_asset_set_service.MutateCustomerAssetSetsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_customer_asset_sets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomerAssetSetServiceClient": + 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() + + +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__ = ("CustomerAssetSetServiceClient",) diff --git a/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/README.rst b/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/README.rst new file mode 100644 index 000000000..f4602778f --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomerAssetSetServiceTransport` is the ABC for all transports. +- public child `CustomerAssetSetServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomerAssetSetServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomerAssetSetServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomerAssetSetServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/__init__.py b/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/__init__.py new file mode 100644 index 000000000..27dbb7b93 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomerAssetSetServiceTransport +from .grpc import CustomerAssetSetServiceGrpcTransport +from .grpc_asyncio import CustomerAssetSetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerAssetSetServiceTransport]] +_transport_registry["grpc"] = CustomerAssetSetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CustomerAssetSetServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CustomerAssetSetServiceTransport", + "CustomerAssetSetServiceGrpcTransport", + "CustomerAssetSetServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/base.py b/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/base.py new file mode 100644 index 000000000..d839be8e1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import customer_asset_set_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 CustomerAssetSetServiceTransport(abc.ABC): + """Abstract transport class for CustomerAssetSetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customer_asset_sets: gapic_v1.method.wrap_method( + self.mutate_customer_asset_sets, + 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 mutate_customer_asset_sets( + self, + ) -> Callable[ + [customer_asset_set_service.MutateCustomerAssetSetsRequest], + Union[ + customer_asset_set_service.MutateCustomerAssetSetsResponse, + Awaitable[ + customer_asset_set_service.MutateCustomerAssetSetsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomerAssetSetServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/grpc.py b/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/grpc.py new file mode 100644 index 000000000..3fe57b5a1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/grpc.py @@ -0,0 +1,384 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import customer_asset_set_service +from .base import CustomerAssetSetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerAssetSetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerAssetSetService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerAssetSetServiceGrpcTransport(CustomerAssetSetServiceTransport): + """gRPC backend transport for CustomerAssetSetService. + + Service to manage customer asset set + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_customer_asset_sets( + self, + ) -> Callable[ + [customer_asset_set_service.MutateCustomerAssetSetsRequest], + customer_asset_set_service.MutateCustomerAssetSetsResponse, + ]: + r"""Return a callable for the mutate customer asset sets method over gRPC. + + Creates, or removes customer asset sets. Operation + statuses are returned. + + Returns: + Callable[[~.MutateCustomerAssetSetsRequest], + ~.MutateCustomerAssetSetsResponse]: + 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 "mutate_customer_asset_sets" not in self._stubs: + self._stubs["mutate_customer_asset_sets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerAssetSetService/MutateCustomerAssetSets", + request_serializer=customer_asset_set_service.MutateCustomerAssetSetsRequest.serialize, + response_deserializer=customer_asset_set_service.MutateCustomerAssetSetsResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_asset_sets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomerAssetSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..92180793a --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_asset_set_service/transports/grpc_asyncio.py @@ -0,0 +1,407 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import customer_asset_set_service +from .base import CustomerAssetSetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerAssetSetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerAssetSetService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerAssetSetServiceGrpcAsyncIOTransport( + CustomerAssetSetServiceTransport +): + """gRPC AsyncIO backend transport for CustomerAssetSetService. + + Service to manage customer asset set + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_customer_asset_sets( + self, + ) -> Callable[ + [customer_asset_set_service.MutateCustomerAssetSetsRequest], + Awaitable[customer_asset_set_service.MutateCustomerAssetSetsResponse], + ]: + r"""Return a callable for the mutate customer asset sets method over gRPC. + + Creates, or removes customer asset sets. Operation + statuses are returned. + + Returns: + Callable[[~.MutateCustomerAssetSetsRequest], + Awaitable[~.MutateCustomerAssetSetsResponse]]: + 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 "mutate_customer_asset_sets" not in self._stubs: + self._stubs["mutate_customer_asset_sets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerAssetSetService/MutateCustomerAssetSets", + request_serializer=customer_asset_set_service.MutateCustomerAssetSetsRequest.serialize, + response_deserializer=customer_asset_set_service.MutateCustomerAssetSetsResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_asset_sets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_customer_asset_sets: self._wrap_method( + self.mutate_customer_asset_sets, + 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" + + +__all__ = ("CustomerAssetSetServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_client_link_service/__init__.py b/google/ads/googleads/v24/services/services/customer_client_link_service/__init__.py new file mode 100644 index 000000000..4fd154093 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_client_link_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomerClientLinkServiceClient +from .async_client import CustomerClientLinkServiceAsyncClient + +__all__ = ( + "CustomerClientLinkServiceClient", + "CustomerClientLinkServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/customer_client_link_service/async_client.py b/google/ads/googleads/v24/services/services/customer_client_link_service/async_client.py new file mode 100644 index 000000000..ddaff6ae3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_client_link_service/async_client.py @@ -0,0 +1,441 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import customer_client_link_service +from .transports.base import ( + CustomerClientLinkServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CustomerClientLinkServiceClient + +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 CustomerClientLinkServiceAsyncClient: + """Service to manage customer client links.""" + + _client: CustomerClientLinkServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomerClientLinkServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + CustomerClientLinkServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomerClientLinkServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomerClientLinkServiceClient._DEFAULT_UNIVERSE + + customer_path = staticmethod(CustomerClientLinkServiceClient.customer_path) + parse_customer_path = staticmethod( + CustomerClientLinkServiceClient.parse_customer_path + ) + customer_client_link_path = staticmethod( + CustomerClientLinkServiceClient.customer_client_link_path + ) + parse_customer_client_link_path = staticmethod( + CustomerClientLinkServiceClient.parse_customer_client_link_path + ) + common_billing_account_path = staticmethod( + CustomerClientLinkServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomerClientLinkServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomerClientLinkServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomerClientLinkServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomerClientLinkServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomerClientLinkServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomerClientLinkServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomerClientLinkServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomerClientLinkServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomerClientLinkServiceClient.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: + CustomerClientLinkServiceAsyncClient: The constructed client. + """ + return CustomerClientLinkServiceClient.from_service_account_info.__func__(CustomerClientLinkServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomerClientLinkServiceAsyncClient: The constructed client. + """ + return CustomerClientLinkServiceClient.from_service_account_file.__func__(CustomerClientLinkServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomerClientLinkServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomerClientLinkServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerClientLinkServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CustomerClientLinkServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomerClientLinkServiceTransport, + Callable[..., CustomerClientLinkServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer client link 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,CustomerClientLinkServiceTransport,Callable[..., CustomerClientLinkServiceTransport]]]): + 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 CustomerClientLinkServiceTransport 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 = CustomerClientLinkServiceClient( + 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.ads.googleads.v24.services.CustomerClientLinkServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerClientLinkService", + "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.ads.googleads.v24.services.CustomerClientLinkService", + "credentialsType": None, + } + ), + ) + + async def mutate_customer_client_link( + self, + request: Optional[ + Union[ + customer_client_link_service.MutateCustomerClientLinkRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[ + customer_client_link_service.CustomerClientLinkOperation + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_client_link_service.MutateCustomerClientLinkResponse: + r"""Creates or updates a customer client link. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `ManagerLinkError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomerClientLinkRequest, dict]]): + The request object. Request message for + [CustomerClientLinkService.MutateCustomerClientLink][google.ads.googleads.v24.services.CustomerClientLinkService.MutateCustomerClientLink]. + customer_id (:class:`str`): + Required. The ID of the customer + whose customer link are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (:class:`google.ads.googleads.v24.services.types.CustomerClientLinkOperation`): + Required. The operation to perform on + the individual CustomerClientLink. + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateCustomerClientLinkResponse: + Response message for a + CustomerClientLink mutate. + + """ + # 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 = [customer_id, operation] + 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, + customer_client_link_service.MutateCustomerClientLinkRequest, + ): + request = ( + customer_client_link_service.MutateCustomerClientLinkRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_customer_client_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomerClientLinkServiceAsyncClient": + 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__ = ("CustomerClientLinkServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/customer_client_link_service/client.py b/google/ads/googleads/v24/services/services/customer_client_link_service/client.py new file mode 100644 index 000000000..546e7e673 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_client_link_service/client.py @@ -0,0 +1,924 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import customer_client_link_service +from .transports.base import ( + CustomerClientLinkServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerClientLinkServiceGrpcTransport +from .transports.grpc_asyncio import ( + CustomerClientLinkServiceGrpcAsyncIOTransport, +) + + +class CustomerClientLinkServiceClientMeta(type): + """Metaclass for the CustomerClientLinkService 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[CustomerClientLinkServiceTransport]] + _transport_registry["grpc"] = CustomerClientLinkServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CustomerClientLinkServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerClientLinkServiceTransport]: + """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 CustomerClientLinkServiceClient( + metaclass=CustomerClientLinkServiceClientMeta +): + """Service to manage customer client links.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomerClientLinkServiceClient: 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: + CustomerClientLinkServiceClient: 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) -> CustomerClientLinkServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerClientLinkServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def customer_client_link_path( + customer_id: str, + client_customer_id: str, + manager_link_id: str, + ) -> str: + """Returns a fully-qualified customer_client_link string.""" + return "customers/{customer_id}/customerClientLinks/{client_customer_id}~{manager_link_id}".format( + customer_id=customer_id, + client_customer_id=client_customer_id, + manager_link_id=manager_link_id, + ) + + @staticmethod + def parse_customer_client_link_path(path: str) -> Dict[str, str]: + """Parses a customer_client_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerClientLinks/(?P.+?)~(?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 = ( + CustomerClientLinkServiceClient._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 = ( + CustomerClientLinkServiceClient._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 + ): + """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 = ( + CustomerClientLinkServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CustomerClientLinkServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = CustomerClientLinkServiceClient._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 = CustomerClientLinkServiceClient._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): + """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, + CustomerClientLinkServiceTransport, + Callable[..., CustomerClientLinkServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer client link 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,CustomerClientLinkServiceTransport,Callable[..., CustomerClientLinkServiceTransport]]]): + 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 CustomerClientLinkServiceTransport 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, + ) = CustomerClientLinkServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomerClientLinkServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CustomerClientLinkServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomerClientLinkServiceTransport + ) + if transport_provided: + # transport is a CustomerClientLinkServiceTransport 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( + CustomerClientLinkServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomerClientLinkServiceClient._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[CustomerClientLinkServiceTransport], + Callable[..., CustomerClientLinkServiceTransport], + ] = ( + CustomerClientLinkServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomerClientLinkServiceTransport], 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.ads.googleads.v24.services.CustomerClientLinkServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerClientLinkService", + "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.ads.googleads.v24.services.CustomerClientLinkService", + "credentialsType": None, + } + ), + ) + + def mutate_customer_client_link( + self, + request: Optional[ + Union[ + customer_client_link_service.MutateCustomerClientLinkRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[ + customer_client_link_service.CustomerClientLinkOperation + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_client_link_service.MutateCustomerClientLinkResponse: + r"""Creates or updates a customer client link. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `ManagerLinkError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomerClientLinkRequest, dict]): + The request object. Request message for + [CustomerClientLinkService.MutateCustomerClientLink][google.ads.googleads.v24.services.CustomerClientLinkService.MutateCustomerClientLink]. + customer_id (str): + Required. The ID of the customer + whose customer link are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (google.ads.googleads.v24.services.types.CustomerClientLinkOperation): + Required. The operation to perform on + the individual CustomerClientLink. + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateCustomerClientLinkResponse: + Response message for a + CustomerClientLink mutate. + + """ + # 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 = [customer_id, operation] + 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, + customer_client_link_service.MutateCustomerClientLinkRequest, + ): + request = ( + customer_client_link_service.MutateCustomerClientLinkRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_customer_client_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomerClientLinkServiceClient": + 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() + + +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__ = ("CustomerClientLinkServiceClient",) diff --git a/google/ads/googleads/v24/services/services/customer_client_link_service/transports/README.rst b/google/ads/googleads/v24/services/services/customer_client_link_service/transports/README.rst new file mode 100644 index 000000000..31b708693 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_client_link_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomerClientLinkServiceTransport` is the ABC for all transports. +- public child `CustomerClientLinkServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomerClientLinkServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomerClientLinkServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomerClientLinkServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/customer_client_link_service/transports/__init__.py b/google/ads/googleads/v24/services/services/customer_client_link_service/transports/__init__.py new file mode 100644 index 000000000..58baca776 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_client_link_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomerClientLinkServiceTransport +from .grpc import CustomerClientLinkServiceGrpcTransport +from .grpc_asyncio import CustomerClientLinkServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerClientLinkServiceTransport]] +_transport_registry["grpc"] = CustomerClientLinkServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CustomerClientLinkServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CustomerClientLinkServiceTransport", + "CustomerClientLinkServiceGrpcTransport", + "CustomerClientLinkServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customer_client_link_service/transports/base.py b/google/ads/googleads/v24/services/services/customer_client_link_service/transports/base.py new file mode 100644 index 000000000..c21596f46 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_client_link_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import customer_client_link_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 CustomerClientLinkServiceTransport(abc.ABC): + """Abstract transport class for CustomerClientLinkService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customer_client_link: gapic_v1.method.wrap_method( + self.mutate_customer_client_link, + 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 mutate_customer_client_link( + self, + ) -> Callable[ + [customer_client_link_service.MutateCustomerClientLinkRequest], + Union[ + customer_client_link_service.MutateCustomerClientLinkResponse, + Awaitable[ + customer_client_link_service.MutateCustomerClientLinkResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomerClientLinkServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_client_link_service/transports/grpc.py b/google/ads/googleads/v24/services/services/customer_client_link_service/transports/grpc.py new file mode 100644 index 000000000..0abb9b68c --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_client_link_service/transports/grpc.py @@ -0,0 +1,393 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import customer_client_link_service +from .base import CustomerClientLinkServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerClientLinkService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerClientLinkService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerClientLinkServiceGrpcTransport( + CustomerClientLinkServiceTransport +): + """gRPC backend transport for CustomerClientLinkService. + + Service to manage customer client links. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_customer_client_link( + self, + ) -> Callable[ + [customer_client_link_service.MutateCustomerClientLinkRequest], + customer_client_link_service.MutateCustomerClientLinkResponse, + ]: + r"""Return a callable for the mutate customer client link method over gRPC. + + Creates or updates a customer client link. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `ManagerLinkError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomerClientLinkRequest], + ~.MutateCustomerClientLinkResponse]: + 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 "mutate_customer_client_link" not in self._stubs: + self._stubs["mutate_customer_client_link"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerClientLinkService/MutateCustomerClientLink", + request_serializer=customer_client_link_service.MutateCustomerClientLinkRequest.serialize, + response_deserializer=customer_client_link_service.MutateCustomerClientLinkResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_client_link"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomerClientLinkServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_client_link_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/customer_client_link_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..30def6380 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_client_link_service/transports/grpc_asyncio.py @@ -0,0 +1,416 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import customer_client_link_service +from .base import CustomerClientLinkServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerClientLinkService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerClientLinkService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerClientLinkServiceGrpcAsyncIOTransport( + CustomerClientLinkServiceTransport +): + """gRPC AsyncIO backend transport for CustomerClientLinkService. + + Service to manage customer client links. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_customer_client_link( + self, + ) -> Callable[ + [customer_client_link_service.MutateCustomerClientLinkRequest], + Awaitable[ + customer_client_link_service.MutateCustomerClientLinkResponse + ], + ]: + r"""Return a callable for the mutate customer client link method over gRPC. + + Creates or updates a customer client link. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `ManagerLinkError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomerClientLinkRequest], + Awaitable[~.MutateCustomerClientLinkResponse]]: + 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 "mutate_customer_client_link" not in self._stubs: + self._stubs["mutate_customer_client_link"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerClientLinkService/MutateCustomerClientLink", + request_serializer=customer_client_link_service.MutateCustomerClientLinkRequest.serialize, + response_deserializer=customer_client_link_service.MutateCustomerClientLinkResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_client_link"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_customer_client_link: self._wrap_method( + self.mutate_customer_client_link, + 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" + + +__all__ = ("CustomerClientLinkServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_conversion_goal_service/__init__.py b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/__init__.py new file mode 100644 index 000000000..38a3be945 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomerConversionGoalServiceClient +from .async_client import CustomerConversionGoalServiceAsyncClient + +__all__ = ( + "CustomerConversionGoalServiceClient", + "CustomerConversionGoalServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/customer_conversion_goal_service/async_client.py b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/async_client.py new file mode 100644 index 000000000..4de128340 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/async_client.py @@ -0,0 +1,436 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + customer_conversion_goal_service, +) +from .transports.base import ( + CustomerConversionGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CustomerConversionGoalServiceClient + +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 CustomerConversionGoalServiceAsyncClient: + """Service to manage customer conversion goal.""" + + _client: CustomerConversionGoalServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomerConversionGoalServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + CustomerConversionGoalServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomerConversionGoalServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomerConversionGoalServiceClient._DEFAULT_UNIVERSE + + customer_conversion_goal_path = staticmethod( + CustomerConversionGoalServiceClient.customer_conversion_goal_path + ) + parse_customer_conversion_goal_path = staticmethod( + CustomerConversionGoalServiceClient.parse_customer_conversion_goal_path + ) + common_billing_account_path = staticmethod( + CustomerConversionGoalServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomerConversionGoalServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomerConversionGoalServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomerConversionGoalServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomerConversionGoalServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomerConversionGoalServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomerConversionGoalServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomerConversionGoalServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomerConversionGoalServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomerConversionGoalServiceClient.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: + CustomerConversionGoalServiceAsyncClient: The constructed client. + """ + return CustomerConversionGoalServiceClient.from_service_account_info.__func__(CustomerConversionGoalServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomerConversionGoalServiceAsyncClient: The constructed client. + """ + return CustomerConversionGoalServiceClient.from_service_account_file.__func__(CustomerConversionGoalServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomerConversionGoalServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomerConversionGoalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerConversionGoalServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + CustomerConversionGoalServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomerConversionGoalServiceTransport, + Callable[..., CustomerConversionGoalServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer conversion goal 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,CustomerConversionGoalServiceTransport,Callable[..., CustomerConversionGoalServiceTransport]]]): + 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 CustomerConversionGoalServiceTransport 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 = CustomerConversionGoalServiceClient( + 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.ads.googleads.v24.services.CustomerConversionGoalServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerConversionGoalService", + "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.ads.googleads.v24.services.CustomerConversionGoalService", + "credentialsType": None, + } + ), + ) + + async def mutate_customer_conversion_goals( + self, + request: Optional[ + Union[ + customer_conversion_goal_service.MutateCustomerConversionGoalsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + customer_conversion_goal_service.CustomerConversionGoalOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_conversion_goal_service.MutateCustomerConversionGoalsResponse: + r"""Creates, updates or removes customer conversion + goals. Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomerConversionGoalsRequest, dict]]): + The request object. Request message for + [CustomerConversionGoalService.MutateCustomerConversionGoals][google.ads.googleads.v24.services.CustomerConversionGoalService.MutateCustomerConversionGoals]. + customer_id (:class:`str`): + Required. The ID of the customer + whose customer conversion goals are + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CustomerConversionGoalOperation]`): + Required. The list of operations to + perform on individual customer + conversion goal. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomerConversionGoalsResponse: + Response message for a customer + conversion goal mutate. + + """ + # 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 = [customer_id, operations] + 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, + customer_conversion_goal_service.MutateCustomerConversionGoalsRequest, + ): + request = customer_conversion_goal_service.MutateCustomerConversionGoalsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_customer_conversion_goals + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomerConversionGoalServiceAsyncClient": + 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__ = ("CustomerConversionGoalServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/customer_conversion_goal_service/client.py b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/client.py new file mode 100644 index 000000000..6104cc0da --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/client.py @@ -0,0 +1,921 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + customer_conversion_goal_service, +) +from .transports.base import ( + CustomerConversionGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerConversionGoalServiceGrpcTransport +from .transports.grpc_asyncio import ( + CustomerConversionGoalServiceGrpcAsyncIOTransport, +) + + +class CustomerConversionGoalServiceClientMeta(type): + """Metaclass for the CustomerConversionGoalService 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[CustomerConversionGoalServiceTransport]] + _transport_registry["grpc"] = CustomerConversionGoalServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CustomerConversionGoalServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerConversionGoalServiceTransport]: + """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 CustomerConversionGoalServiceClient( + metaclass=CustomerConversionGoalServiceClientMeta +): + """Service to manage customer conversion goal.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomerConversionGoalServiceClient: 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: + CustomerConversionGoalServiceClient: 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) -> CustomerConversionGoalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerConversionGoalServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customer_conversion_goal_path( + customer_id: str, + category: str, + source: str, + ) -> str: + """Returns a fully-qualified customer_conversion_goal string.""" + return "customers/{customer_id}/customerConversionGoals/{category}~{source}".format( + customer_id=customer_id, + category=category, + source=source, + ) + + @staticmethod + def parse_customer_conversion_goal_path(path: str) -> Dict[str, str]: + """Parses a customer_conversion_goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerConversionGoals/(?P.+?)~(?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 = ( + CustomerConversionGoalServiceClient._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 = ( + CustomerConversionGoalServiceClient._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 + ): + """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 = ( + CustomerConversionGoalServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + CustomerConversionGoalServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = CustomerConversionGoalServiceClient._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 = CustomerConversionGoalServiceClient._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): + """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, + CustomerConversionGoalServiceTransport, + Callable[..., CustomerConversionGoalServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer conversion goal 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,CustomerConversionGoalServiceTransport,Callable[..., CustomerConversionGoalServiceTransport]]]): + 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 CustomerConversionGoalServiceTransport 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, + ) = CustomerConversionGoalServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomerConversionGoalServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CustomerConversionGoalServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomerConversionGoalServiceTransport + ) + if transport_provided: + # transport is a CustomerConversionGoalServiceTransport 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( + CustomerConversionGoalServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomerConversionGoalServiceClient._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[CustomerConversionGoalServiceTransport], + Callable[..., CustomerConversionGoalServiceTransport], + ] = ( + CustomerConversionGoalServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomerConversionGoalServiceTransport], + 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.ads.googleads.v24.services.CustomerConversionGoalServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerConversionGoalService", + "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.ads.googleads.v24.services.CustomerConversionGoalService", + "credentialsType": None, + } + ), + ) + + def mutate_customer_conversion_goals( + self, + request: Optional[ + Union[ + customer_conversion_goal_service.MutateCustomerConversionGoalsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + customer_conversion_goal_service.CustomerConversionGoalOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_conversion_goal_service.MutateCustomerConversionGoalsResponse: + r"""Creates, updates or removes customer conversion + goals. Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomerConversionGoalsRequest, dict]): + The request object. Request message for + [CustomerConversionGoalService.MutateCustomerConversionGoals][google.ads.googleads.v24.services.CustomerConversionGoalService.MutateCustomerConversionGoals]. + customer_id (str): + Required. The ID of the customer + whose customer conversion goals are + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomerConversionGoalOperation]): + Required. The list of operations to + perform on individual customer + conversion goal. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomerConversionGoalsResponse: + Response message for a customer + conversion goal mutate. + + """ + # 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 = [customer_id, operations] + 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, + customer_conversion_goal_service.MutateCustomerConversionGoalsRequest, + ): + request = customer_conversion_goal_service.MutateCustomerConversionGoalsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_customer_conversion_goals + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomerConversionGoalServiceClient": + 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() + + +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__ = ("CustomerConversionGoalServiceClient",) diff --git a/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/README.rst b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/README.rst new file mode 100644 index 000000000..0be245c04 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomerConversionGoalServiceTransport` is the ABC for all transports. +- public child `CustomerConversionGoalServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomerConversionGoalServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomerConversionGoalServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomerConversionGoalServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/__init__.py b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/__init__.py new file mode 100644 index 000000000..c1742d79e --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomerConversionGoalServiceTransport +from .grpc import CustomerConversionGoalServiceGrpcTransport +from .grpc_asyncio import CustomerConversionGoalServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerConversionGoalServiceTransport]] +_transport_registry["grpc"] = CustomerConversionGoalServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CustomerConversionGoalServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CustomerConversionGoalServiceTransport", + "CustomerConversionGoalServiceGrpcTransport", + "CustomerConversionGoalServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/base.py b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/base.py new file mode 100644 index 000000000..cc456b2fd --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + customer_conversion_goal_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 CustomerConversionGoalServiceTransport(abc.ABC): + """Abstract transport class for CustomerConversionGoalService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customer_conversion_goals: gapic_v1.method.wrap_method( + self.mutate_customer_conversion_goals, + 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 mutate_customer_conversion_goals( + self, + ) -> Callable[ + [customer_conversion_goal_service.MutateCustomerConversionGoalsRequest], + Union[ + customer_conversion_goal_service.MutateCustomerConversionGoalsResponse, + Awaitable[ + customer_conversion_goal_service.MutateCustomerConversionGoalsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomerConversionGoalServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/grpc.py b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/grpc.py new file mode 100644 index 000000000..ce45ca109 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/grpc.py @@ -0,0 +1,389 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + customer_conversion_goal_service, +) +from .base import CustomerConversionGoalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerConversionGoalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerConversionGoalService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerConversionGoalServiceGrpcTransport( + CustomerConversionGoalServiceTransport +): + """gRPC backend transport for CustomerConversionGoalService. + + Service to manage customer conversion goal. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_customer_conversion_goals( + self, + ) -> Callable[ + [customer_conversion_goal_service.MutateCustomerConversionGoalsRequest], + customer_conversion_goal_service.MutateCustomerConversionGoalsResponse, + ]: + r"""Return a callable for the mutate customer conversion + goals method over gRPC. + + Creates, updates or removes customer conversion + goals. Operation statuses are returned. + + Returns: + Callable[[~.MutateCustomerConversionGoalsRequest], + ~.MutateCustomerConversionGoalsResponse]: + 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 "mutate_customer_conversion_goals" not in self._stubs: + self._stubs["mutate_customer_conversion_goals"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerConversionGoalService/MutateCustomerConversionGoals", + request_serializer=customer_conversion_goal_service.MutateCustomerConversionGoalsRequest.serialize, + response_deserializer=customer_conversion_goal_service.MutateCustomerConversionGoalsResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_conversion_goals"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomerConversionGoalServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..99aa878fa --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_conversion_goal_service/transports/grpc_asyncio.py @@ -0,0 +1,412 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + customer_conversion_goal_service, +) +from .base import CustomerConversionGoalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerConversionGoalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerConversionGoalService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerConversionGoalServiceGrpcAsyncIOTransport( + CustomerConversionGoalServiceTransport +): + """gRPC AsyncIO backend transport for CustomerConversionGoalService. + + Service to manage customer conversion goal. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_customer_conversion_goals( + self, + ) -> Callable[ + [customer_conversion_goal_service.MutateCustomerConversionGoalsRequest], + Awaitable[ + customer_conversion_goal_service.MutateCustomerConversionGoalsResponse + ], + ]: + r"""Return a callable for the mutate customer conversion + goals method over gRPC. + + Creates, updates or removes customer conversion + goals. Operation statuses are returned. + + Returns: + Callable[[~.MutateCustomerConversionGoalsRequest], + Awaitable[~.MutateCustomerConversionGoalsResponse]]: + 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 "mutate_customer_conversion_goals" not in self._stubs: + self._stubs["mutate_customer_conversion_goals"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerConversionGoalService/MutateCustomerConversionGoals", + request_serializer=customer_conversion_goal_service.MutateCustomerConversionGoalsRequest.serialize, + response_deserializer=customer_conversion_goal_service.MutateCustomerConversionGoalsResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_conversion_goals"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_customer_conversion_goals: self._wrap_method( + self.mutate_customer_conversion_goals, + 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" + + +__all__ = ("CustomerConversionGoalServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_customizer_service/__init__.py b/google/ads/googleads/v24/services/services/customer_customizer_service/__init__.py new file mode 100644 index 000000000..d91d91175 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_customizer_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomerCustomizerServiceClient +from .async_client import CustomerCustomizerServiceAsyncClient + +__all__ = ( + "CustomerCustomizerServiceClient", + "CustomerCustomizerServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/customer_customizer_service/async_client.py b/google/ads/googleads/v24/services/services/customer_customizer_service/async_client.py new file mode 100644 index 000000000..e3316cd11 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_customizer_service/async_client.py @@ -0,0 +1,441 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import customer_customizer_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CustomerCustomizerServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CustomerCustomizerServiceClient + +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 CustomerCustomizerServiceAsyncClient: + """Service to manage customer customizer""" + + _client: CustomerCustomizerServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomerCustomizerServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + CustomerCustomizerServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomerCustomizerServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomerCustomizerServiceClient._DEFAULT_UNIVERSE + + customer_customizer_path = staticmethod( + CustomerCustomizerServiceClient.customer_customizer_path + ) + parse_customer_customizer_path = staticmethod( + CustomerCustomizerServiceClient.parse_customer_customizer_path + ) + customizer_attribute_path = staticmethod( + CustomerCustomizerServiceClient.customizer_attribute_path + ) + parse_customizer_attribute_path = staticmethod( + CustomerCustomizerServiceClient.parse_customizer_attribute_path + ) + common_billing_account_path = staticmethod( + CustomerCustomizerServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomerCustomizerServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomerCustomizerServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomerCustomizerServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomerCustomizerServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomerCustomizerServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomerCustomizerServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomerCustomizerServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomerCustomizerServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomerCustomizerServiceClient.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: + CustomerCustomizerServiceAsyncClient: The constructed client. + """ + return CustomerCustomizerServiceClient.from_service_account_info.__func__(CustomerCustomizerServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomerCustomizerServiceAsyncClient: The constructed client. + """ + return CustomerCustomizerServiceClient.from_service_account_file.__func__(CustomerCustomizerServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomerCustomizerServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomerCustomizerServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerCustomizerServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CustomerCustomizerServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomerCustomizerServiceTransport, + Callable[..., CustomerCustomizerServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer customizer 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,CustomerCustomizerServiceTransport,Callable[..., CustomerCustomizerServiceTransport]]]): + 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 CustomerCustomizerServiceTransport 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 = CustomerCustomizerServiceClient( + 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.ads.googleads.v24.services.CustomerCustomizerServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerCustomizerService", + "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.ads.googleads.v24.services.CustomerCustomizerService", + "credentialsType": None, + } + ), + ) + + async def mutate_customer_customizers( + self, + request: Optional[ + Union[ + customer_customizer_service.MutateCustomerCustomizersRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + customer_customizer_service.CustomerCustomizerOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_customizer_service.MutateCustomerCustomizersResponse: + r"""Creates, updates or removes customer customizers. + Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomerCustomizersRequest, dict]]): + The request object. Request message for + [CustomerCustomizerService.MutateCustomerCustomizers][google.ads.googleads.v24.services.CustomerCustomizerService.MutateCustomerCustomizers]. + customer_id (:class:`str`): + Required. The ID of the customer + whose customer customizers are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CustomerCustomizerOperation]`): + Required. The list of operations to + perform on individual customer + customizers. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomerCustomizersResponse: + Response message for a customizer + attribute mutate. + + """ + # 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 = [customer_id, operations] + 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, + customer_customizer_service.MutateCustomerCustomizersRequest, + ): + request = ( + customer_customizer_service.MutateCustomerCustomizersRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_customer_customizers + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomerCustomizerServiceAsyncClient": + 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__ = ("CustomerCustomizerServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/customer_customizer_service/client.py b/google/ads/googleads/v24/services/services/customer_customizer_service/client.py new file mode 100644 index 000000000..8afe14b60 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_customizer_service/client.py @@ -0,0 +1,935 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import customer_customizer_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CustomerCustomizerServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerCustomizerServiceGrpcTransport +from .transports.grpc_asyncio import ( + CustomerCustomizerServiceGrpcAsyncIOTransport, +) + + +class CustomerCustomizerServiceClientMeta(type): + """Metaclass for the CustomerCustomizerService 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[CustomerCustomizerServiceTransport]] + _transport_registry["grpc"] = CustomerCustomizerServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CustomerCustomizerServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerCustomizerServiceTransport]: + """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 CustomerCustomizerServiceClient( + metaclass=CustomerCustomizerServiceClientMeta +): + """Service to manage customer customizer""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomerCustomizerServiceClient: 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: + CustomerCustomizerServiceClient: 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) -> CustomerCustomizerServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerCustomizerServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customer_customizer_path( + customer_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified customer_customizer string.""" + return "customers/{customer_id}/customerCustomizers/{customizer_attribute_id}".format( + customer_id=customer_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_customer_customizer_path(path: str) -> Dict[str, str]: + """Parses a customer_customizer path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerCustomizers/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customizer_attribute_path( + customer_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified customizer_attribute string.""" + return "customers/{customer_id}/customizerAttributes/{customizer_attribute_id}".format( + customer_id=customer_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_customizer_attribute_path(path: str) -> Dict[str, str]: + """Parses a customizer_attribute path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customizerAttributes/(?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 = ( + CustomerCustomizerServiceClient._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 = ( + CustomerCustomizerServiceClient._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 + ): + """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 = ( + CustomerCustomizerServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CustomerCustomizerServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = CustomerCustomizerServiceClient._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 = CustomerCustomizerServiceClient._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): + """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, + CustomerCustomizerServiceTransport, + Callable[..., CustomerCustomizerServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer customizer 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,CustomerCustomizerServiceTransport,Callable[..., CustomerCustomizerServiceTransport]]]): + 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 CustomerCustomizerServiceTransport 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, + ) = CustomerCustomizerServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomerCustomizerServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CustomerCustomizerServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomerCustomizerServiceTransport + ) + if transport_provided: + # transport is a CustomerCustomizerServiceTransport 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( + CustomerCustomizerServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomerCustomizerServiceClient._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[CustomerCustomizerServiceTransport], + Callable[..., CustomerCustomizerServiceTransport], + ] = ( + CustomerCustomizerServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomerCustomizerServiceTransport], 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.ads.googleads.v24.services.CustomerCustomizerServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerCustomizerService", + "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.ads.googleads.v24.services.CustomerCustomizerService", + "credentialsType": None, + } + ), + ) + + def mutate_customer_customizers( + self, + request: Optional[ + Union[ + customer_customizer_service.MutateCustomerCustomizersRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + customer_customizer_service.CustomerCustomizerOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_customizer_service.MutateCustomerCustomizersResponse: + r"""Creates, updates or removes customer customizers. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomerCustomizersRequest, dict]): + The request object. Request message for + [CustomerCustomizerService.MutateCustomerCustomizers][google.ads.googleads.v24.services.CustomerCustomizerService.MutateCustomerCustomizers]. + customer_id (str): + Required. The ID of the customer + whose customer customizers are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomerCustomizerOperation]): + Required. The list of operations to + perform on individual customer + customizers. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomerCustomizersResponse: + Response message for a customizer + attribute mutate. + + """ + # 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 = [customer_id, operations] + 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, + customer_customizer_service.MutateCustomerCustomizersRequest, + ): + request = ( + customer_customizer_service.MutateCustomerCustomizersRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_customer_customizers + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomerCustomizerServiceClient": + 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() + + +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__ = ("CustomerCustomizerServiceClient",) diff --git a/google/ads/googleads/v24/services/services/customer_customizer_service/transports/README.rst b/google/ads/googleads/v24/services/services/customer_customizer_service/transports/README.rst new file mode 100644 index 000000000..91966f081 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_customizer_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomerCustomizerServiceTransport` is the ABC for all transports. +- public child `CustomerCustomizerServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomerCustomizerServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomerCustomizerServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomerCustomizerServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/customer_customizer_service/transports/__init__.py b/google/ads/googleads/v24/services/services/customer_customizer_service/transports/__init__.py new file mode 100644 index 000000000..d5b3d0296 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_customizer_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomerCustomizerServiceTransport +from .grpc import CustomerCustomizerServiceGrpcTransport +from .grpc_asyncio import CustomerCustomizerServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerCustomizerServiceTransport]] +_transport_registry["grpc"] = CustomerCustomizerServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CustomerCustomizerServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CustomerCustomizerServiceTransport", + "CustomerCustomizerServiceGrpcTransport", + "CustomerCustomizerServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customer_customizer_service/transports/base.py b/google/ads/googleads/v24/services/services/customer_customizer_service/transports/base.py new file mode 100644 index 000000000..1d874b253 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_customizer_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import customer_customizer_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 CustomerCustomizerServiceTransport(abc.ABC): + """Abstract transport class for CustomerCustomizerService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customer_customizers: gapic_v1.method.wrap_method( + self.mutate_customer_customizers, + 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 mutate_customer_customizers( + self, + ) -> Callable[ + [customer_customizer_service.MutateCustomerCustomizersRequest], + Union[ + customer_customizer_service.MutateCustomerCustomizersResponse, + Awaitable[ + customer_customizer_service.MutateCustomerCustomizersResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomerCustomizerServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_customizer_service/transports/grpc.py b/google/ads/googleads/v24/services/services/customer_customizer_service/transports/grpc.py new file mode 100644 index 000000000..50ce3587c --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_customizer_service/transports/grpc.py @@ -0,0 +1,386 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import customer_customizer_service +from .base import CustomerCustomizerServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerCustomizerService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerCustomizerService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerCustomizerServiceGrpcTransport( + CustomerCustomizerServiceTransport +): + """gRPC backend transport for CustomerCustomizerService. + + Service to manage customer customizer + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_customer_customizers( + self, + ) -> Callable[ + [customer_customizer_service.MutateCustomerCustomizersRequest], + customer_customizer_service.MutateCustomerCustomizersResponse, + ]: + r"""Return a callable for the mutate customer customizers method over gRPC. + + Creates, updates or removes customer customizers. + Operation statuses are returned. + + Returns: + Callable[[~.MutateCustomerCustomizersRequest], + ~.MutateCustomerCustomizersResponse]: + 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 "mutate_customer_customizers" not in self._stubs: + self._stubs["mutate_customer_customizers"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerCustomizerService/MutateCustomerCustomizers", + request_serializer=customer_customizer_service.MutateCustomerCustomizersRequest.serialize, + response_deserializer=customer_customizer_service.MutateCustomerCustomizersResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_customizers"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomerCustomizerServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_customizer_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/customer_customizer_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..a631143ef --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_customizer_service/transports/grpc_asyncio.py @@ -0,0 +1,409 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import customer_customizer_service +from .base import CustomerCustomizerServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerCustomizerService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerCustomizerService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerCustomizerServiceGrpcAsyncIOTransport( + CustomerCustomizerServiceTransport +): + """gRPC AsyncIO backend transport for CustomerCustomizerService. + + Service to manage customer customizer + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_customer_customizers( + self, + ) -> Callable[ + [customer_customizer_service.MutateCustomerCustomizersRequest], + Awaitable[ + customer_customizer_service.MutateCustomerCustomizersResponse + ], + ]: + r"""Return a callable for the mutate customer customizers method over gRPC. + + Creates, updates or removes customer customizers. + Operation statuses are returned. + + Returns: + Callable[[~.MutateCustomerCustomizersRequest], + Awaitable[~.MutateCustomerCustomizersResponse]]: + 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 "mutate_customer_customizers" not in self._stubs: + self._stubs["mutate_customer_customizers"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerCustomizerService/MutateCustomerCustomizers", + request_serializer=customer_customizer_service.MutateCustomerCustomizersRequest.serialize, + response_deserializer=customer_customizer_service.MutateCustomerCustomizersResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_customizers"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_customer_customizers: self._wrap_method( + self.mutate_customer_customizers, + 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" + + +__all__ = ("CustomerCustomizerServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_label_service/__init__.py b/google/ads/googleads/v24/services/services/customer_label_service/__init__.py new file mode 100644 index 000000000..1bbc2881f --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_label_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomerLabelServiceClient +from .async_client import CustomerLabelServiceAsyncClient + +__all__ = ( + "CustomerLabelServiceClient", + "CustomerLabelServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/customer_label_service/async_client.py b/google/ads/googleads/v24/services/services/customer_label_service/async_client.py new file mode 100644 index 000000000..8412c80f1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_label_service/async_client.py @@ -0,0 +1,443 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import customer_label_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CustomerLabelServiceTransport, DEFAULT_CLIENT_INFO +from .client import CustomerLabelServiceClient + +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 CustomerLabelServiceAsyncClient: + """Service to manage labels on Google Ads customers. + + This service is commonly used by manager accounts to apply their + own labels to their client accounts. The label entity must exist + under the manager account. + """ + + _client: CustomerLabelServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomerLabelServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CustomerLabelServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomerLabelServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomerLabelServiceClient._DEFAULT_UNIVERSE + + customer_path = staticmethod(CustomerLabelServiceClient.customer_path) + parse_customer_path = staticmethod( + CustomerLabelServiceClient.parse_customer_path + ) + customer_label_path = staticmethod( + CustomerLabelServiceClient.customer_label_path + ) + parse_customer_label_path = staticmethod( + CustomerLabelServiceClient.parse_customer_label_path + ) + label_path = staticmethod(CustomerLabelServiceClient.label_path) + parse_label_path = staticmethod(CustomerLabelServiceClient.parse_label_path) + common_billing_account_path = staticmethod( + CustomerLabelServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomerLabelServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomerLabelServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomerLabelServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomerLabelServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomerLabelServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomerLabelServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomerLabelServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomerLabelServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomerLabelServiceClient.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: + CustomerLabelServiceAsyncClient: The constructed client. + """ + return CustomerLabelServiceClient.from_service_account_info.__func__(CustomerLabelServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomerLabelServiceAsyncClient: The constructed client. + """ + return CustomerLabelServiceClient.from_service_account_file.__func__(CustomerLabelServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomerLabelServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomerLabelServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerLabelServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CustomerLabelServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomerLabelServiceTransport, + Callable[..., CustomerLabelServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer label 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,CustomerLabelServiceTransport,Callable[..., CustomerLabelServiceTransport]]]): + 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 CustomerLabelServiceTransport 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 = CustomerLabelServiceClient( + 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.ads.googleads.v24.services.CustomerLabelServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerLabelService", + "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.ads.googleads.v24.services.CustomerLabelService", + "credentialsType": None, + } + ), + ) + + async def mutate_customer_labels( + self, + request: Optional[ + Union[customer_label_service.MutateCustomerLabelsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[customer_label_service.CustomerLabelOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_label_service.MutateCustomerLabelsResponse: + r"""Creates and removes customer-label relationships. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomerLabelsRequest, dict]]): + The request object. Request message for + [CustomerLabelService.MutateCustomerLabels][google.ads.googleads.v24.services.CustomerLabelService.MutateCustomerLabels]. + + A single ``MutateCustomerLabelsRequest`` can only modify + labels for the single customer account specified in the + request. To apply a label to multiple different + accounts, separate ``MutateCustomerLabelsRequest`` calls + must be made. + customer_id (:class:`str`): + Required. ID of the customer whose + customer-label relationships are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CustomerLabelOperation]`): + Required. The list of operations to + perform on customer-label relationships. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomerLabelsResponse: + Response message for a customer + labels mutate. + + """ + # 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 = [customer_id, operations] + 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, customer_label_service.MutateCustomerLabelsRequest + ): + request = customer_label_service.MutateCustomerLabelsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_customer_labels + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomerLabelServiceAsyncClient": + 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__ = ("CustomerLabelServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/customer_label_service/client.py b/google/ads/googleads/v24/services/services/customer_label_service/client.py new file mode 100644 index 000000000..f0da9506c --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_label_service/client.py @@ -0,0 +1,945 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import customer_label_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CustomerLabelServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CustomerLabelServiceGrpcTransport +from .transports.grpc_asyncio import CustomerLabelServiceGrpcAsyncIOTransport + + +class CustomerLabelServiceClientMeta(type): + """Metaclass for the CustomerLabelService 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[CustomerLabelServiceTransport]] + _transport_registry["grpc"] = CustomerLabelServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CustomerLabelServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerLabelServiceTransport]: + """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 CustomerLabelServiceClient(metaclass=CustomerLabelServiceClientMeta): + """Service to manage labels on Google Ads customers. + + This service is commonly used by manager accounts to apply their + own labels to their client accounts. The label entity must exist + under the manager account. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomerLabelServiceClient: 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: + CustomerLabelServiceClient: 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) -> CustomerLabelServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerLabelServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def customer_label_path( + customer_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified customer_label string.""" + return "customers/{customer_id}/customerLabels/{label_id}".format( + customer_id=customer_id, + label_id=label_id, + ) + + @staticmethod + def parse_customer_label_path(path: str) -> Dict[str, str]: + """Parses a customer_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerLabels/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def label_path( + customer_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified label string.""" + return "customers/{customer_id}/labels/{label_id}".format( + customer_id=customer_id, + label_id=label_id, + ) + + @staticmethod + def parse_label_path(path: str) -> Dict[str, str]: + """Parses a label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/labels/(?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 = ( + CustomerLabelServiceClient._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 = ( + CustomerLabelServiceClient._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 + ): + """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 = CustomerLabelServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CustomerLabelServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + CustomerLabelServiceClient._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 = CustomerLabelServiceClient._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): + """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, + CustomerLabelServiceTransport, + Callable[..., CustomerLabelServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer label 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,CustomerLabelServiceTransport,Callable[..., CustomerLabelServiceTransport]]]): + 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 CustomerLabelServiceTransport 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, + ) = CustomerLabelServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomerLabelServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = CustomerLabelServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomerLabelServiceTransport + ) + if transport_provided: + # transport is a CustomerLabelServiceTransport 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(CustomerLabelServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomerLabelServiceClient._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[CustomerLabelServiceTransport], + Callable[..., CustomerLabelServiceTransport], + ] = ( + CustomerLabelServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomerLabelServiceTransport], 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.ads.googleads.v24.services.CustomerLabelServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerLabelService", + "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.ads.googleads.v24.services.CustomerLabelService", + "credentialsType": None, + } + ), + ) + + def mutate_customer_labels( + self, + request: Optional[ + Union[customer_label_service.MutateCustomerLabelsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[customer_label_service.CustomerLabelOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_label_service.MutateCustomerLabelsResponse: + r"""Creates and removes customer-label relationships. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomerLabelsRequest, dict]): + The request object. Request message for + [CustomerLabelService.MutateCustomerLabels][google.ads.googleads.v24.services.CustomerLabelService.MutateCustomerLabels]. + + A single ``MutateCustomerLabelsRequest`` can only modify + labels for the single customer account specified in the + request. To apply a label to multiple different + accounts, separate ``MutateCustomerLabelsRequest`` calls + must be made. + customer_id (str): + Required. ID of the customer whose + customer-label relationships are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomerLabelOperation]): + Required. The list of operations to + perform on customer-label relationships. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomerLabelsResponse: + Response message for a customer + labels mutate. + + """ + # 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 = [customer_id, operations] + 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, customer_label_service.MutateCustomerLabelsRequest + ): + request = customer_label_service.MutateCustomerLabelsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_customer_labels + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomerLabelServiceClient": + 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() + + +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__ = ("CustomerLabelServiceClient",) diff --git a/google/ads/googleads/v24/services/services/customer_label_service/transports/README.rst b/google/ads/googleads/v24/services/services/customer_label_service/transports/README.rst new file mode 100644 index 000000000..2eb369646 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_label_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomerLabelServiceTransport` is the ABC for all transports. +- public child `CustomerLabelServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomerLabelServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomerLabelServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomerLabelServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/customer_label_service/transports/__init__.py b/google/ads/googleads/v24/services/services/customer_label_service/transports/__init__.py new file mode 100644 index 000000000..80ffc8171 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_label_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomerLabelServiceTransport +from .grpc import CustomerLabelServiceGrpcTransport +from .grpc_asyncio import CustomerLabelServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerLabelServiceTransport]] +_transport_registry["grpc"] = CustomerLabelServiceGrpcTransport +_transport_registry["grpc_asyncio"] = CustomerLabelServiceGrpcAsyncIOTransport + +__all__ = ( + "CustomerLabelServiceTransport", + "CustomerLabelServiceGrpcTransport", + "CustomerLabelServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customer_label_service/transports/base.py b/google/ads/googleads/v24/services/services/customer_label_service/transports/base.py new file mode 100644 index 000000000..884ca8012 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_label_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import customer_label_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 CustomerLabelServiceTransport(abc.ABC): + """Abstract transport class for CustomerLabelService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customer_labels: gapic_v1.method.wrap_method( + self.mutate_customer_labels, + 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 mutate_customer_labels( + self, + ) -> Callable[ + [customer_label_service.MutateCustomerLabelsRequest], + Union[ + customer_label_service.MutateCustomerLabelsResponse, + Awaitable[customer_label_service.MutateCustomerLabelsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomerLabelServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_label_service/transports/grpc.py b/google/ads/googleads/v24/services/services/customer_label_service/transports/grpc.py new file mode 100644 index 000000000..a8c6bd23d --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_label_service/transports/grpc.py @@ -0,0 +1,393 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import customer_label_service +from .base import CustomerLabelServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerLabelService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerLabelService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerLabelServiceGrpcTransport(CustomerLabelServiceTransport): + """gRPC backend transport for CustomerLabelService. + + Service to manage labels on Google Ads customers. + + This service is commonly used by manager accounts to apply their + own labels to their client accounts. The label entity must exist + under the manager account. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_customer_labels( + self, + ) -> Callable[ + [customer_label_service.MutateCustomerLabelsRequest], + customer_label_service.MutateCustomerLabelsResponse, + ]: + r"""Return a callable for the mutate customer labels method over gRPC. + + Creates and removes customer-label relationships. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomerLabelsRequest], + ~.MutateCustomerLabelsResponse]: + 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 "mutate_customer_labels" not in self._stubs: + self._stubs["mutate_customer_labels"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerLabelService/MutateCustomerLabels", + request_serializer=customer_label_service.MutateCustomerLabelsRequest.serialize, + response_deserializer=customer_label_service.MutateCustomerLabelsResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_labels"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomerLabelServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_label_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/customer_label_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..33b3ddc37 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_label_service/transports/grpc_asyncio.py @@ -0,0 +1,414 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import customer_label_service +from .base import CustomerLabelServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerLabelService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerLabelService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerLabelServiceGrpcAsyncIOTransport(CustomerLabelServiceTransport): + """gRPC AsyncIO backend transport for CustomerLabelService. + + Service to manage labels on Google Ads customers. + + This service is commonly used by manager accounts to apply their + own labels to their client accounts. The label entity must exist + under the manager account. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_customer_labels( + self, + ) -> Callable[ + [customer_label_service.MutateCustomerLabelsRequest], + Awaitable[customer_label_service.MutateCustomerLabelsResponse], + ]: + r"""Return a callable for the mutate customer labels method over gRPC. + + Creates and removes customer-label relationships. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `HeaderError <>`__ `InternalError <>`__ `LabelError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomerLabelsRequest], + Awaitable[~.MutateCustomerLabelsResponse]]: + 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 "mutate_customer_labels" not in self._stubs: + self._stubs["mutate_customer_labels"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerLabelService/MutateCustomerLabels", + request_serializer=customer_label_service.MutateCustomerLabelsRequest.serialize, + response_deserializer=customer_label_service.MutateCustomerLabelsResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_labels"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_customer_labels: self._wrap_method( + self.mutate_customer_labels, + 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" + + +__all__ = ("CustomerLabelServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/__init__.py b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/__init__.py new file mode 100644 index 000000000..6b94f3ae8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomerLifecycleGoalServiceClient +from .async_client import CustomerLifecycleGoalServiceAsyncClient + +__all__ = ( + "CustomerLifecycleGoalServiceClient", + "CustomerLifecycleGoalServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/async_client.py b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/async_client.py new file mode 100644 index 000000000..beed217c5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/async_client.py @@ -0,0 +1,442 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + customer_lifecycle_goal_service, +) +from .transports.base import ( + CustomerLifecycleGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CustomerLifecycleGoalServiceClient + +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 CustomerLifecycleGoalServiceAsyncClient: + """Service to configure customer lifecycle goals.""" + + _client: CustomerLifecycleGoalServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomerLifecycleGoalServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + CustomerLifecycleGoalServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomerLifecycleGoalServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomerLifecycleGoalServiceClient._DEFAULT_UNIVERSE + + customer_path = staticmethod( + CustomerLifecycleGoalServiceClient.customer_path + ) + parse_customer_path = staticmethod( + CustomerLifecycleGoalServiceClient.parse_customer_path + ) + customer_lifecycle_goal_path = staticmethod( + CustomerLifecycleGoalServiceClient.customer_lifecycle_goal_path + ) + parse_customer_lifecycle_goal_path = staticmethod( + CustomerLifecycleGoalServiceClient.parse_customer_lifecycle_goal_path + ) + common_billing_account_path = staticmethod( + CustomerLifecycleGoalServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomerLifecycleGoalServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomerLifecycleGoalServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomerLifecycleGoalServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomerLifecycleGoalServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomerLifecycleGoalServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomerLifecycleGoalServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomerLifecycleGoalServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomerLifecycleGoalServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomerLifecycleGoalServiceClient.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: + CustomerLifecycleGoalServiceAsyncClient: The constructed client. + """ + return CustomerLifecycleGoalServiceClient.from_service_account_info.__func__(CustomerLifecycleGoalServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomerLifecycleGoalServiceAsyncClient: The constructed client. + """ + return CustomerLifecycleGoalServiceClient.from_service_account_file.__func__(CustomerLifecycleGoalServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomerLifecycleGoalServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomerLifecycleGoalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerLifecycleGoalServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CustomerLifecycleGoalServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomerLifecycleGoalServiceTransport, + Callable[..., CustomerLifecycleGoalServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer lifecycle goal 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,CustomerLifecycleGoalServiceTransport,Callable[..., CustomerLifecycleGoalServiceTransport]]]): + 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 CustomerLifecycleGoalServiceTransport 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 = CustomerLifecycleGoalServiceClient( + 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.ads.googleads.v24.services.CustomerLifecycleGoalServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerLifecycleGoalService", + "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.ads.googleads.v24.services.CustomerLifecycleGoalService", + "credentialsType": None, + } + ), + ) + + async def configure_customer_lifecycle_goals( + self, + request: Optional[ + Union[ + customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[ + customer_lifecycle_goal_service.CustomerLifecycleGoalOperation + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsResponse + ): + r"""Process the given customer lifecycle configurations. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ + `CustomerLifecycleGoalConfigError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ConfigureCustomerLifecycleGoalsRequest, dict]]): + The request object. Request message for + [CustomerLifecycleGoalService.ConfigureCustomerLifecycleGoals][google.ads.googleads.v24.services.CustomerLifecycleGoalService.ConfigureCustomerLifecycleGoals]. + customer_id (:class:`str`): + Required. The ID of the customer + performing the upload. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (:class:`google.ads.googleads.v24.services.types.CustomerLifecycleGoalOperation`): + Required. The operation to perform + customer lifecycle goal update. + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.ConfigureCustomerLifecycleGoalsResponse: + Response message for + [CustomerLifecycleGoalService.ConfigureCustomerLifecycleGoals][google.ads.googleads.v24.services.CustomerLifecycleGoalService.ConfigureCustomerLifecycleGoals]. + + """ + # 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 = [customer_id, operation] + 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, + customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsRequest, + ): + request = customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.configure_customer_lifecycle_goals + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomerLifecycleGoalServiceAsyncClient": + 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__ = ("CustomerLifecycleGoalServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/client.py b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/client.py new file mode 100644 index 000000000..c915f2c7e --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/client.py @@ -0,0 +1,923 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + customer_lifecycle_goal_service, +) +from .transports.base import ( + CustomerLifecycleGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerLifecycleGoalServiceGrpcTransport +from .transports.grpc_asyncio import ( + CustomerLifecycleGoalServiceGrpcAsyncIOTransport, +) + + +class CustomerLifecycleGoalServiceClientMeta(type): + """Metaclass for the CustomerLifecycleGoalService 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[CustomerLifecycleGoalServiceTransport]] + _transport_registry["grpc"] = CustomerLifecycleGoalServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CustomerLifecycleGoalServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerLifecycleGoalServiceTransport]: + """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 CustomerLifecycleGoalServiceClient( + metaclass=CustomerLifecycleGoalServiceClientMeta +): + """Service to configure customer lifecycle goals.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomerLifecycleGoalServiceClient: 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: + CustomerLifecycleGoalServiceClient: 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) -> CustomerLifecycleGoalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerLifecycleGoalServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def customer_lifecycle_goal_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer_lifecycle_goal string.""" + return "customers/{customer_id}/customerLifecycleGoals".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_lifecycle_goal_path(path: str) -> Dict[str, str]: + """Parses a customer_lifecycle_goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerLifecycleGoals$", 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 = ( + CustomerLifecycleGoalServiceClient._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 = ( + CustomerLifecycleGoalServiceClient._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 + ): + """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 = ( + CustomerLifecycleGoalServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + CustomerLifecycleGoalServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = CustomerLifecycleGoalServiceClient._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 = CustomerLifecycleGoalServiceClient._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): + """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, + CustomerLifecycleGoalServiceTransport, + Callable[..., CustomerLifecycleGoalServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer lifecycle goal 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,CustomerLifecycleGoalServiceTransport,Callable[..., CustomerLifecycleGoalServiceTransport]]]): + 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 CustomerLifecycleGoalServiceTransport 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, + ) = CustomerLifecycleGoalServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomerLifecycleGoalServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CustomerLifecycleGoalServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomerLifecycleGoalServiceTransport + ) + if transport_provided: + # transport is a CustomerLifecycleGoalServiceTransport 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( + CustomerLifecycleGoalServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomerLifecycleGoalServiceClient._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[CustomerLifecycleGoalServiceTransport], + Callable[..., CustomerLifecycleGoalServiceTransport], + ] = ( + CustomerLifecycleGoalServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomerLifecycleGoalServiceTransport], + 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.ads.googleads.v24.services.CustomerLifecycleGoalServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerLifecycleGoalService", + "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.ads.googleads.v24.services.CustomerLifecycleGoalService", + "credentialsType": None, + } + ), + ) + + def configure_customer_lifecycle_goals( + self, + request: Optional[ + Union[ + customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[ + customer_lifecycle_goal_service.CustomerLifecycleGoalOperation + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsResponse + ): + r"""Process the given customer lifecycle configurations. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ + `CustomerLifecycleGoalConfigError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ConfigureCustomerLifecycleGoalsRequest, dict]): + The request object. Request message for + [CustomerLifecycleGoalService.ConfigureCustomerLifecycleGoals][google.ads.googleads.v24.services.CustomerLifecycleGoalService.ConfigureCustomerLifecycleGoals]. + customer_id (str): + Required. The ID of the customer + performing the upload. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (google.ads.googleads.v24.services.types.CustomerLifecycleGoalOperation): + Required. The operation to perform + customer lifecycle goal update. + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.ConfigureCustomerLifecycleGoalsResponse: + Response message for + [CustomerLifecycleGoalService.ConfigureCustomerLifecycleGoals][google.ads.googleads.v24.services.CustomerLifecycleGoalService.ConfigureCustomerLifecycleGoals]. + + """ + # 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 = [customer_id, operation] + 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, + customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsRequest, + ): + request = customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.configure_customer_lifecycle_goals + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomerLifecycleGoalServiceClient": + 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() + + +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__ = ("CustomerLifecycleGoalServiceClient",) diff --git a/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/README.rst b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/README.rst new file mode 100644 index 000000000..690454b68 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomerLifecycleGoalServiceTransport` is the ABC for all transports. +- public child `CustomerLifecycleGoalServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomerLifecycleGoalServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomerLifecycleGoalServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomerLifecycleGoalServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/__init__.py b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/__init__.py new file mode 100644 index 000000000..9a249d1b4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomerLifecycleGoalServiceTransport +from .grpc import CustomerLifecycleGoalServiceGrpcTransport +from .grpc_asyncio import CustomerLifecycleGoalServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerLifecycleGoalServiceTransport]] +_transport_registry["grpc"] = CustomerLifecycleGoalServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CustomerLifecycleGoalServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CustomerLifecycleGoalServiceTransport", + "CustomerLifecycleGoalServiceGrpcTransport", + "CustomerLifecycleGoalServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/base.py b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/base.py new file mode 100644 index 000000000..5cf1a3a34 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + customer_lifecycle_goal_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 CustomerLifecycleGoalServiceTransport(abc.ABC): + """Abstract transport class for CustomerLifecycleGoalService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.configure_customer_lifecycle_goals: gapic_v1.method.wrap_method( + self.configure_customer_lifecycle_goals, + 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 configure_customer_lifecycle_goals( + self, + ) -> Callable[ + [ + customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsRequest + ], + Union[ + customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsResponse, + Awaitable[ + customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomerLifecycleGoalServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/grpc.py b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/grpc.py new file mode 100644 index 000000000..70f10200a --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/grpc.py @@ -0,0 +1,395 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + customer_lifecycle_goal_service, +) +from .base import CustomerLifecycleGoalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerLifecycleGoalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerLifecycleGoalService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerLifecycleGoalServiceGrpcTransport( + CustomerLifecycleGoalServiceTransport +): + """gRPC backend transport for CustomerLifecycleGoalService. + + Service to configure customer lifecycle goals. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 configure_customer_lifecycle_goals( + self, + ) -> Callable[ + [ + customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsRequest + ], + customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsResponse, + ]: + r"""Return a callable for the configure customer lifecycle + goals method over gRPC. + + Process the given customer lifecycle configurations. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ + `CustomerLifecycleGoalConfigError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ConfigureCustomerLifecycleGoalsRequest], + ~.ConfigureCustomerLifecycleGoalsResponse]: + 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 "configure_customer_lifecycle_goals" not in self._stubs: + self._stubs["configure_customer_lifecycle_goals"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerLifecycleGoalService/ConfigureCustomerLifecycleGoals", + request_serializer=customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsRequest.serialize, + response_deserializer=customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsResponse.deserialize, + ) + ) + return self._stubs["configure_customer_lifecycle_goals"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomerLifecycleGoalServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..be436f2a6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_lifecycle_goal_service/transports/grpc_asyncio.py @@ -0,0 +1,418 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + customer_lifecycle_goal_service, +) +from .base import CustomerLifecycleGoalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerLifecycleGoalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerLifecycleGoalService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerLifecycleGoalServiceGrpcAsyncIOTransport( + CustomerLifecycleGoalServiceTransport +): + """gRPC AsyncIO backend transport for CustomerLifecycleGoalService. + + Service to configure customer lifecycle goals. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 configure_customer_lifecycle_goals( + self, + ) -> Callable[ + [ + customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsRequest + ], + Awaitable[ + customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsResponse + ], + ]: + r"""Return a callable for the configure customer lifecycle + goals method over gRPC. + + Process the given customer lifecycle configurations. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ + `CustomerLifecycleGoalConfigError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ConfigureCustomerLifecycleGoalsRequest], + Awaitable[~.ConfigureCustomerLifecycleGoalsResponse]]: + 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 "configure_customer_lifecycle_goals" not in self._stubs: + self._stubs["configure_customer_lifecycle_goals"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerLifecycleGoalService/ConfigureCustomerLifecycleGoals", + request_serializer=customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsRequest.serialize, + response_deserializer=customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsResponse.deserialize, + ) + ) + return self._stubs["configure_customer_lifecycle_goals"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.configure_customer_lifecycle_goals: self._wrap_method( + self.configure_customer_lifecycle_goals, + 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" + + +__all__ = ("CustomerLifecycleGoalServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_manager_link_service/__init__.py b/google/ads/googleads/v24/services/services/customer_manager_link_service/__init__.py new file mode 100644 index 000000000..c96c89cde --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_manager_link_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomerManagerLinkServiceClient +from .async_client import CustomerManagerLinkServiceAsyncClient + +__all__ = ( + "CustomerManagerLinkServiceClient", + "CustomerManagerLinkServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/customer_manager_link_service/async_client.py b/google/ads/googleads/v24/services/services/customer_manager_link_service/async_client.py new file mode 100644 index 000000000..545d8c43d --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_manager_link_service/async_client.py @@ -0,0 +1,576 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + customer_manager_link_service, +) +from .transports.base import ( + CustomerManagerLinkServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CustomerManagerLinkServiceClient + +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 CustomerManagerLinkServiceAsyncClient: + """Service to manage customer-manager links.""" + + _client: CustomerManagerLinkServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomerManagerLinkServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + CustomerManagerLinkServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomerManagerLinkServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomerManagerLinkServiceClient._DEFAULT_UNIVERSE + + customer_path = staticmethod(CustomerManagerLinkServiceClient.customer_path) + parse_customer_path = staticmethod( + CustomerManagerLinkServiceClient.parse_customer_path + ) + customer_manager_link_path = staticmethod( + CustomerManagerLinkServiceClient.customer_manager_link_path + ) + parse_customer_manager_link_path = staticmethod( + CustomerManagerLinkServiceClient.parse_customer_manager_link_path + ) + common_billing_account_path = staticmethod( + CustomerManagerLinkServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomerManagerLinkServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomerManagerLinkServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomerManagerLinkServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomerManagerLinkServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomerManagerLinkServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomerManagerLinkServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomerManagerLinkServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomerManagerLinkServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomerManagerLinkServiceClient.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: + CustomerManagerLinkServiceAsyncClient: The constructed client. + """ + return CustomerManagerLinkServiceClient.from_service_account_info.__func__(CustomerManagerLinkServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomerManagerLinkServiceAsyncClient: The constructed client. + """ + return CustomerManagerLinkServiceClient.from_service_account_file.__func__(CustomerManagerLinkServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomerManagerLinkServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomerManagerLinkServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerManagerLinkServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CustomerManagerLinkServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomerManagerLinkServiceTransport, + Callable[..., CustomerManagerLinkServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer manager link 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,CustomerManagerLinkServiceTransport,Callable[..., CustomerManagerLinkServiceTransport]]]): + 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 CustomerManagerLinkServiceTransport 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 = CustomerManagerLinkServiceClient( + 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.ads.googleads.v24.services.CustomerManagerLinkServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerManagerLinkService", + "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.ads.googleads.v24.services.CustomerManagerLinkService", + "credentialsType": None, + } + ), + ) + + async def mutate_customer_manager_link( + self, + request: Optional[ + Union[ + customer_manager_link_service.MutateCustomerManagerLinkRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + customer_manager_link_service.CustomerManagerLinkOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_manager_link_service.MutateCustomerManagerLinkResponse: + r"""Updates customer manager links. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `ManagerLinkError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomerManagerLinkRequest, dict]]): + The request object. Request message for + [CustomerManagerLinkService.MutateCustomerManagerLink][google.ads.googleads.v24.services.CustomerManagerLinkService.MutateCustomerManagerLink]. + customer_id (:class:`str`): + Required. The ID of the customer + whose customer manager links are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CustomerManagerLinkOperation]`): + Required. The list of operations to + perform on individual customer manager + links. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomerManagerLinkResponse: + Response message for a + CustomerManagerLink mutate. + + """ + # 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 = [customer_id, operations] + 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, + customer_manager_link_service.MutateCustomerManagerLinkRequest, + ): + request = ( + customer_manager_link_service.MutateCustomerManagerLinkRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_customer_manager_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 move_manager_link( + self, + request: Optional[ + Union[customer_manager_link_service.MoveManagerLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + previous_customer_manager_link: Optional[str] = None, + new_manager: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_manager_link_service.MoveManagerLinkResponse: + r"""Moves a client customer to a new manager customer. This + simplifies the complex request that requires two operations to + move a client customer to a new manager, for example: + + 1. Update operation with Status INACTIVE (previous manager) and, + 2. Update operation with Status ACTIVE (new manager). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MoveManagerLinkRequest, dict]]): + The request object. Request message for + [CustomerManagerLinkService.MoveManagerLink][google.ads.googleads.v24.services.CustomerManagerLinkService.MoveManagerLink]. + customer_id (:class:`str`): + Required. The ID of the client + customer that is being moved. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + previous_customer_manager_link (:class:`str`): + Required. The resource name of the previous + CustomerManagerLink. The resource name has the form: + ``customers/{customer_id}/customerManagerLinks/{manager_customer_id}~{manager_link_id}`` + + This corresponds to the ``previous_customer_manager_link`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + new_manager (:class:`str`): + Required. The resource name of the new manager customer + that the client wants to move to. Customer resource + names have the format: "customers/{customer_id}" + + This corresponds to the ``new_manager`` 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.ads.googleads.v24.services.types.MoveManagerLinkResponse: + Response message for a + CustomerManagerLink moveManagerLink. + + """ + # 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 = [ + customer_id, + previous_customer_manager_link, + new_manager, + ] + 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, customer_manager_link_service.MoveManagerLinkRequest + ): + request = customer_manager_link_service.MoveManagerLinkRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if previous_customer_manager_link is not None: + request.previous_customer_manager_link = ( + previous_customer_manager_link + ) + if new_manager is not None: + request.new_manager = new_manager + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.move_manager_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomerManagerLinkServiceAsyncClient": + 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__ = ("CustomerManagerLinkServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/customer_manager_link_service/client.py b/google/ads/googleads/v24/services/services/customer_manager_link_service/client.py new file mode 100644 index 000000000..58e556475 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_manager_link_service/client.py @@ -0,0 +1,1071 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + customer_manager_link_service, +) +from .transports.base import ( + CustomerManagerLinkServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerManagerLinkServiceGrpcTransport +from .transports.grpc_asyncio import ( + CustomerManagerLinkServiceGrpcAsyncIOTransport, +) + + +class CustomerManagerLinkServiceClientMeta(type): + """Metaclass for the CustomerManagerLinkService 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[CustomerManagerLinkServiceTransport]] + _transport_registry["grpc"] = CustomerManagerLinkServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CustomerManagerLinkServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerManagerLinkServiceTransport]: + """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 CustomerManagerLinkServiceClient( + metaclass=CustomerManagerLinkServiceClientMeta +): + """Service to manage customer-manager links.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomerManagerLinkServiceClient: 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: + CustomerManagerLinkServiceClient: 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) -> CustomerManagerLinkServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerManagerLinkServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def customer_manager_link_path( + customer_id: str, + manager_customer_id: str, + manager_link_id: str, + ) -> str: + """Returns a fully-qualified customer_manager_link string.""" + return "customers/{customer_id}/customerManagerLinks/{manager_customer_id}~{manager_link_id}".format( + customer_id=customer_id, + manager_customer_id=manager_customer_id, + manager_link_id=manager_link_id, + ) + + @staticmethod + def parse_customer_manager_link_path(path: str) -> Dict[str, str]: + """Parses a customer_manager_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerManagerLinks/(?P.+?)~(?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 = ( + CustomerManagerLinkServiceClient._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 = ( + CustomerManagerLinkServiceClient._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 + ): + """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 = ( + CustomerManagerLinkServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + CustomerManagerLinkServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = CustomerManagerLinkServiceClient._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 = CustomerManagerLinkServiceClient._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): + """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, + CustomerManagerLinkServiceTransport, + Callable[..., CustomerManagerLinkServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer manager link 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,CustomerManagerLinkServiceTransport,Callable[..., CustomerManagerLinkServiceTransport]]]): + 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 CustomerManagerLinkServiceTransport 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, + ) = CustomerManagerLinkServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomerManagerLinkServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CustomerManagerLinkServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomerManagerLinkServiceTransport + ) + if transport_provided: + # transport is a CustomerManagerLinkServiceTransport 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( + CustomerManagerLinkServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomerManagerLinkServiceClient._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[CustomerManagerLinkServiceTransport], + Callable[..., CustomerManagerLinkServiceTransport], + ] = ( + CustomerManagerLinkServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomerManagerLinkServiceTransport], + 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.ads.googleads.v24.services.CustomerManagerLinkServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerManagerLinkService", + "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.ads.googleads.v24.services.CustomerManagerLinkService", + "credentialsType": None, + } + ), + ) + + def mutate_customer_manager_link( + self, + request: Optional[ + Union[ + customer_manager_link_service.MutateCustomerManagerLinkRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + customer_manager_link_service.CustomerManagerLinkOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_manager_link_service.MutateCustomerManagerLinkResponse: + r"""Updates customer manager links. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `ManagerLinkError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomerManagerLinkRequest, dict]): + The request object. Request message for + [CustomerManagerLinkService.MutateCustomerManagerLink][google.ads.googleads.v24.services.CustomerManagerLinkService.MutateCustomerManagerLink]. + customer_id (str): + Required. The ID of the customer + whose customer manager links are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomerManagerLinkOperation]): + Required. The list of operations to + perform on individual customer manager + links. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomerManagerLinkResponse: + Response message for a + CustomerManagerLink mutate. + + """ + # 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 = [customer_id, operations] + 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, + customer_manager_link_service.MutateCustomerManagerLinkRequest, + ): + request = ( + customer_manager_link_service.MutateCustomerManagerLinkRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_customer_manager_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 move_manager_link( + self, + request: Optional[ + Union[customer_manager_link_service.MoveManagerLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + previous_customer_manager_link: Optional[str] = None, + new_manager: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_manager_link_service.MoveManagerLinkResponse: + r"""Moves a client customer to a new manager customer. This + simplifies the complex request that requires two operations to + move a client customer to a new manager, for example: + + 1. Update operation with Status INACTIVE (previous manager) and, + 2. Update operation with Status ACTIVE (new manager). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MoveManagerLinkRequest, dict]): + The request object. Request message for + [CustomerManagerLinkService.MoveManagerLink][google.ads.googleads.v24.services.CustomerManagerLinkService.MoveManagerLink]. + customer_id (str): + Required. The ID of the client + customer that is being moved. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + previous_customer_manager_link (str): + Required. The resource name of the previous + CustomerManagerLink. The resource name has the form: + ``customers/{customer_id}/customerManagerLinks/{manager_customer_id}~{manager_link_id}`` + + This corresponds to the ``previous_customer_manager_link`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + new_manager (str): + Required. The resource name of the new manager customer + that the client wants to move to. Customer resource + names have the format: "customers/{customer_id}" + + This corresponds to the ``new_manager`` 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.ads.googleads.v24.services.types.MoveManagerLinkResponse: + Response message for a + CustomerManagerLink moveManagerLink. + + """ + # 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 = [ + customer_id, + previous_customer_manager_link, + new_manager, + ] + 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, customer_manager_link_service.MoveManagerLinkRequest + ): + request = customer_manager_link_service.MoveManagerLinkRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if previous_customer_manager_link is not None: + request.previous_customer_manager_link = ( + previous_customer_manager_link + ) + if new_manager is not None: + request.new_manager = new_manager + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.move_manager_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomerManagerLinkServiceClient": + 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() + + +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__ = ("CustomerManagerLinkServiceClient",) diff --git a/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/README.rst b/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/README.rst new file mode 100644 index 000000000..c1a5fdef7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomerManagerLinkServiceTransport` is the ABC for all transports. +- public child `CustomerManagerLinkServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomerManagerLinkServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomerManagerLinkServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomerManagerLinkServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/__init__.py b/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/__init__.py new file mode 100644 index 000000000..8e060267b --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomerManagerLinkServiceTransport +from .grpc import CustomerManagerLinkServiceGrpcTransport +from .grpc_asyncio import CustomerManagerLinkServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerManagerLinkServiceTransport]] +_transport_registry["grpc"] = CustomerManagerLinkServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CustomerManagerLinkServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CustomerManagerLinkServiceTransport", + "CustomerManagerLinkServiceGrpcTransport", + "CustomerManagerLinkServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/base.py b/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/base.py new file mode 100644 index 000000000..ebdd98e1c --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/base.py @@ -0,0 +1,194 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + customer_manager_link_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 CustomerManagerLinkServiceTransport(abc.ABC): + """Abstract transport class for CustomerManagerLinkService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customer_manager_link: gapic_v1.method.wrap_method( + self.mutate_customer_manager_link, + default_timeout=None, + client_info=client_info, + ), + self.move_manager_link: gapic_v1.method.wrap_method( + self.move_manager_link, + 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 mutate_customer_manager_link( + self, + ) -> Callable[ + [customer_manager_link_service.MutateCustomerManagerLinkRequest], + Union[ + customer_manager_link_service.MutateCustomerManagerLinkResponse, + Awaitable[ + customer_manager_link_service.MutateCustomerManagerLinkResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def move_manager_link( + self, + ) -> Callable[ + [customer_manager_link_service.MoveManagerLinkRequest], + Union[ + customer_manager_link_service.MoveManagerLinkResponse, + Awaitable[customer_manager_link_service.MoveManagerLinkResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomerManagerLinkServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/grpc.py b/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/grpc.py new file mode 100644 index 000000000..e23b02532 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/grpc.py @@ -0,0 +1,432 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + customer_manager_link_service, +) +from .base import CustomerManagerLinkServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerManagerLinkService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerManagerLinkService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerManagerLinkServiceGrpcTransport( + CustomerManagerLinkServiceTransport +): + """gRPC backend transport for CustomerManagerLinkService. + + Service to manage customer-manager links. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_customer_manager_link( + self, + ) -> Callable[ + [customer_manager_link_service.MutateCustomerManagerLinkRequest], + customer_manager_link_service.MutateCustomerManagerLinkResponse, + ]: + r"""Return a callable for the mutate customer manager link method over gRPC. + + Updates customer manager links. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `ManagerLinkError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomerManagerLinkRequest], + ~.MutateCustomerManagerLinkResponse]: + 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 "mutate_customer_manager_link" not in self._stubs: + self._stubs["mutate_customer_manager_link"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerManagerLinkService/MutateCustomerManagerLink", + request_serializer=customer_manager_link_service.MutateCustomerManagerLinkRequest.serialize, + response_deserializer=customer_manager_link_service.MutateCustomerManagerLinkResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_manager_link"] + + @property + def move_manager_link( + self, + ) -> Callable[ + [customer_manager_link_service.MoveManagerLinkRequest], + customer_manager_link_service.MoveManagerLinkResponse, + ]: + r"""Return a callable for the move manager link method over gRPC. + + Moves a client customer to a new manager customer. This + simplifies the complex request that requires two operations to + move a client customer to a new manager, for example: + + 1. Update operation with Status INACTIVE (previous manager) and, + 2. Update operation with Status ACTIVE (new manager). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MoveManagerLinkRequest], + ~.MoveManagerLinkResponse]: + 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 "move_manager_link" not in self._stubs: + self._stubs["move_manager_link"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerManagerLinkService/MoveManagerLink", + request_serializer=customer_manager_link_service.MoveManagerLinkRequest.serialize, + response_deserializer=customer_manager_link_service.MoveManagerLinkResponse.deserialize, + ) + return self._stubs["move_manager_link"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomerManagerLinkServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..1a69b0f82 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_manager_link_service/transports/grpc_asyncio.py @@ -0,0 +1,460 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + customer_manager_link_service, +) +from .base import CustomerManagerLinkServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerManagerLinkService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerManagerLinkService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerManagerLinkServiceGrpcAsyncIOTransport( + CustomerManagerLinkServiceTransport +): + """gRPC AsyncIO backend transport for CustomerManagerLinkService. + + Service to manage customer-manager links. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_customer_manager_link( + self, + ) -> Callable[ + [customer_manager_link_service.MutateCustomerManagerLinkRequest], + Awaitable[ + customer_manager_link_service.MutateCustomerManagerLinkResponse + ], + ]: + r"""Return a callable for the mutate customer manager link method over gRPC. + + Updates customer manager links. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `ManagerLinkError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomerManagerLinkRequest], + Awaitable[~.MutateCustomerManagerLinkResponse]]: + 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 "mutate_customer_manager_link" not in self._stubs: + self._stubs["mutate_customer_manager_link"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerManagerLinkService/MutateCustomerManagerLink", + request_serializer=customer_manager_link_service.MutateCustomerManagerLinkRequest.serialize, + response_deserializer=customer_manager_link_service.MutateCustomerManagerLinkResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_manager_link"] + + @property + def move_manager_link( + self, + ) -> Callable[ + [customer_manager_link_service.MoveManagerLinkRequest], + Awaitable[customer_manager_link_service.MoveManagerLinkResponse], + ]: + r"""Return a callable for the move manager link method over gRPC. + + Moves a client customer to a new manager customer. This + simplifies the complex request that requires two operations to + move a client customer to a new manager, for example: + + 1. Update operation with Status INACTIVE (previous manager) and, + 2. Update operation with Status ACTIVE (new manager). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MoveManagerLinkRequest], + Awaitable[~.MoveManagerLinkResponse]]: + 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 "move_manager_link" not in self._stubs: + self._stubs["move_manager_link"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerManagerLinkService/MoveManagerLink", + request_serializer=customer_manager_link_service.MoveManagerLinkRequest.serialize, + response_deserializer=customer_manager_link_service.MoveManagerLinkResponse.deserialize, + ) + return self._stubs["move_manager_link"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_customer_manager_link: self._wrap_method( + self.mutate_customer_manager_link, + default_timeout=None, + client_info=client_info, + ), + self.move_manager_link: self._wrap_method( + self.move_manager_link, + 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" + + +__all__ = ("CustomerManagerLinkServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_negative_criterion_service/__init__.py b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/__init__.py new file mode 100644 index 000000000..5039f942d --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomerNegativeCriterionServiceClient +from .async_client import CustomerNegativeCriterionServiceAsyncClient + +__all__ = ( + "CustomerNegativeCriterionServiceClient", + "CustomerNegativeCriterionServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/customer_negative_criterion_service/async_client.py b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/async_client.py new file mode 100644 index 000000000..d69159492 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/async_client.py @@ -0,0 +1,448 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + customer_negative_criterion_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CustomerNegativeCriterionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CustomerNegativeCriterionServiceClient + +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 CustomerNegativeCriterionServiceAsyncClient: + """Service to manage customer negative criteria.""" + + _client: CustomerNegativeCriterionServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomerNegativeCriterionServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + CustomerNegativeCriterionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomerNegativeCriterionServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomerNegativeCriterionServiceClient._DEFAULT_UNIVERSE + + customer_negative_criterion_path = staticmethod( + CustomerNegativeCriterionServiceClient.customer_negative_criterion_path + ) + parse_customer_negative_criterion_path = staticmethod( + CustomerNegativeCriterionServiceClient.parse_customer_negative_criterion_path + ) + mobile_app_category_constant_path = staticmethod( + CustomerNegativeCriterionServiceClient.mobile_app_category_constant_path + ) + parse_mobile_app_category_constant_path = staticmethod( + CustomerNegativeCriterionServiceClient.parse_mobile_app_category_constant_path + ) + common_billing_account_path = staticmethod( + CustomerNegativeCriterionServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomerNegativeCriterionServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomerNegativeCriterionServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomerNegativeCriterionServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomerNegativeCriterionServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomerNegativeCriterionServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomerNegativeCriterionServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomerNegativeCriterionServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomerNegativeCriterionServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomerNegativeCriterionServiceClient.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: + CustomerNegativeCriterionServiceAsyncClient: The constructed client. + """ + return CustomerNegativeCriterionServiceClient.from_service_account_info.__func__(CustomerNegativeCriterionServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomerNegativeCriterionServiceAsyncClient: The constructed client. + """ + return CustomerNegativeCriterionServiceClient.from_service_account_file.__func__(CustomerNegativeCriterionServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomerNegativeCriterionServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomerNegativeCriterionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerNegativeCriterionServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + CustomerNegativeCriterionServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomerNegativeCriterionServiceTransport, + Callable[..., CustomerNegativeCriterionServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer negative criterion 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,CustomerNegativeCriterionServiceTransport,Callable[..., CustomerNegativeCriterionServiceTransport]]]): + 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 CustomerNegativeCriterionServiceTransport 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 = CustomerNegativeCriterionServiceClient( + 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.ads.googleads.v24.services.CustomerNegativeCriterionServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerNegativeCriterionService", + "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.ads.googleads.v24.services.CustomerNegativeCriterionService", + "credentialsType": None, + } + ), + ) + + async def mutate_customer_negative_criteria( + self, + request: Optional[ + Union[ + customer_negative_criterion_service.MutateCustomerNegativeCriteriaRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + customer_negative_criterion_service.CustomerNegativeCriterionOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + customer_negative_criterion_service.MutateCustomerNegativeCriteriaResponse + ): + r"""Creates or removes criteria. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CriterionError <>`__ + `DatabaseError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomerNegativeCriteriaRequest, dict]]): + The request object. Request message for + [CustomerNegativeCriterionService.MutateCustomerNegativeCriteria][google.ads.googleads.v24.services.CustomerNegativeCriterionService.MutateCustomerNegativeCriteria]. + customer_id (:class:`str`): + Required. The ID of the customer + whose criteria are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CustomerNegativeCriterionOperation]`): + Required. The list of operations to + perform on individual criteria. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomerNegativeCriteriaResponse: + Response message for customer + negative criterion mutate. + + """ + # 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 = [customer_id, operations] + 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, + customer_negative_criterion_service.MutateCustomerNegativeCriteriaRequest, + ): + request = customer_negative_criterion_service.MutateCustomerNegativeCriteriaRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_customer_negative_criteria + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomerNegativeCriterionServiceAsyncClient": + 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__ = ("CustomerNegativeCriterionServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/customer_negative_criterion_service/client.py b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/client.py new file mode 100644 index 000000000..e64906c44 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/client.py @@ -0,0 +1,945 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + customer_negative_criterion_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CustomerNegativeCriterionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerNegativeCriterionServiceGrpcTransport +from .transports.grpc_asyncio import ( + CustomerNegativeCriterionServiceGrpcAsyncIOTransport, +) + + +class CustomerNegativeCriterionServiceClientMeta(type): + """Metaclass for the CustomerNegativeCriterionService 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[CustomerNegativeCriterionServiceTransport]] + _transport_registry["grpc"] = CustomerNegativeCriterionServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CustomerNegativeCriterionServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerNegativeCriterionServiceTransport]: + """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 CustomerNegativeCriterionServiceClient( + metaclass=CustomerNegativeCriterionServiceClientMeta +): + """Service to manage customer negative criteria.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomerNegativeCriterionServiceClient: 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: + CustomerNegativeCriterionServiceClient: 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) -> CustomerNegativeCriterionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerNegativeCriterionServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customer_negative_criterion_path( + customer_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified customer_negative_criterion string.""" + return "customers/{customer_id}/customerNegativeCriteria/{criterion_id}".format( + customer_id=customer_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_customer_negative_criterion_path(path: str) -> Dict[str, str]: + """Parses a customer_negative_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerNegativeCriteria/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def mobile_app_category_constant_path( + mobile_app_category_id: str, + ) -> str: + """Returns a fully-qualified mobile_app_category_constant string.""" + return "mobileAppCategoryConstants/{mobile_app_category_id}".format( + mobile_app_category_id=mobile_app_category_id, + ) + + @staticmethod + def parse_mobile_app_category_constant_path(path: str) -> Dict[str, str]: + """Parses a mobile_app_category_constant path into its component segments.""" + m = re.match( + r"^mobileAppCategoryConstants/(?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 = ( + CustomerNegativeCriterionServiceClient._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 = ( + CustomerNegativeCriterionServiceClient._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 + ): + """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 = ( + CustomerNegativeCriterionServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + CustomerNegativeCriterionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = CustomerNegativeCriterionServiceClient._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 = ( + CustomerNegativeCriterionServiceClient._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): + """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, + CustomerNegativeCriterionServiceTransport, + Callable[..., CustomerNegativeCriterionServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer negative criterion 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,CustomerNegativeCriterionServiceTransport,Callable[..., CustomerNegativeCriterionServiceTransport]]]): + 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 CustomerNegativeCriterionServiceTransport 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, + ) = CustomerNegativeCriterionServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomerNegativeCriterionServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CustomerNegativeCriterionServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomerNegativeCriterionServiceTransport + ) + if transport_provided: + # transport is a CustomerNegativeCriterionServiceTransport 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( + CustomerNegativeCriterionServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomerNegativeCriterionServiceClient._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[CustomerNegativeCriterionServiceTransport], + Callable[..., CustomerNegativeCriterionServiceTransport], + ] = ( + CustomerNegativeCriterionServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomerNegativeCriterionServiceTransport], + 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.ads.googleads.v24.services.CustomerNegativeCriterionServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerNegativeCriterionService", + "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.ads.googleads.v24.services.CustomerNegativeCriterionService", + "credentialsType": None, + } + ), + ) + + def mutate_customer_negative_criteria( + self, + request: Optional[ + Union[ + customer_negative_criterion_service.MutateCustomerNegativeCriteriaRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + customer_negative_criterion_service.CustomerNegativeCriterionOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + customer_negative_criterion_service.MutateCustomerNegativeCriteriaResponse + ): + r"""Creates or removes criteria. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CriterionError <>`__ + `DatabaseError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomerNegativeCriteriaRequest, dict]): + The request object. Request message for + [CustomerNegativeCriterionService.MutateCustomerNegativeCriteria][google.ads.googleads.v24.services.CustomerNegativeCriterionService.MutateCustomerNegativeCriteria]. + customer_id (str): + Required. The ID of the customer + whose criteria are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomerNegativeCriterionOperation]): + Required. The list of operations to + perform on individual criteria. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomerNegativeCriteriaResponse: + Response message for customer + negative criterion mutate. + + """ + # 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 = [customer_id, operations] + 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, + customer_negative_criterion_service.MutateCustomerNegativeCriteriaRequest, + ): + request = customer_negative_criterion_service.MutateCustomerNegativeCriteriaRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_customer_negative_criteria + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomerNegativeCriterionServiceClient": + 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() + + +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__ = ("CustomerNegativeCriterionServiceClient",) diff --git a/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/README.rst b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/README.rst new file mode 100644 index 000000000..25e753897 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomerNegativeCriterionServiceTransport` is the ABC for all transports. +- public child `CustomerNegativeCriterionServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomerNegativeCriterionServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomerNegativeCriterionServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomerNegativeCriterionServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/__init__.py b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/__init__.py new file mode 100644 index 000000000..3bd9d8b90 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomerNegativeCriterionServiceTransport +from .grpc import CustomerNegativeCriterionServiceGrpcTransport +from .grpc_asyncio import CustomerNegativeCriterionServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerNegativeCriterionServiceTransport]] +_transport_registry["grpc"] = CustomerNegativeCriterionServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CustomerNegativeCriterionServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CustomerNegativeCriterionServiceTransport", + "CustomerNegativeCriterionServiceGrpcTransport", + "CustomerNegativeCriterionServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/base.py b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/base.py new file mode 100644 index 000000000..29aa972a3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + customer_negative_criterion_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 CustomerNegativeCriterionServiceTransport(abc.ABC): + """Abstract transport class for CustomerNegativeCriterionService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customer_negative_criteria: gapic_v1.method.wrap_method( + self.mutate_customer_negative_criteria, + 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 mutate_customer_negative_criteria( + self, + ) -> Callable[ + [ + customer_negative_criterion_service.MutateCustomerNegativeCriteriaRequest + ], + Union[ + customer_negative_criterion_service.MutateCustomerNegativeCriteriaResponse, + Awaitable[ + customer_negative_criterion_service.MutateCustomerNegativeCriteriaResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomerNegativeCriterionServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/grpc.py b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/grpc.py new file mode 100644 index 000000000..271bc005d --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/grpc.py @@ -0,0 +1,396 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + customer_negative_criterion_service, +) +from .base import CustomerNegativeCriterionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerNegativeCriterionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerNegativeCriterionService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerNegativeCriterionServiceGrpcTransport( + CustomerNegativeCriterionServiceTransport +): + """gRPC backend transport for CustomerNegativeCriterionService. + + Service to manage customer negative criteria. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_customer_negative_criteria( + self, + ) -> Callable[ + [ + customer_negative_criterion_service.MutateCustomerNegativeCriteriaRequest + ], + customer_negative_criterion_service.MutateCustomerNegativeCriteriaResponse, + ]: + r"""Return a callable for the mutate customer negative + criteria method over gRPC. + + Creates or removes criteria. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CriterionError <>`__ + `DatabaseError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomerNegativeCriteriaRequest], + ~.MutateCustomerNegativeCriteriaResponse]: + 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 "mutate_customer_negative_criteria" not in self._stubs: + self._stubs["mutate_customer_negative_criteria"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerNegativeCriterionService/MutateCustomerNegativeCriteria", + request_serializer=customer_negative_criterion_service.MutateCustomerNegativeCriteriaRequest.serialize, + response_deserializer=customer_negative_criterion_service.MutateCustomerNegativeCriteriaResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_negative_criteria"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomerNegativeCriterionServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..91c648f62 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_negative_criterion_service/transports/grpc_asyncio.py @@ -0,0 +1,419 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + customer_negative_criterion_service, +) +from .base import CustomerNegativeCriterionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerNegativeCriterionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerNegativeCriterionService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerNegativeCriterionServiceGrpcAsyncIOTransport( + CustomerNegativeCriterionServiceTransport +): + """gRPC AsyncIO backend transport for CustomerNegativeCriterionService. + + Service to manage customer negative criteria. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_customer_negative_criteria( + self, + ) -> Callable[ + [ + customer_negative_criterion_service.MutateCustomerNegativeCriteriaRequest + ], + Awaitable[ + customer_negative_criterion_service.MutateCustomerNegativeCriteriaResponse + ], + ]: + r"""Return a callable for the mutate customer negative + criteria method over gRPC. + + Creates or removes criteria. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CriterionError <>`__ + `DatabaseError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomerNegativeCriteriaRequest], + Awaitable[~.MutateCustomerNegativeCriteriaResponse]]: + 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 "mutate_customer_negative_criteria" not in self._stubs: + self._stubs["mutate_customer_negative_criteria"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerNegativeCriterionService/MutateCustomerNegativeCriteria", + request_serializer=customer_negative_criterion_service.MutateCustomerNegativeCriteriaRequest.serialize, + response_deserializer=customer_negative_criterion_service.MutateCustomerNegativeCriteriaResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_negative_criteria"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_customer_negative_criteria: self._wrap_method( + self.mutate_customer_negative_criteria, + 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" + + +__all__ = ("CustomerNegativeCriterionServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_service/__init__.py b/google/ads/googleads/v24/services/services/customer_service/__init__.py new file mode 100644 index 000000000..472cff388 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomerServiceClient +from .async_client import CustomerServiceAsyncClient + +__all__ = ( + "CustomerServiceClient", + "CustomerServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/customer_service/async_client.py b/google/ads/googleads/v24/services/services/customer_service/async_client.py new file mode 100644 index 000000000..914533b9e --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_service/async_client.py @@ -0,0 +1,590 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.resources.types import customer +from google.ads.googleads.v24.services.types import customer_service +from .transports.base import CustomerServiceTransport, DEFAULT_CLIENT_INFO +from .client import CustomerServiceClient + +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 CustomerServiceAsyncClient: + """Service to manage customers.""" + + _client: CustomerServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomerServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = CustomerServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomerServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomerServiceClient._DEFAULT_UNIVERSE + + conversion_action_path = staticmethod( + CustomerServiceClient.conversion_action_path + ) + parse_conversion_action_path = staticmethod( + CustomerServiceClient.parse_conversion_action_path + ) + customer_path = staticmethod(CustomerServiceClient.customer_path) + parse_customer_path = staticmethod( + CustomerServiceClient.parse_customer_path + ) + common_billing_account_path = staticmethod( + CustomerServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomerServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(CustomerServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + CustomerServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomerServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomerServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomerServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomerServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomerServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomerServiceClient.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: + CustomerServiceAsyncClient: The constructed client. + """ + return CustomerServiceClient.from_service_account_info.__func__(CustomerServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomerServiceAsyncClient: The constructed client. + """ + return CustomerServiceClient.from_service_account_file.__func__(CustomerServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomerServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomerServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CustomerServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomerServiceTransport, + Callable[..., CustomerServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer 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,CustomerServiceTransport,Callable[..., CustomerServiceTransport]]]): + 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 CustomerServiceTransport 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 = CustomerServiceClient( + 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.ads.googleads.v24.services.CustomerServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerService", + "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.ads.googleads.v24.services.CustomerService", + "credentialsType": None, + } + ), + ) + + async def mutate_customer( + self, + request: Optional[ + Union[customer_service.MutateCustomerRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[customer_service.CustomerOperation] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_service.MutateCustomerResponse: + r"""Updates a customer. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RequestError <>`__ `UrlFieldError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomerRequest, dict]]): + The request object. Request message for + [CustomerService.MutateCustomer][google.ads.googleads.v24.services.CustomerService.MutateCustomer]. + customer_id (:class:`str`): + Required. The ID of the customer + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (:class:`google.ads.googleads.v24.services.types.CustomerOperation`): + Required. The operation to perform on + the customer + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateCustomerResponse: + Response message for customer mutate. + """ + # 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 = [customer_id, operation] + 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, customer_service.MutateCustomerRequest): + request = customer_service.MutateCustomerRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_customer + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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_accessible_customers( + self, + request: Optional[ + Union[customer_service.ListAccessibleCustomersRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_service.ListAccessibleCustomersResponse: + r"""Returns resource names of customers directly accessible by the + user authenticating the call. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListAccessibleCustomersRequest, dict]]): + The request object. Request message for + [CustomerService.ListAccessibleCustomers][google.ads.googleads.v24.services.CustomerService.ListAccessibleCustomers]. + 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.googleads.v24.services.types.ListAccessibleCustomersResponse: + Response message for + [CustomerService.ListAccessibleCustomers][google.ads.googleads.v24.services.CustomerService.ListAccessibleCustomers]. + + """ + # 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, customer_service.ListAccessibleCustomersRequest + ): + request = customer_service.ListAccessibleCustomersRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_accessible_customers + ] + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def create_customer_client( + self, + request: Optional[ + Union[customer_service.CreateCustomerClientRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + customer_client: Optional[customer.Customer] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_service.CreateCustomerClientResponse: + r"""Creates a new client under manager. The new client customer is + returned. + + List of thrown errors: `AccessInvitationError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CurrencyCodeError <>`__ `HeaderError <>`__ `InternalError <>`__ + `ManagerLinkError <>`__ `QuotaError <>`__ `RequestError <>`__ + `StringLengthError <>`__ `TimeZoneError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.CreateCustomerClientRequest, dict]]): + The request object. Request message for + [CustomerService.CreateCustomerClient][google.ads.googleads.v24.services.CustomerService.CreateCustomerClient]. + customer_id (:class:`str`): + Required. The ID of the Manager under + whom client customer is being created. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + customer_client (:class:`google.ads.googleads.v24.resources.types.Customer`): + Required. The new client customer to + create. The resource name on this + customer will be ignored. + + This corresponds to the ``customer_client`` 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.ads.googleads.v24.services.types.CreateCustomerClientResponse: + Response message for + CreateCustomerClient mutate. + + """ + # 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 = [customer_id, customer_client] + 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, customer_service.CreateCustomerClientRequest + ): + request = customer_service.CreateCustomerClientRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if customer_client is not None: + request.customer_client = customer_client + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.create_customer_client + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomerServiceAsyncClient": + 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__ = ("CustomerServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/customer_service/client.py b/google/ads/googleads/v24/services/services/customer_service/client.py new file mode 100644 index 000000000..9bfec6202 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_service/client.py @@ -0,0 +1,1054 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.resources.types import customer +from google.ads.googleads.v24.services.types import customer_service +from .transports.base import CustomerServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CustomerServiceGrpcTransport +from .transports.grpc_asyncio import CustomerServiceGrpcAsyncIOTransport + + +class CustomerServiceClientMeta(type): + """Metaclass for the CustomerService 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[CustomerServiceTransport]] + _transport_registry["grpc"] = CustomerServiceGrpcTransport + _transport_registry["grpc_asyncio"] = CustomerServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerServiceTransport]: + """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 CustomerServiceClient(metaclass=CustomerServiceClientMeta): + """Service to manage customers.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomerServiceClient: 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: + CustomerServiceClient: 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) -> CustomerServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def conversion_action_path( + customer_id: str, + conversion_action_id: str, + ) -> str: + """Returns a fully-qualified conversion_action string.""" + return "customers/{customer_id}/conversionActions/{conversion_action_id}".format( + customer_id=customer_id, + conversion_action_id=conversion_action_id, + ) + + @staticmethod + def parse_conversion_action_path(path: str) -> Dict[str, str]: + """Parses a conversion_action path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionActions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?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 = CustomerServiceClient._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 = CustomerServiceClient._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 + ): + """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 = CustomerServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CustomerServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + CustomerServiceClient._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 = CustomerServiceClient._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): + """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, + CustomerServiceTransport, + Callable[..., CustomerServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer 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,CustomerServiceTransport,Callable[..., CustomerServiceTransport]]]): + 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 CustomerServiceTransport 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, + ) = CustomerServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomerServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = CustomerServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomerServiceTransport) + if transport_provided: + # transport is a CustomerServiceTransport 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(CustomerServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomerServiceClient._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[CustomerServiceTransport], + Callable[..., CustomerServiceTransport], + ] = ( + CustomerServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., CustomerServiceTransport], 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.ads.googleads.v24.services.CustomerServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerService", + "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.ads.googleads.v24.services.CustomerService", + "credentialsType": None, + } + ), + ) + + def mutate_customer( + self, + request: Optional[ + Union[customer_service.MutateCustomerRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[customer_service.CustomerOperation] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_service.MutateCustomerResponse: + r"""Updates a customer. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RequestError <>`__ `UrlFieldError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomerRequest, dict]): + The request object. Request message for + [CustomerService.MutateCustomer][google.ads.googleads.v24.services.CustomerService.MutateCustomer]. + customer_id (str): + Required. The ID of the customer + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (google.ads.googleads.v24.services.types.CustomerOperation): + Required. The operation to perform on + the customer + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateCustomerResponse: + Response message for customer mutate. + """ + # 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 = [customer_id, operation] + 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, customer_service.MutateCustomerRequest): + request = customer_service.MutateCustomerRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.mutate_customer] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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_accessible_customers( + self, + request: Optional[ + Union[customer_service.ListAccessibleCustomersRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_service.ListAccessibleCustomersResponse: + r"""Returns resource names of customers directly accessible by the + user authenticating the call. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListAccessibleCustomersRequest, dict]): + The request object. Request message for + [CustomerService.ListAccessibleCustomers][google.ads.googleads.v24.services.CustomerService.ListAccessibleCustomers]. + 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.googleads.v24.services.types.ListAccessibleCustomersResponse: + Response message for + [CustomerService.ListAccessibleCustomers][google.ads.googleads.v24.services.CustomerService.ListAccessibleCustomers]. + + """ + # 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, customer_service.ListAccessibleCustomersRequest + ): + request = customer_service.ListAccessibleCustomersRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_accessible_customers + ] + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def create_customer_client( + self, + request: Optional[ + Union[customer_service.CreateCustomerClientRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + customer_client: Optional[customer.Customer] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_service.CreateCustomerClientResponse: + r"""Creates a new client under manager. The new client customer is + returned. + + List of thrown errors: `AccessInvitationError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CurrencyCodeError <>`__ `HeaderError <>`__ `InternalError <>`__ + `ManagerLinkError <>`__ `QuotaError <>`__ `RequestError <>`__ + `StringLengthError <>`__ `TimeZoneError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.CreateCustomerClientRequest, dict]): + The request object. Request message for + [CustomerService.CreateCustomerClient][google.ads.googleads.v24.services.CustomerService.CreateCustomerClient]. + customer_id (str): + Required. The ID of the Manager under + whom client customer is being created. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + customer_client (google.ads.googleads.v24.resources.types.Customer): + Required. The new client customer to + create. The resource name on this + customer will be ignored. + + This corresponds to the ``customer_client`` 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.ads.googleads.v24.services.types.CreateCustomerClientResponse: + Response message for + CreateCustomerClient mutate. + + """ + # 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 = [customer_id, customer_client] + 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, customer_service.CreateCustomerClientRequest + ): + request = customer_service.CreateCustomerClientRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if customer_client is not None: + request.customer_client = customer_client + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.create_customer_client + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomerServiceClient": + 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() + + +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__ = ("CustomerServiceClient",) diff --git a/google/ads/googleads/v24/services/services/customer_service/transports/README.rst b/google/ads/googleads/v24/services/services/customer_service/transports/README.rst new file mode 100644 index 000000000..cbf95eca5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomerServiceTransport` is the ABC for all transports. +- public child `CustomerServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomerServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomerServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomerServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/customer_service/transports/__init__.py b/google/ads/googleads/v24/services/services/customer_service/transports/__init__.py new file mode 100644 index 000000000..13accff7e --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomerServiceTransport +from .grpc import CustomerServiceGrpcTransport +from .grpc_asyncio import CustomerServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerServiceTransport]] +_transport_registry["grpc"] = CustomerServiceGrpcTransport +_transport_registry["grpc_asyncio"] = CustomerServiceGrpcAsyncIOTransport + +__all__ = ( + "CustomerServiceTransport", + "CustomerServiceGrpcTransport", + "CustomerServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customer_service/transports/base.py b/google/ads/googleads/v24/services/services/customer_service/transports/base.py new file mode 100644 index 000000000..66179e1d2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_service/transports/base.py @@ -0,0 +1,207 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import customer_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 CustomerServiceTransport(abc.ABC): + """Abstract transport class for CustomerService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customer: gapic_v1.method.wrap_method( + self.mutate_customer, + default_timeout=None, + client_info=client_info, + ), + self.list_accessible_customers: gapic_v1.method.wrap_method( + self.list_accessible_customers, + default_timeout=None, + client_info=client_info, + ), + self.create_customer_client: gapic_v1.method.wrap_method( + self.create_customer_client, + 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 mutate_customer( + self, + ) -> Callable[ + [customer_service.MutateCustomerRequest], + Union[ + customer_service.MutateCustomerResponse, + Awaitable[customer_service.MutateCustomerResponse], + ], + ]: + raise NotImplementedError() + + @property + def list_accessible_customers( + self, + ) -> Callable[ + [customer_service.ListAccessibleCustomersRequest], + Union[ + customer_service.ListAccessibleCustomersResponse, + Awaitable[customer_service.ListAccessibleCustomersResponse], + ], + ]: + raise NotImplementedError() + + @property + def create_customer_client( + self, + ) -> Callable[ + [customer_service.CreateCustomerClientRequest], + Union[ + customer_service.CreateCustomerClientResponse, + Awaitable[customer_service.CreateCustomerClientResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomerServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_service/transports/grpc.py b/google/ads/googleads/v24/services/services/customer_service/transports/grpc.py new file mode 100644 index 000000000..8eb1728c5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_service/transports/grpc.py @@ -0,0 +1,460 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import customer_service +from .base import CustomerServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerServiceGrpcTransport(CustomerServiceTransport): + """gRPC backend transport for CustomerService. + + Service to manage customers. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_customer( + self, + ) -> Callable[ + [customer_service.MutateCustomerRequest], + customer_service.MutateCustomerResponse, + ]: + r"""Return a callable for the mutate customer method over gRPC. + + Updates a customer. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RequestError <>`__ `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateCustomerRequest], + ~.MutateCustomerResponse]: + 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 "mutate_customer" not in self._stubs: + self._stubs["mutate_customer"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerService/MutateCustomer", + request_serializer=customer_service.MutateCustomerRequest.serialize, + response_deserializer=customer_service.MutateCustomerResponse.deserialize, + ) + return self._stubs["mutate_customer"] + + @property + def list_accessible_customers( + self, + ) -> Callable[ + [customer_service.ListAccessibleCustomersRequest], + customer_service.ListAccessibleCustomersResponse, + ]: + r"""Return a callable for the list accessible customers method over gRPC. + + Returns resource names of customers directly accessible by the + user authenticating the call. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListAccessibleCustomersRequest], + ~.ListAccessibleCustomersResponse]: + 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_accessible_customers" not in self._stubs: + self._stubs["list_accessible_customers"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerService/ListAccessibleCustomers", + request_serializer=customer_service.ListAccessibleCustomersRequest.serialize, + response_deserializer=customer_service.ListAccessibleCustomersResponse.deserialize, + ) + ) + return self._stubs["list_accessible_customers"] + + @property + def create_customer_client( + self, + ) -> Callable[ + [customer_service.CreateCustomerClientRequest], + customer_service.CreateCustomerClientResponse, + ]: + r"""Return a callable for the create customer client method over gRPC. + + Creates a new client under manager. The new client customer is + returned. + + List of thrown errors: `AccessInvitationError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CurrencyCodeError <>`__ `HeaderError <>`__ `InternalError <>`__ + `ManagerLinkError <>`__ `QuotaError <>`__ `RequestError <>`__ + `StringLengthError <>`__ `TimeZoneError <>`__ + + Returns: + Callable[[~.CreateCustomerClientRequest], + ~.CreateCustomerClientResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_customer_client" not in self._stubs: + self._stubs["create_customer_client"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerService/CreateCustomerClient", + request_serializer=customer_service.CreateCustomerClientRequest.serialize, + response_deserializer=customer_service.CreateCustomerClientResponse.deserialize, + ) + ) + return self._stubs["create_customer_client"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomerServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/customer_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..1e0aca3a1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_service/transports/grpc_asyncio.py @@ -0,0 +1,491 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import customer_service +from .base import CustomerServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerServiceGrpcAsyncIOTransport(CustomerServiceTransport): + """gRPC AsyncIO backend transport for CustomerService. + + Service to manage customers. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_customer( + self, + ) -> Callable[ + [customer_service.MutateCustomerRequest], + Awaitable[customer_service.MutateCustomerResponse], + ]: + r"""Return a callable for the mutate customer method over gRPC. + + Updates a customer. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RequestError <>`__ `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateCustomerRequest], + Awaitable[~.MutateCustomerResponse]]: + 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 "mutate_customer" not in self._stubs: + self._stubs["mutate_customer"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerService/MutateCustomer", + request_serializer=customer_service.MutateCustomerRequest.serialize, + response_deserializer=customer_service.MutateCustomerResponse.deserialize, + ) + return self._stubs["mutate_customer"] + + @property + def list_accessible_customers( + self, + ) -> Callable[ + [customer_service.ListAccessibleCustomersRequest], + Awaitable[customer_service.ListAccessibleCustomersResponse], + ]: + r"""Return a callable for the list accessible customers method over gRPC. + + Returns resource names of customers directly accessible by the + user authenticating the call. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListAccessibleCustomersRequest], + Awaitable[~.ListAccessibleCustomersResponse]]: + 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_accessible_customers" not in self._stubs: + self._stubs["list_accessible_customers"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerService/ListAccessibleCustomers", + request_serializer=customer_service.ListAccessibleCustomersRequest.serialize, + response_deserializer=customer_service.ListAccessibleCustomersResponse.deserialize, + ) + ) + return self._stubs["list_accessible_customers"] + + @property + def create_customer_client( + self, + ) -> Callable[ + [customer_service.CreateCustomerClientRequest], + Awaitable[customer_service.CreateCustomerClientResponse], + ]: + r"""Return a callable for the create customer client method over gRPC. + + Creates a new client under manager. The new client customer is + returned. + + List of thrown errors: `AccessInvitationError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CurrencyCodeError <>`__ `HeaderError <>`__ `InternalError <>`__ + `ManagerLinkError <>`__ `QuotaError <>`__ `RequestError <>`__ + `StringLengthError <>`__ `TimeZoneError <>`__ + + Returns: + Callable[[~.CreateCustomerClientRequest], + Awaitable[~.CreateCustomerClientResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_customer_client" not in self._stubs: + self._stubs["create_customer_client"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerService/CreateCustomerClient", + request_serializer=customer_service.CreateCustomerClientRequest.serialize, + response_deserializer=customer_service.CreateCustomerClientResponse.deserialize, + ) + ) + return self._stubs["create_customer_client"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_customer: self._wrap_method( + self.mutate_customer, + default_timeout=None, + client_info=client_info, + ), + self.list_accessible_customers: self._wrap_method( + self.list_accessible_customers, + default_timeout=None, + client_info=client_info, + ), + self.create_customer_client: self._wrap_method( + self.create_customer_client, + 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" + + +__all__ = ("CustomerServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/__init__.py b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/__init__.py new file mode 100644 index 000000000..9b972589b --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomerSkAdNetworkConversionValueSchemaServiceClient +from .async_client import ( + CustomerSkAdNetworkConversionValueSchemaServiceAsyncClient, +) + +__all__ = ( + "CustomerSkAdNetworkConversionValueSchemaServiceClient", + "CustomerSkAdNetworkConversionValueSchemaServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/async_client.py b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/async_client.py new file mode 100644 index 000000000..6366981b1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/async_client.py @@ -0,0 +1,412 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + customer_sk_ad_network_conversion_value_schema_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CustomerSkAdNetworkConversionValueSchemaServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CustomerSkAdNetworkConversionValueSchemaServiceClient + +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 CustomerSkAdNetworkConversionValueSchemaServiceAsyncClient: + """Service to manage CustomerSkAdNetworkConversionValueSchema.""" + + _client: CustomerSkAdNetworkConversionValueSchemaServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ( + CustomerSkAdNetworkConversionValueSchemaServiceClient.DEFAULT_ENDPOINT + ) + DEFAULT_MTLS_ENDPOINT = ( + CustomerSkAdNetworkConversionValueSchemaServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomerSkAdNetworkConversionValueSchemaServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ( + CustomerSkAdNetworkConversionValueSchemaServiceClient._DEFAULT_UNIVERSE + ) + + customer_sk_ad_network_conversion_value_schema_path = staticmethod( + CustomerSkAdNetworkConversionValueSchemaServiceClient.customer_sk_ad_network_conversion_value_schema_path + ) + parse_customer_sk_ad_network_conversion_value_schema_path = staticmethod( + CustomerSkAdNetworkConversionValueSchemaServiceClient.parse_customer_sk_ad_network_conversion_value_schema_path + ) + common_billing_account_path = staticmethod( + CustomerSkAdNetworkConversionValueSchemaServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomerSkAdNetworkConversionValueSchemaServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomerSkAdNetworkConversionValueSchemaServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomerSkAdNetworkConversionValueSchemaServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomerSkAdNetworkConversionValueSchemaServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomerSkAdNetworkConversionValueSchemaServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomerSkAdNetworkConversionValueSchemaServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomerSkAdNetworkConversionValueSchemaServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomerSkAdNetworkConversionValueSchemaServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomerSkAdNetworkConversionValueSchemaServiceClient.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: + CustomerSkAdNetworkConversionValueSchemaServiceAsyncClient: The constructed client. + """ + return CustomerSkAdNetworkConversionValueSchemaServiceClient.from_service_account_info.__func__(CustomerSkAdNetworkConversionValueSchemaServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomerSkAdNetworkConversionValueSchemaServiceAsyncClient: The constructed client. + """ + return CustomerSkAdNetworkConversionValueSchemaServiceClient.from_service_account_file.__func__(CustomerSkAdNetworkConversionValueSchemaServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomerSkAdNetworkConversionValueSchemaServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport( + self, + ) -> CustomerSkAdNetworkConversionValueSchemaServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerSkAdNetworkConversionValueSchemaServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + CustomerSkAdNetworkConversionValueSchemaServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomerSkAdNetworkConversionValueSchemaServiceTransport, + Callable[ + ..., + CustomerSkAdNetworkConversionValueSchemaServiceTransport, + ], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer sk ad network conversion value schema 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,CustomerSkAdNetworkConversionValueSchemaServiceTransport,Callable[..., CustomerSkAdNetworkConversionValueSchemaServiceTransport]]]): + 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 CustomerSkAdNetworkConversionValueSchemaServiceTransport 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 = CustomerSkAdNetworkConversionValueSchemaServiceClient( + 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.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaService", + "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.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaService", + "credentialsType": None, + } + ), + ) + + async def mutate_customer_sk_ad_network_conversion_value_schema( + self, + request: Optional[ + Union[ + customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaResponse + ): + r"""Creates or updates the CustomerSkAdNetworkConversionValueSchema. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `InternalError <>`__ + `MutateError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomerSkAdNetworkConversionValueSchemaRequest, dict]]): + The request object. Request message for + [CustomerSkAdNetworkConversionValueSchemaService.MutateCustomerSkAdNetworkConversionValueSchema][google.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaService.MutateCustomerSkAdNetworkConversionValueSchema]. + 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.googleads.v24.services.types.MutateCustomerSkAdNetworkConversionValueSchemaResponse: + Response message for + MutateCustomerSkAdNetworkConversionValueSchema. + + """ + # 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, + customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaRequest, + ): + request = customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_customer_sk_ad_network_conversion_value_schema + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__( + self, + ) -> "CustomerSkAdNetworkConversionValueSchemaServiceAsyncClient": + 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__ = ("CustomerSkAdNetworkConversionValueSchemaServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/client.py b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/client.py new file mode 100644 index 000000000..2a34786dc --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/client.py @@ -0,0 +1,895 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + customer_sk_ad_network_conversion_value_schema_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CustomerSkAdNetworkConversionValueSchemaServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ( + CustomerSkAdNetworkConversionValueSchemaServiceGrpcTransport, +) +from .transports.grpc_asyncio import ( + CustomerSkAdNetworkConversionValueSchemaServiceGrpcAsyncIOTransport, +) + + +class CustomerSkAdNetworkConversionValueSchemaServiceClientMeta(type): + """Metaclass for the CustomerSkAdNetworkConversionValueSchemaService 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[CustomerSkAdNetworkConversionValueSchemaServiceTransport]] + _transport_registry["grpc"] = ( + CustomerSkAdNetworkConversionValueSchemaServiceGrpcTransport + ) + _transport_registry["grpc_asyncio"] = ( + CustomerSkAdNetworkConversionValueSchemaServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerSkAdNetworkConversionValueSchemaServiceTransport]: + """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 CustomerSkAdNetworkConversionValueSchemaServiceClient( + metaclass=CustomerSkAdNetworkConversionValueSchemaServiceClientMeta +): + """Service to manage CustomerSkAdNetworkConversionValueSchema.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomerSkAdNetworkConversionValueSchemaServiceClient: 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: + CustomerSkAdNetworkConversionValueSchemaServiceClient: 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, + ) -> CustomerSkAdNetworkConversionValueSchemaServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerSkAdNetworkConversionValueSchemaServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customer_sk_ad_network_conversion_value_schema_path( + customer_id: str, + account_link_id: str, + ) -> str: + """Returns a fully-qualified customer_sk_ad_network_conversion_value_schema string.""" + return "customers/{customer_id}/customerSkAdNetworkConversionValueSchemas/{account_link_id}".format( + customer_id=customer_id, + account_link_id=account_link_id, + ) + + @staticmethod + def parse_customer_sk_ad_network_conversion_value_schema_path( + path: str, + ) -> Dict[str, str]: + """Parses a customer_sk_ad_network_conversion_value_schema path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerSkAdNetworkConversionValueSchemas/(?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 = ( + CustomerSkAdNetworkConversionValueSchemaServiceClient._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 = ( + CustomerSkAdNetworkConversionValueSchemaServiceClient._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 + ): + """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 = ( + CustomerSkAdNetworkConversionValueSchemaServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + CustomerSkAdNetworkConversionValueSchemaServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = CustomerSkAdNetworkConversionValueSchemaServiceClient._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 = ( + CustomerSkAdNetworkConversionValueSchemaServiceClient._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): + """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, + CustomerSkAdNetworkConversionValueSchemaServiceTransport, + Callable[ + ..., + CustomerSkAdNetworkConversionValueSchemaServiceTransport, + ], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer sk ad network conversion value schema 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,CustomerSkAdNetworkConversionValueSchemaServiceTransport,Callable[..., CustomerSkAdNetworkConversionValueSchemaServiceTransport]]]): + 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 CustomerSkAdNetworkConversionValueSchemaServiceTransport 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, + ) = ( + CustomerSkAdNetworkConversionValueSchemaServiceClient._read_environment_variables() + ) + self._client_cert_source = CustomerSkAdNetworkConversionValueSchemaServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = CustomerSkAdNetworkConversionValueSchemaServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomerSkAdNetworkConversionValueSchemaServiceTransport + ) + if transport_provided: + # transport is a CustomerSkAdNetworkConversionValueSchemaServiceTransport 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( + CustomerSkAdNetworkConversionValueSchemaServiceTransport, + transport, + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomerSkAdNetworkConversionValueSchemaServiceClient._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[CustomerSkAdNetworkConversionValueSchemaServiceTransport], + Callable[ + ..., + CustomerSkAdNetworkConversionValueSchemaServiceTransport, + ], + ] = ( + CustomerSkAdNetworkConversionValueSchemaServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[ + ..., + CustomerSkAdNetworkConversionValueSchemaServiceTransport, + ], + 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.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaService", + "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.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaService", + "credentialsType": None, + } + ), + ) + + def mutate_customer_sk_ad_network_conversion_value_schema( + self, + request: Optional[ + Union[ + customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaResponse + ): + r"""Creates or updates the CustomerSkAdNetworkConversionValueSchema. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `InternalError <>`__ + `MutateError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomerSkAdNetworkConversionValueSchemaRequest, dict]): + The request object. Request message for + [CustomerSkAdNetworkConversionValueSchemaService.MutateCustomerSkAdNetworkConversionValueSchema][google.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaService.MutateCustomerSkAdNetworkConversionValueSchema]. + 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.googleads.v24.services.types.MutateCustomerSkAdNetworkConversionValueSchemaResponse: + Response message for + MutateCustomerSkAdNetworkConversionValueSchema. + + """ + # 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, + customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaRequest, + ): + request = customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_customer_sk_ad_network_conversion_value_schema + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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, + ) -> "CustomerSkAdNetworkConversionValueSchemaServiceClient": + 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() + + +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__ = ("CustomerSkAdNetworkConversionValueSchemaServiceClient",) diff --git a/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/README.rst b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/README.rst new file mode 100644 index 000000000..e6df248e7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomerSkAdNetworkConversionValueSchemaServiceTransport` is the ABC for all transports. +- public child `CustomerSkAdNetworkConversionValueSchemaServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomerSkAdNetworkConversionValueSchemaServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomerSkAdNetworkConversionValueSchemaServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomerSkAdNetworkConversionValueSchemaServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/__init__.py b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/__init__.py new file mode 100644 index 000000000..c41c74b21 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/__init__.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomerSkAdNetworkConversionValueSchemaServiceTransport +from .grpc import CustomerSkAdNetworkConversionValueSchemaServiceGrpcTransport +from .grpc_asyncio import ( + CustomerSkAdNetworkConversionValueSchemaServiceGrpcAsyncIOTransport, +) + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerSkAdNetworkConversionValueSchemaServiceTransport]] +_transport_registry["grpc"] = ( + CustomerSkAdNetworkConversionValueSchemaServiceGrpcTransport +) +_transport_registry["grpc_asyncio"] = ( + CustomerSkAdNetworkConversionValueSchemaServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CustomerSkAdNetworkConversionValueSchemaServiceTransport", + "CustomerSkAdNetworkConversionValueSchemaServiceGrpcTransport", + "CustomerSkAdNetworkConversionValueSchemaServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/base.py b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/base.py new file mode 100644 index 000000000..67dfbfe02 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + customer_sk_ad_network_conversion_value_schema_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 CustomerSkAdNetworkConversionValueSchemaServiceTransport(abc.ABC): + """Abstract transport class for CustomerSkAdNetworkConversionValueSchemaService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customer_sk_ad_network_conversion_value_schema: gapic_v1.method.wrap_method( + self.mutate_customer_sk_ad_network_conversion_value_schema, + 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 mutate_customer_sk_ad_network_conversion_value_schema( + self, + ) -> Callable[ + [ + customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaRequest + ], + Union[ + customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaResponse, + Awaitable[ + customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomerSkAdNetworkConversionValueSchemaServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/grpc.py b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/grpc.py new file mode 100644 index 000000000..bda41a2c6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/grpc.py @@ -0,0 +1,402 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + customer_sk_ad_network_conversion_value_schema_service, +) +from .base import ( + CustomerSkAdNetworkConversionValueSchemaServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerSkAdNetworkConversionValueSchemaServiceGrpcTransport( + CustomerSkAdNetworkConversionValueSchemaServiceTransport +): + """gRPC backend transport for CustomerSkAdNetworkConversionValueSchemaService. + + Service to manage CustomerSkAdNetworkConversionValueSchema. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_customer_sk_ad_network_conversion_value_schema( + self, + ) -> Callable[ + [ + customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaRequest + ], + customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaResponse, + ]: + r"""Return a callable for the mutate customer sk ad network + conversion value schema method over gRPC. + + Creates or updates the CustomerSkAdNetworkConversionValueSchema. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `InternalError <>`__ + `MutateError <>`__ + + Returns: + Callable[[~.MutateCustomerSkAdNetworkConversionValueSchemaRequest], + ~.MutateCustomerSkAdNetworkConversionValueSchemaResponse]: + 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 ( + "mutate_customer_sk_ad_network_conversion_value_schema" + not in self._stubs + ): + self._stubs[ + "mutate_customer_sk_ad_network_conversion_value_schema" + ] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaService/MutateCustomerSkAdNetworkConversionValueSchema", + request_serializer=customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaRequest.serialize, + response_deserializer=customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaResponse.deserialize, + ) + return self._stubs[ + "mutate_customer_sk_ad_network_conversion_value_schema" + ] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomerSkAdNetworkConversionValueSchemaServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..395d8f883 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/grpc_asyncio.py @@ -0,0 +1,427 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + customer_sk_ad_network_conversion_value_schema_service, +) +from .base import ( + CustomerSkAdNetworkConversionValueSchemaServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerSkAdNetworkConversionValueSchemaServiceGrpcAsyncIOTransport( + CustomerSkAdNetworkConversionValueSchemaServiceTransport +): + """gRPC AsyncIO backend transport for CustomerSkAdNetworkConversionValueSchemaService. + + Service to manage CustomerSkAdNetworkConversionValueSchema. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_customer_sk_ad_network_conversion_value_schema( + self, + ) -> Callable[ + [ + customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaRequest + ], + Awaitable[ + customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaResponse + ], + ]: + r"""Return a callable for the mutate customer sk ad network + conversion value schema method over gRPC. + + Creates or updates the CustomerSkAdNetworkConversionValueSchema. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `InternalError <>`__ + `MutateError <>`__ + + Returns: + Callable[[~.MutateCustomerSkAdNetworkConversionValueSchemaRequest], + Awaitable[~.MutateCustomerSkAdNetworkConversionValueSchemaResponse]]: + 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 ( + "mutate_customer_sk_ad_network_conversion_value_schema" + not in self._stubs + ): + self._stubs[ + "mutate_customer_sk_ad_network_conversion_value_schema" + ] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaService/MutateCustomerSkAdNetworkConversionValueSchema", + request_serializer=customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaRequest.serialize, + response_deserializer=customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaResponse.deserialize, + ) + return self._stubs[ + "mutate_customer_sk_ad_network_conversion_value_schema" + ] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_customer_sk_ad_network_conversion_value_schema: self._wrap_method( + self.mutate_customer_sk_ad_network_conversion_value_schema, + 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" + + +__all__ = ( + "CustomerSkAdNetworkConversionValueSchemaServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/__init__.py b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/__init__.py new file mode 100644 index 000000000..66498c94b --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomerUserAccessInvitationServiceClient +from .async_client import CustomerUserAccessInvitationServiceAsyncClient + +__all__ = ( + "CustomerUserAccessInvitationServiceClient", + "CustomerUserAccessInvitationServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/async_client.py b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/async_client.py new file mode 100644 index 000000000..435b39a8c --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/async_client.py @@ -0,0 +1,447 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + customer_user_access_invitation_service, +) +from .transports.base import ( + CustomerUserAccessInvitationServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CustomerUserAccessInvitationServiceClient + +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 CustomerUserAccessInvitationServiceAsyncClient: + """This service manages the access invitation extended to users + for a given customer. + """ + + _client: CustomerUserAccessInvitationServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ( + CustomerUserAccessInvitationServiceClient.DEFAULT_ENDPOINT + ) + DEFAULT_MTLS_ENDPOINT = ( + CustomerUserAccessInvitationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomerUserAccessInvitationServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ( + CustomerUserAccessInvitationServiceClient._DEFAULT_UNIVERSE + ) + + customer_user_access_invitation_path = staticmethod( + CustomerUserAccessInvitationServiceClient.customer_user_access_invitation_path + ) + parse_customer_user_access_invitation_path = staticmethod( + CustomerUserAccessInvitationServiceClient.parse_customer_user_access_invitation_path + ) + common_billing_account_path = staticmethod( + CustomerUserAccessInvitationServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomerUserAccessInvitationServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomerUserAccessInvitationServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomerUserAccessInvitationServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomerUserAccessInvitationServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomerUserAccessInvitationServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomerUserAccessInvitationServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomerUserAccessInvitationServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomerUserAccessInvitationServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomerUserAccessInvitationServiceClient.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: + CustomerUserAccessInvitationServiceAsyncClient: The constructed client. + """ + return CustomerUserAccessInvitationServiceClient.from_service_account_info.__func__(CustomerUserAccessInvitationServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomerUserAccessInvitationServiceAsyncClient: The constructed client. + """ + return CustomerUserAccessInvitationServiceClient.from_service_account_file.__func__(CustomerUserAccessInvitationServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomerUserAccessInvitationServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomerUserAccessInvitationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerUserAccessInvitationServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + CustomerUserAccessInvitationServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomerUserAccessInvitationServiceTransport, + Callable[..., CustomerUserAccessInvitationServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer user access invitation 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,CustomerUserAccessInvitationServiceTransport,Callable[..., CustomerUserAccessInvitationServiceTransport]]]): + 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 CustomerUserAccessInvitationServiceTransport 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 = CustomerUserAccessInvitationServiceClient( + 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.ads.googleads.v24.services.CustomerUserAccessInvitationServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerUserAccessInvitationService", + "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.ads.googleads.v24.services.CustomerUserAccessInvitationService", + "credentialsType": None, + } + ), + ) + + async def mutate_customer_user_access_invitation( + self, + request: Optional[ + Union[ + customer_user_access_invitation_service.MutateCustomerUserAccessInvitationRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[ + customer_user_access_invitation_service.CustomerUserAccessInvitationOperation + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + customer_user_access_invitation_service.MutateCustomerUserAccessInvitationResponse + ): + r"""Creates or removes an access invitation. + + List of thrown errors: `AccessInvitationError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomerUserAccessInvitationRequest, dict]]): + The request object. Request message for + [CustomerUserAccessInvitationService.MutateCustomerUserAccessInvitation][google.ads.googleads.v24.services.CustomerUserAccessInvitationService.MutateCustomerUserAccessInvitation] + customer_id (:class:`str`): + Required. The ID of the customer + whose access invitation is being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (:class:`google.ads.googleads.v24.services.types.CustomerUserAccessInvitationOperation`): + Required. The operation to perform on + the access invitation + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateCustomerUserAccessInvitationResponse: + Response message for access + invitation mutate. + + """ + # 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 = [customer_id, operation] + 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, + customer_user_access_invitation_service.MutateCustomerUserAccessInvitationRequest, + ): + request = customer_user_access_invitation_service.MutateCustomerUserAccessInvitationRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_customer_user_access_invitation + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__( + self, + ) -> "CustomerUserAccessInvitationServiceAsyncClient": + 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__ = ("CustomerUserAccessInvitationServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/client.py b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/client.py new file mode 100644 index 000000000..26d2e1840 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/client.py @@ -0,0 +1,920 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + customer_user_access_invitation_service, +) +from .transports.base import ( + CustomerUserAccessInvitationServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerUserAccessInvitationServiceGrpcTransport +from .transports.grpc_asyncio import ( + CustomerUserAccessInvitationServiceGrpcAsyncIOTransport, +) + + +class CustomerUserAccessInvitationServiceClientMeta(type): + """Metaclass for the CustomerUserAccessInvitationService 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[CustomerUserAccessInvitationServiceTransport]] + _transport_registry["grpc"] = ( + CustomerUserAccessInvitationServiceGrpcTransport + ) + _transport_registry["grpc_asyncio"] = ( + CustomerUserAccessInvitationServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerUserAccessInvitationServiceTransport]: + """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 CustomerUserAccessInvitationServiceClient( + metaclass=CustomerUserAccessInvitationServiceClientMeta +): + """This service manages the access invitation extended to users + for a given customer. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomerUserAccessInvitationServiceClient: 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: + CustomerUserAccessInvitationServiceClient: 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) -> CustomerUserAccessInvitationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerUserAccessInvitationServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customer_user_access_invitation_path( + customer_id: str, + invitation_id: str, + ) -> str: + """Returns a fully-qualified customer_user_access_invitation string.""" + return "customers/{customer_id}/customerUserAccessInvitations/{invitation_id}".format( + customer_id=customer_id, + invitation_id=invitation_id, + ) + + @staticmethod + def parse_customer_user_access_invitation_path(path: str) -> Dict[str, str]: + """Parses a customer_user_access_invitation path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerUserAccessInvitations/(?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 = ( + CustomerUserAccessInvitationServiceClient._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 = ( + CustomerUserAccessInvitationServiceClient._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 + ): + """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 = ( + CustomerUserAccessInvitationServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + CustomerUserAccessInvitationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = CustomerUserAccessInvitationServiceClient._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 = ( + CustomerUserAccessInvitationServiceClient._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): + """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, + CustomerUserAccessInvitationServiceTransport, + Callable[..., CustomerUserAccessInvitationServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer user access invitation 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,CustomerUserAccessInvitationServiceTransport,Callable[..., CustomerUserAccessInvitationServiceTransport]]]): + 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 CustomerUserAccessInvitationServiceTransport 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, + ) = ( + CustomerUserAccessInvitationServiceClient._read_environment_variables() + ) + self._client_cert_source = ( + CustomerUserAccessInvitationServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CustomerUserAccessInvitationServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomerUserAccessInvitationServiceTransport + ) + if transport_provided: + # transport is a CustomerUserAccessInvitationServiceTransport 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( + CustomerUserAccessInvitationServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomerUserAccessInvitationServiceClient._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[CustomerUserAccessInvitationServiceTransport], + Callable[..., CustomerUserAccessInvitationServiceTransport], + ] = ( + CustomerUserAccessInvitationServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomerUserAccessInvitationServiceTransport], + 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.ads.googleads.v24.services.CustomerUserAccessInvitationServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerUserAccessInvitationService", + "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.ads.googleads.v24.services.CustomerUserAccessInvitationService", + "credentialsType": None, + } + ), + ) + + def mutate_customer_user_access_invitation( + self, + request: Optional[ + Union[ + customer_user_access_invitation_service.MutateCustomerUserAccessInvitationRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[ + customer_user_access_invitation_service.CustomerUserAccessInvitationOperation + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + customer_user_access_invitation_service.MutateCustomerUserAccessInvitationResponse + ): + r"""Creates or removes an access invitation. + + List of thrown errors: `AccessInvitationError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomerUserAccessInvitationRequest, dict]): + The request object. Request message for + [CustomerUserAccessInvitationService.MutateCustomerUserAccessInvitation][google.ads.googleads.v24.services.CustomerUserAccessInvitationService.MutateCustomerUserAccessInvitation] + customer_id (str): + Required. The ID of the customer + whose access invitation is being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (google.ads.googleads.v24.services.types.CustomerUserAccessInvitationOperation): + Required. The operation to perform on + the access invitation + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateCustomerUserAccessInvitationResponse: + Response message for access + invitation mutate. + + """ + # 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 = [customer_id, operation] + 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, + customer_user_access_invitation_service.MutateCustomerUserAccessInvitationRequest, + ): + request = customer_user_access_invitation_service.MutateCustomerUserAccessInvitationRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_customer_user_access_invitation + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomerUserAccessInvitationServiceClient": + 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() + + +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__ = ("CustomerUserAccessInvitationServiceClient",) diff --git a/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/README.rst b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/README.rst new file mode 100644 index 000000000..21406cf04 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomerUserAccessInvitationServiceTransport` is the ABC for all transports. +- public child `CustomerUserAccessInvitationServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomerUserAccessInvitationServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomerUserAccessInvitationServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomerUserAccessInvitationServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/__init__.py b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/__init__.py new file mode 100644 index 000000000..813a355ca --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/__init__.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomerUserAccessInvitationServiceTransport +from .grpc import CustomerUserAccessInvitationServiceGrpcTransport +from .grpc_asyncio import ( + CustomerUserAccessInvitationServiceGrpcAsyncIOTransport, +) + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerUserAccessInvitationServiceTransport]] +_transport_registry["grpc"] = CustomerUserAccessInvitationServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CustomerUserAccessInvitationServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CustomerUserAccessInvitationServiceTransport", + "CustomerUserAccessInvitationServiceGrpcTransport", + "CustomerUserAccessInvitationServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/base.py b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/base.py new file mode 100644 index 000000000..86f45aacb --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + customer_user_access_invitation_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 CustomerUserAccessInvitationServiceTransport(abc.ABC): + """Abstract transport class for CustomerUserAccessInvitationService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customer_user_access_invitation: gapic_v1.method.wrap_method( + self.mutate_customer_user_access_invitation, + 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 mutate_customer_user_access_invitation( + self, + ) -> Callable[ + [ + customer_user_access_invitation_service.MutateCustomerUserAccessInvitationRequest + ], + Union[ + customer_user_access_invitation_service.MutateCustomerUserAccessInvitationResponse, + Awaitable[ + customer_user_access_invitation_service.MutateCustomerUserAccessInvitationResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomerUserAccessInvitationServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/grpc.py b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/grpc.py new file mode 100644 index 000000000..04dc0cad9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/grpc.py @@ -0,0 +1,399 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + customer_user_access_invitation_service, +) +from .base import ( + CustomerUserAccessInvitationServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerUserAccessInvitationService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerUserAccessInvitationService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerUserAccessInvitationServiceGrpcTransport( + CustomerUserAccessInvitationServiceTransport +): + """gRPC backend transport for CustomerUserAccessInvitationService. + + This service manages the access invitation extended to users + for a given customer. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_customer_user_access_invitation( + self, + ) -> Callable[ + [ + customer_user_access_invitation_service.MutateCustomerUserAccessInvitationRequest + ], + customer_user_access_invitation_service.MutateCustomerUserAccessInvitationResponse, + ]: + r"""Return a callable for the mutate customer user access + invitation method over gRPC. + + Creates or removes an access invitation. + + List of thrown errors: `AccessInvitationError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomerUserAccessInvitationRequest], + ~.MutateCustomerUserAccessInvitationResponse]: + 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 "mutate_customer_user_access_invitation" not in self._stubs: + self._stubs["mutate_customer_user_access_invitation"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerUserAccessInvitationService/MutateCustomerUserAccessInvitation", + request_serializer=customer_user_access_invitation_service.MutateCustomerUserAccessInvitationRequest.serialize, + response_deserializer=customer_user_access_invitation_service.MutateCustomerUserAccessInvitationResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_user_access_invitation"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomerUserAccessInvitationServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..788ad235b --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_invitation_service/transports/grpc_asyncio.py @@ -0,0 +1,422 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + customer_user_access_invitation_service, +) +from .base import ( + CustomerUserAccessInvitationServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerUserAccessInvitationService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerUserAccessInvitationService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerUserAccessInvitationServiceGrpcAsyncIOTransport( + CustomerUserAccessInvitationServiceTransport +): + """gRPC AsyncIO backend transport for CustomerUserAccessInvitationService. + + This service manages the access invitation extended to users + for a given customer. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_customer_user_access_invitation( + self, + ) -> Callable[ + [ + customer_user_access_invitation_service.MutateCustomerUserAccessInvitationRequest + ], + Awaitable[ + customer_user_access_invitation_service.MutateCustomerUserAccessInvitationResponse + ], + ]: + r"""Return a callable for the mutate customer user access + invitation method over gRPC. + + Creates or removes an access invitation. + + List of thrown errors: `AccessInvitationError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomerUserAccessInvitationRequest], + Awaitable[~.MutateCustomerUserAccessInvitationResponse]]: + 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 "mutate_customer_user_access_invitation" not in self._stubs: + self._stubs["mutate_customer_user_access_invitation"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerUserAccessInvitationService/MutateCustomerUserAccessInvitation", + request_serializer=customer_user_access_invitation_service.MutateCustomerUserAccessInvitationRequest.serialize, + response_deserializer=customer_user_access_invitation_service.MutateCustomerUserAccessInvitationResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_user_access_invitation"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_customer_user_access_invitation: self._wrap_method( + self.mutate_customer_user_access_invitation, + 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" + + +__all__ = ("CustomerUserAccessInvitationServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_user_access_service/__init__.py b/google/ads/googleads/v24/services/services/customer_user_access_service/__init__.py new file mode 100644 index 000000000..2a5177c77 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomerUserAccessServiceClient +from .async_client import CustomerUserAccessServiceAsyncClient + +__all__ = ( + "CustomerUserAccessServiceClient", + "CustomerUserAccessServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/customer_user_access_service/async_client.py b/google/ads/googleads/v24/services/services/customer_user_access_service/async_client.py new file mode 100644 index 000000000..8679b2a6f --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_service/async_client.py @@ -0,0 +1,437 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import customer_user_access_service +from .transports.base import ( + CustomerUserAccessServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CustomerUserAccessServiceClient + +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 CustomerUserAccessServiceAsyncClient: + """This service manages the permissions of a user on a given + customer. + """ + + _client: CustomerUserAccessServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomerUserAccessServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + CustomerUserAccessServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomerUserAccessServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomerUserAccessServiceClient._DEFAULT_UNIVERSE + + customer_user_access_path = staticmethod( + CustomerUserAccessServiceClient.customer_user_access_path + ) + parse_customer_user_access_path = staticmethod( + CustomerUserAccessServiceClient.parse_customer_user_access_path + ) + common_billing_account_path = staticmethod( + CustomerUserAccessServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomerUserAccessServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomerUserAccessServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomerUserAccessServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomerUserAccessServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomerUserAccessServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomerUserAccessServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomerUserAccessServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomerUserAccessServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomerUserAccessServiceClient.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: + CustomerUserAccessServiceAsyncClient: The constructed client. + """ + return CustomerUserAccessServiceClient.from_service_account_info.__func__(CustomerUserAccessServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomerUserAccessServiceAsyncClient: The constructed client. + """ + return CustomerUserAccessServiceClient.from_service_account_file.__func__(CustomerUserAccessServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomerUserAccessServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomerUserAccessServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerUserAccessServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CustomerUserAccessServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomerUserAccessServiceTransport, + Callable[..., CustomerUserAccessServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer user access 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,CustomerUserAccessServiceTransport,Callable[..., CustomerUserAccessServiceTransport]]]): + 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 CustomerUserAccessServiceTransport 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 = CustomerUserAccessServiceClient( + 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.ads.googleads.v24.services.CustomerUserAccessServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerUserAccessService", + "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.ads.googleads.v24.services.CustomerUserAccessService", + "credentialsType": None, + } + ), + ) + + async def mutate_customer_user_access( + self, + request: Optional[ + Union[ + customer_user_access_service.MutateCustomerUserAccessRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[ + customer_user_access_service.CustomerUserAccessOperation + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_user_access_service.MutateCustomerUserAccessResponse: + r"""Updates, removes permission of a user on a given customer. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CustomerUserAccessError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomerUserAccessRequest, dict]]): + The request object. Mutate Request for + [CustomerUserAccessService.MutateCustomerUserAccess][google.ads.googleads.v24.services.CustomerUserAccessService.MutateCustomerUserAccess]. + customer_id (:class:`str`): + Required. The ID of the customer + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (:class:`google.ads.googleads.v24.services.types.CustomerUserAccessOperation`): + Required. The operation to perform on + the customer + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateCustomerUserAccessResponse: + Response message for customer user + access mutate. + + """ + # 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 = [customer_id, operation] + 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, + customer_user_access_service.MutateCustomerUserAccessRequest, + ): + request = ( + customer_user_access_service.MutateCustomerUserAccessRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_customer_user_access + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomerUserAccessServiceAsyncClient": + 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__ = ("CustomerUserAccessServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/customer_user_access_service/client.py b/google/ads/googleads/v24/services/services/customer_user_access_service/client.py new file mode 100644 index 000000000..f4c7a8506 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_service/client.py @@ -0,0 +1,907 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import customer_user_access_service +from .transports.base import ( + CustomerUserAccessServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerUserAccessServiceGrpcTransport +from .transports.grpc_asyncio import ( + CustomerUserAccessServiceGrpcAsyncIOTransport, +) + + +class CustomerUserAccessServiceClientMeta(type): + """Metaclass for the CustomerUserAccessService 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[CustomerUserAccessServiceTransport]] + _transport_registry["grpc"] = CustomerUserAccessServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CustomerUserAccessServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerUserAccessServiceTransport]: + """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 CustomerUserAccessServiceClient( + metaclass=CustomerUserAccessServiceClientMeta +): + """This service manages the permissions of a user on a given + customer. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomerUserAccessServiceClient: 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: + CustomerUserAccessServiceClient: 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) -> CustomerUserAccessServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerUserAccessServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customer_user_access_path( + customer_id: str, + user_id: str, + ) -> str: + """Returns a fully-qualified customer_user_access string.""" + return "customers/{customer_id}/customerUserAccesses/{user_id}".format( + customer_id=customer_id, + user_id=user_id, + ) + + @staticmethod + def parse_customer_user_access_path(path: str) -> Dict[str, str]: + """Parses a customer_user_access path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerUserAccesses/(?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 = ( + CustomerUserAccessServiceClient._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 = ( + CustomerUserAccessServiceClient._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 + ): + """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 = ( + CustomerUserAccessServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = CustomerUserAccessServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = CustomerUserAccessServiceClient._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 = CustomerUserAccessServiceClient._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): + """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, + CustomerUserAccessServiceTransport, + Callable[..., CustomerUserAccessServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customer user access 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,CustomerUserAccessServiceTransport,Callable[..., CustomerUserAccessServiceTransport]]]): + 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 CustomerUserAccessServiceTransport 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, + ) = CustomerUserAccessServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomerUserAccessServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CustomerUserAccessServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomerUserAccessServiceTransport + ) + if transport_provided: + # transport is a CustomerUserAccessServiceTransport 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( + CustomerUserAccessServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomerUserAccessServiceClient._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[CustomerUserAccessServiceTransport], + Callable[..., CustomerUserAccessServiceTransport], + ] = ( + CustomerUserAccessServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomerUserAccessServiceTransport], 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.ads.googleads.v24.services.CustomerUserAccessServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomerUserAccessService", + "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.ads.googleads.v24.services.CustomerUserAccessService", + "credentialsType": None, + } + ), + ) + + def mutate_customer_user_access( + self, + request: Optional[ + Union[ + customer_user_access_service.MutateCustomerUserAccessRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operation: Optional[ + customer_user_access_service.CustomerUserAccessOperation + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customer_user_access_service.MutateCustomerUserAccessResponse: + r"""Updates, removes permission of a user on a given customer. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CustomerUserAccessError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomerUserAccessRequest, dict]): + The request object. Mutate Request for + [CustomerUserAccessService.MutateCustomerUserAccess][google.ads.googleads.v24.services.CustomerUserAccessService.MutateCustomerUserAccess]. + customer_id (str): + Required. The ID of the customer + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operation (google.ads.googleads.v24.services.types.CustomerUserAccessOperation): + Required. The operation to perform on + the customer + + This corresponds to the ``operation`` 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.ads.googleads.v24.services.types.MutateCustomerUserAccessResponse: + Response message for customer user + access mutate. + + """ + # 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 = [customer_id, operation] + 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, + customer_user_access_service.MutateCustomerUserAccessRequest, + ): + request = ( + customer_user_access_service.MutateCustomerUserAccessRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operation is not None: + request.operation = operation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_customer_user_access + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomerUserAccessServiceClient": + 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() + + +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__ = ("CustomerUserAccessServiceClient",) diff --git a/google/ads/googleads/v24/services/services/customer_user_access_service/transports/README.rst b/google/ads/googleads/v24/services/services/customer_user_access_service/transports/README.rst new file mode 100644 index 000000000..023a12f75 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomerUserAccessServiceTransport` is the ABC for all transports. +- public child `CustomerUserAccessServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomerUserAccessServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomerUserAccessServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomerUserAccessServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/customer_user_access_service/transports/__init__.py b/google/ads/googleads/v24/services/services/customer_user_access_service/transports/__init__.py new file mode 100644 index 000000000..2b62c8b2b --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomerUserAccessServiceTransport +from .grpc import CustomerUserAccessServiceGrpcTransport +from .grpc_asyncio import CustomerUserAccessServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerUserAccessServiceTransport]] +_transport_registry["grpc"] = CustomerUserAccessServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CustomerUserAccessServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CustomerUserAccessServiceTransport", + "CustomerUserAccessServiceGrpcTransport", + "CustomerUserAccessServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customer_user_access_service/transports/base.py b/google/ads/googleads/v24/services/services/customer_user_access_service/transports/base.py new file mode 100644 index 000000000..384044396 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import customer_user_access_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 CustomerUserAccessServiceTransport(abc.ABC): + """Abstract transport class for CustomerUserAccessService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customer_user_access: gapic_v1.method.wrap_method( + self.mutate_customer_user_access, + 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 mutate_customer_user_access( + self, + ) -> Callable[ + [customer_user_access_service.MutateCustomerUserAccessRequest], + Union[ + customer_user_access_service.MutateCustomerUserAccessResponse, + Awaitable[ + customer_user_access_service.MutateCustomerUserAccessResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomerUserAccessServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_user_access_service/transports/grpc.py b/google/ads/googleads/v24/services/services/customer_user_access_service/transports/grpc.py new file mode 100644 index 000000000..2e3a5d5eb --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_service/transports/grpc.py @@ -0,0 +1,392 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import customer_user_access_service +from .base import CustomerUserAccessServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerUserAccessService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerUserAccessService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerUserAccessServiceGrpcTransport( + CustomerUserAccessServiceTransport +): + """gRPC backend transport for CustomerUserAccessService. + + This service manages the permissions of a user on a given + customer. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_customer_user_access( + self, + ) -> Callable[ + [customer_user_access_service.MutateCustomerUserAccessRequest], + customer_user_access_service.MutateCustomerUserAccessResponse, + ]: + r"""Return a callable for the mutate customer user access method over gRPC. + + Updates, removes permission of a user on a given customer. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CustomerUserAccessError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomerUserAccessRequest], + ~.MutateCustomerUserAccessResponse]: + 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 "mutate_customer_user_access" not in self._stubs: + self._stubs["mutate_customer_user_access"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerUserAccessService/MutateCustomerUserAccess", + request_serializer=customer_user_access_service.MutateCustomerUserAccessRequest.serialize, + response_deserializer=customer_user_access_service.MutateCustomerUserAccessResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_user_access"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomerUserAccessServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/customer_user_access_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/customer_user_access_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..c7d528122 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customer_user_access_service/transports/grpc_asyncio.py @@ -0,0 +1,415 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import customer_user_access_service +from .base import CustomerUserAccessServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomerUserAccessService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomerUserAccessService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomerUserAccessServiceGrpcAsyncIOTransport( + CustomerUserAccessServiceTransport +): + """gRPC AsyncIO backend transport for CustomerUserAccessService. + + This service manages the permissions of a user on a given + customer. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_customer_user_access( + self, + ) -> Callable[ + [customer_user_access_service.MutateCustomerUserAccessRequest], + Awaitable[ + customer_user_access_service.MutateCustomerUserAccessResponse + ], + ]: + r"""Return a callable for the mutate customer user access method over gRPC. + + Updates, removes permission of a user on a given customer. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CustomerUserAccessError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateCustomerUserAccessRequest], + Awaitable[~.MutateCustomerUserAccessResponse]]: + 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 "mutate_customer_user_access" not in self._stubs: + self._stubs["mutate_customer_user_access"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomerUserAccessService/MutateCustomerUserAccess", + request_serializer=customer_user_access_service.MutateCustomerUserAccessRequest.serialize, + response_deserializer=customer_user_access_service.MutateCustomerUserAccessResponse.deserialize, + ) + ) + return self._stubs["mutate_customer_user_access"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_customer_user_access: self._wrap_method( + self.mutate_customer_user_access, + 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" + + +__all__ = ("CustomerUserAccessServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/customizer_attribute_service/__init__.py b/google/ads/googleads/v24/services/services/customizer_attribute_service/__init__.py new file mode 100644 index 000000000..7643c2676 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customizer_attribute_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import CustomizerAttributeServiceClient +from .async_client import CustomizerAttributeServiceAsyncClient + +__all__ = ( + "CustomizerAttributeServiceClient", + "CustomizerAttributeServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/customizer_attribute_service/async_client.py b/google/ads/googleads/v24/services/services/customizer_attribute_service/async_client.py new file mode 100644 index 000000000..e0cfc7a86 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customizer_attribute_service/async_client.py @@ -0,0 +1,435 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import customizer_attribute_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CustomizerAttributeServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import CustomizerAttributeServiceClient + +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 CustomizerAttributeServiceAsyncClient: + """Service to manage customizer attribute""" + + _client: CustomizerAttributeServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = CustomizerAttributeServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + CustomizerAttributeServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + CustomizerAttributeServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = CustomizerAttributeServiceClient._DEFAULT_UNIVERSE + + customizer_attribute_path = staticmethod( + CustomizerAttributeServiceClient.customizer_attribute_path + ) + parse_customizer_attribute_path = staticmethod( + CustomizerAttributeServiceClient.parse_customizer_attribute_path + ) + common_billing_account_path = staticmethod( + CustomizerAttributeServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + CustomizerAttributeServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + CustomizerAttributeServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + CustomizerAttributeServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + CustomizerAttributeServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + CustomizerAttributeServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + CustomizerAttributeServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + CustomizerAttributeServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + CustomizerAttributeServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + CustomizerAttributeServiceClient.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: + CustomizerAttributeServiceAsyncClient: The constructed client. + """ + return CustomizerAttributeServiceClient.from_service_account_info.__func__(CustomizerAttributeServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CustomizerAttributeServiceAsyncClient: The constructed client. + """ + return CustomizerAttributeServiceClient.from_service_account_file.__func__(CustomizerAttributeServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return CustomizerAttributeServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> CustomizerAttributeServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomizerAttributeServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = CustomizerAttributeServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + CustomizerAttributeServiceTransport, + Callable[..., CustomizerAttributeServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customizer attribute 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,CustomizerAttributeServiceTransport,Callable[..., CustomizerAttributeServiceTransport]]]): + 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 CustomizerAttributeServiceTransport 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 = CustomizerAttributeServiceClient( + 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.ads.googleads.v24.services.CustomizerAttributeServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomizerAttributeService", + "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.ads.googleads.v24.services.CustomizerAttributeService", + "credentialsType": None, + } + ), + ) + + async def mutate_customizer_attributes( + self, + request: Optional[ + Union[ + customizer_attribute_service.MutateCustomizerAttributesRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + customizer_attribute_service.CustomizerAttributeOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customizer_attribute_service.MutateCustomizerAttributesResponse: + r"""Creates, updates or removes customizer attributes. + Operation statuses are returned. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateCustomizerAttributesRequest, dict]]): + The request object. Request message for + [CustomizerAttributeService.MutateCustomizerAttributes][google.ads.googleads.v24.services.CustomizerAttributeService.MutateCustomizerAttributes]. + customer_id (:class:`str`): + Required. The ID of the customer + whose customizer attributes are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.CustomizerAttributeOperation]`): + Required. The list of operations to + perform on individual customizer + attributes. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomizerAttributesResponse: + Response message for a customizer + attribute mutate. + + """ + # 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 = [customer_id, operations] + 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, + customizer_attribute_service.MutateCustomizerAttributesRequest, + ): + request = ( + customizer_attribute_service.MutateCustomizerAttributesRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_customizer_attributes + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "CustomizerAttributeServiceAsyncClient": + 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__ = ("CustomizerAttributeServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/customizer_attribute_service/client.py b/google/ads/googleads/v24/services/services/customizer_attribute_service/client.py new file mode 100644 index 000000000..ff8088ffd --- /dev/null +++ b/google/ads/googleads/v24/services/services/customizer_attribute_service/client.py @@ -0,0 +1,918 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import customizer_attribute_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CustomizerAttributeServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomizerAttributeServiceGrpcTransport +from .transports.grpc_asyncio import ( + CustomizerAttributeServiceGrpcAsyncIOTransport, +) + + +class CustomizerAttributeServiceClientMeta(type): + """Metaclass for the CustomizerAttributeService 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[CustomizerAttributeServiceTransport]] + _transport_registry["grpc"] = CustomizerAttributeServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + CustomizerAttributeServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomizerAttributeServiceTransport]: + """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 CustomizerAttributeServiceClient( + metaclass=CustomizerAttributeServiceClientMeta +): + """Service to manage customizer attribute""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + CustomizerAttributeServiceClient: 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: + CustomizerAttributeServiceClient: 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) -> CustomizerAttributeServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomizerAttributeServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customizer_attribute_path( + customer_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified customizer_attribute string.""" + return "customers/{customer_id}/customizerAttributes/{customizer_attribute_id}".format( + customer_id=customer_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_customizer_attribute_path(path: str) -> Dict[str, str]: + """Parses a customizer_attribute path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customizerAttributes/(?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 = ( + CustomizerAttributeServiceClient._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 = ( + CustomizerAttributeServiceClient._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 + ): + """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 = ( + CustomizerAttributeServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + CustomizerAttributeServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = CustomizerAttributeServiceClient._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 = CustomizerAttributeServiceClient._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): + """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, + CustomizerAttributeServiceTransport, + Callable[..., CustomizerAttributeServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the customizer attribute 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,CustomizerAttributeServiceTransport,Callable[..., CustomizerAttributeServiceTransport]]]): + 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 CustomizerAttributeServiceTransport 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, + ) = CustomizerAttributeServiceClient._read_environment_variables() + self._client_cert_source = ( + CustomizerAttributeServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + CustomizerAttributeServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, CustomizerAttributeServiceTransport + ) + if transport_provided: + # transport is a CustomizerAttributeServiceTransport 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( + CustomizerAttributeServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or CustomizerAttributeServiceClient._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[CustomizerAttributeServiceTransport], + Callable[..., CustomizerAttributeServiceTransport], + ] = ( + CustomizerAttributeServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., CustomizerAttributeServiceTransport], + 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.ads.googleads.v24.services.CustomizerAttributeServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.CustomizerAttributeService", + "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.ads.googleads.v24.services.CustomizerAttributeService", + "credentialsType": None, + } + ), + ) + + def mutate_customizer_attributes( + self, + request: Optional[ + Union[ + customizer_attribute_service.MutateCustomizerAttributesRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + customizer_attribute_service.CustomizerAttributeOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> customizer_attribute_service.MutateCustomizerAttributesResponse: + r"""Creates, updates or removes customizer attributes. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateCustomizerAttributesRequest, dict]): + The request object. Request message for + [CustomizerAttributeService.MutateCustomizerAttributes][google.ads.googleads.v24.services.CustomizerAttributeService.MutateCustomizerAttributes]. + customer_id (str): + Required. The ID of the customer + whose customizer attributes are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomizerAttributeOperation]): + Required. The list of operations to + perform on individual customizer + attributes. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateCustomizerAttributesResponse: + Response message for a customizer + attribute mutate. + + """ + # 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 = [customer_id, operations] + 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, + customizer_attribute_service.MutateCustomizerAttributesRequest, + ): + request = ( + customizer_attribute_service.MutateCustomizerAttributesRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_customizer_attributes + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "CustomizerAttributeServiceClient": + 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() + + +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__ = ("CustomizerAttributeServiceClient",) diff --git a/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/README.rst b/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/README.rst new file mode 100644 index 000000000..132aafcd9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`CustomizerAttributeServiceTransport` is the ABC for all transports. +- public child `CustomizerAttributeServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `CustomizerAttributeServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseCustomizerAttributeServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `CustomizerAttributeServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/__init__.py b/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/__init__.py new file mode 100644 index 000000000..17e465465 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import CustomizerAttributeServiceTransport +from .grpc import CustomizerAttributeServiceGrpcTransport +from .grpc_asyncio import CustomizerAttributeServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomizerAttributeServiceTransport]] +_transport_registry["grpc"] = CustomizerAttributeServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + CustomizerAttributeServiceGrpcAsyncIOTransport +) + +__all__ = ( + "CustomizerAttributeServiceTransport", + "CustomizerAttributeServiceGrpcTransport", + "CustomizerAttributeServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/base.py b/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/base.py new file mode 100644 index 000000000..d256d4ada --- /dev/null +++ b/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import customizer_attribute_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 CustomizerAttributeServiceTransport(abc.ABC): + """Abstract transport class for CustomizerAttributeService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customizer_attributes: gapic_v1.method.wrap_method( + self.mutate_customizer_attributes, + 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 mutate_customizer_attributes( + self, + ) -> Callable[ + [customizer_attribute_service.MutateCustomizerAttributesRequest], + Union[ + customizer_attribute_service.MutateCustomizerAttributesResponse, + Awaitable[ + customizer_attribute_service.MutateCustomizerAttributesResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("CustomizerAttributeServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/grpc.py b/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/grpc.py new file mode 100644 index 000000000..54009a770 --- /dev/null +++ b/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/grpc.py @@ -0,0 +1,386 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import customizer_attribute_service +from .base import CustomizerAttributeServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomizerAttributeService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomizerAttributeService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomizerAttributeServiceGrpcTransport( + CustomizerAttributeServiceTransport +): + """gRPC backend transport for CustomizerAttributeService. + + Service to manage customizer attribute + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_customizer_attributes( + self, + ) -> Callable[ + [customizer_attribute_service.MutateCustomizerAttributesRequest], + customizer_attribute_service.MutateCustomizerAttributesResponse, + ]: + r"""Return a callable for the mutate customizer attributes method over gRPC. + + Creates, updates or removes customizer attributes. + Operation statuses are returned. + + Returns: + Callable[[~.MutateCustomizerAttributesRequest], + ~.MutateCustomizerAttributesResponse]: + 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 "mutate_customizer_attributes" not in self._stubs: + self._stubs["mutate_customizer_attributes"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomizerAttributeService/MutateCustomizerAttributes", + request_serializer=customizer_attribute_service.MutateCustomizerAttributesRequest.serialize, + response_deserializer=customizer_attribute_service.MutateCustomizerAttributesResponse.deserialize, + ) + ) + return self._stubs["mutate_customizer_attributes"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("CustomizerAttributeServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..ad24b66ca --- /dev/null +++ b/google/ads/googleads/v24/services/services/customizer_attribute_service/transports/grpc_asyncio.py @@ -0,0 +1,409 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import customizer_attribute_service +from .base import CustomizerAttributeServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.CustomizerAttributeService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.CustomizerAttributeService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class CustomizerAttributeServiceGrpcAsyncIOTransport( + CustomizerAttributeServiceTransport +): + """gRPC AsyncIO backend transport for CustomizerAttributeService. + + Service to manage customizer attribute + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_customizer_attributes( + self, + ) -> Callable[ + [customizer_attribute_service.MutateCustomizerAttributesRequest], + Awaitable[ + customizer_attribute_service.MutateCustomizerAttributesResponse + ], + ]: + r"""Return a callable for the mutate customizer attributes method over gRPC. + + Creates, updates or removes customizer attributes. + Operation statuses are returned. + + Returns: + Callable[[~.MutateCustomizerAttributesRequest], + Awaitable[~.MutateCustomizerAttributesResponse]]: + 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 "mutate_customizer_attributes" not in self._stubs: + self._stubs["mutate_customizer_attributes"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.CustomizerAttributeService/MutateCustomizerAttributes", + request_serializer=customizer_attribute_service.MutateCustomizerAttributesRequest.serialize, + response_deserializer=customizer_attribute_service.MutateCustomizerAttributesResponse.deserialize, + ) + ) + return self._stubs["mutate_customizer_attributes"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_customizer_attributes: self._wrap_method( + self.mutate_customizer_attributes, + 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" + + +__all__ = ("CustomizerAttributeServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/data_link_service/__init__.py b/google/ads/googleads/v24/services/services/data_link_service/__init__.py new file mode 100644 index 000000000..6be943f5b --- /dev/null +++ b/google/ads/googleads/v24/services/services/data_link_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import DataLinkServiceClient +from .async_client import DataLinkServiceAsyncClient + +__all__ = ( + "DataLinkServiceClient", + "DataLinkServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/data_link_service/async_client.py b/google/ads/googleads/v24/services/services/data_link_service/async_client.py new file mode 100644 index 000000000..8c575a7bc --- /dev/null +++ b/google/ads/googleads/v24/services/services/data_link_service/async_client.py @@ -0,0 +1,645 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.enums.types import ( + data_link_status as gage_data_link_status, +) +from google.ads.googleads.v24.resources.types import data_link as gagr_data_link +from google.ads.googleads.v24.services.types import data_link_service +from .transports.base import DataLinkServiceTransport, DEFAULT_CLIENT_INFO +from .client import DataLinkServiceClient + +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 DataLinkServiceAsyncClient: + """This service allows management of data links between a + Google Ads customer and another data entity. + """ + + _client: DataLinkServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = DataLinkServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = DataLinkServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + DataLinkServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = DataLinkServiceClient._DEFAULT_UNIVERSE + + data_link_path = staticmethod(DataLinkServiceClient.data_link_path) + parse_data_link_path = staticmethod( + DataLinkServiceClient.parse_data_link_path + ) + common_billing_account_path = staticmethod( + DataLinkServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + DataLinkServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(DataLinkServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + DataLinkServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + DataLinkServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + DataLinkServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + DataLinkServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + DataLinkServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + DataLinkServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + DataLinkServiceClient.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: + DataLinkServiceAsyncClient: The constructed client. + """ + return DataLinkServiceClient.from_service_account_info.__func__(DataLinkServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + DataLinkServiceAsyncClient: The constructed client. + """ + return DataLinkServiceClient.from_service_account_file.__func__(DataLinkServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return DataLinkServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> DataLinkServiceTransport: + """Returns the transport used by the client instance. + + Returns: + DataLinkServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = DataLinkServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + DataLinkServiceTransport, + Callable[..., DataLinkServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the data link 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,DataLinkServiceTransport,Callable[..., DataLinkServiceTransport]]]): + 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 DataLinkServiceTransport 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 = DataLinkServiceClient( + 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.ads.googleads.v24.services.DataLinkServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.DataLinkService", + "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.ads.googleads.v24.services.DataLinkService", + "credentialsType": None, + } + ), + ) + + async def create_data_link( + self, + request: Optional[ + Union[data_link_service.CreateDataLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + data_link: Optional[gagr_data_link.DataLink] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> data_link_service.CreateDataLinkResponse: + r"""Creates a data link. The requesting Google Ads account name and + account ID will be shared with the third party (such as YouTube + creators for video links) to whom you are creating the link + with. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `DataLinkError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.CreateDataLinkRequest, dict]]): + The request object. Request message for + [DataLinkService.CreateDataLink][google.ads.googleads.v24.services.DataLinkService.CreateDataLink]. + customer_id (:class:`str`): + Required. The ID of the customer for + which the data link is created. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + data_link (:class:`google.ads.googleads.v24.resources.types.DataLink`): + Required. The data link to be + created. + + This corresponds to the ``data_link`` 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.ads.googleads.v24.services.types.CreateDataLinkResponse: + Response message for + [DataLinkService.CreateDataLink][google.ads.googleads.v24.services.DataLinkService.CreateDataLink]. + + """ + # 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 = [customer_id, data_link] + 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, data_link_service.CreateDataLinkRequest): + request = data_link_service.CreateDataLinkRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if data_link is not None: + request.data_link = data_link + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.create_data_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 remove_data_link( + self, + request: Optional[ + Union[data_link_service.RemoveDataLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + resource_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]]] = (), + ) -> data_link_service.RemoveDataLinkResponse: + r"""Remove a data link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `DataLinkError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.RemoveDataLinkRequest, dict]]): + The request object. Request message for + [DataLinkService.RemoveDataLink][google.ads.googleads.v24.services.DataLinkService.RemoveDataLink]. + customer_id (:class:`str`): + Required. The ID of the customer for + which the data link is updated. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource_name (:class:`str`): + Required. The data link is expected + to have a valid resource name. + + This corresponds to the ``resource_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.ads.googleads.v24.services.types.RemoveDataLinkResponse: + Response message for + [DataLinkService.RemoveDataLink][google.ads.googleads.v24.services.DataLinkService.RemoveDataLink]. + + """ + # 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 = [customer_id, resource_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, data_link_service.RemoveDataLinkRequest): + request = data_link_service.RemoveDataLinkRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.remove_data_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def update_data_link( + self, + request: Optional[ + Union[data_link_service.UpdateDataLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + data_link_status: Optional[ + gage_data_link_status.DataLinkStatusEnum.DataLinkStatus + ] = None, + resource_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]]] = (), + ) -> data_link_service.UpdateDataLinkResponse: + r"""Update a data link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `DataLinkError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.UpdateDataLinkRequest, dict]]): + The request object. Request message for + [DataLinkService.UpdateDataLink][google.ads.googleads.v24.services.DataLinkService.UpdateDataLink]. + customer_id (:class:`str`): + Required. The ID of the customer for + which the data link is created. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + data_link_status (:class:`google.ads.googleads.v24.enums.types.DataLinkStatusEnum.DataLinkStatus`): + Required. The data link status to be + updated to. + + This corresponds to the ``data_link_status`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource_name (:class:`str`): + Required. The data link is expected + to have a valid resource name. + + This corresponds to the ``resource_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.ads.googleads.v24.services.types.UpdateDataLinkResponse: + Response message for + [DataLinkService.UpdateDataLink][google.ads.googleads.v24.services.DataLinkService.UpdateDataLink]. + + """ + # 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 = [customer_id, data_link_status, resource_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, data_link_service.UpdateDataLinkRequest): + request = data_link_service.UpdateDataLinkRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if data_link_status is not None: + request.data_link_status = data_link_status + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_data_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "DataLinkServiceAsyncClient": + 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__ = ("DataLinkServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/data_link_service/client.py b/google/ads/googleads/v24/services/services/data_link_service/client.py new file mode 100644 index 000000000..ba2a079e0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/data_link_service/client.py @@ -0,0 +1,1097 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.enums.types import ( + data_link_status as gage_data_link_status, +) +from google.ads.googleads.v24.resources.types import data_link as gagr_data_link +from google.ads.googleads.v24.services.types import data_link_service +from .transports.base import DataLinkServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import DataLinkServiceGrpcTransport +from .transports.grpc_asyncio import DataLinkServiceGrpcAsyncIOTransport + + +class DataLinkServiceClientMeta(type): + """Metaclass for the DataLinkService 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[DataLinkServiceTransport]] + _transport_registry["grpc"] = DataLinkServiceGrpcTransport + _transport_registry["grpc_asyncio"] = DataLinkServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[DataLinkServiceTransport]: + """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 DataLinkServiceClient(metaclass=DataLinkServiceClientMeta): + """This service allows management of data links between a + Google Ads customer and another data entity. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + DataLinkServiceClient: 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: + DataLinkServiceClient: 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) -> DataLinkServiceTransport: + """Returns the transport used by the client instance. + + Returns: + DataLinkServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def data_link_path( + customer_id: str, + product_link_id: str, + data_link_id: str, + ) -> str: + """Returns a fully-qualified data_link string.""" + return "customers/{customer_id}/dataLinks/{product_link_id}~{data_link_id}".format( + customer_id=customer_id, + product_link_id=product_link_id, + data_link_id=data_link_id, + ) + + @staticmethod + def parse_data_link_path(path: str) -> Dict[str, str]: + """Parses a data_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/dataLinks/(?P.+?)~(?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 = DataLinkServiceClient._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 = DataLinkServiceClient._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 + ): + """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 = DataLinkServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = DataLinkServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + DataLinkServiceClient._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 = DataLinkServiceClient._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): + """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, + DataLinkServiceTransport, + Callable[..., DataLinkServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the data link 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,DataLinkServiceTransport,Callable[..., DataLinkServiceTransport]]]): + 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 DataLinkServiceTransport 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, + ) = DataLinkServiceClient._read_environment_variables() + self._client_cert_source = ( + DataLinkServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = DataLinkServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, DataLinkServiceTransport) + if transport_provided: + # transport is a DataLinkServiceTransport 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(DataLinkServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or DataLinkServiceClient._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[DataLinkServiceTransport], + Callable[..., DataLinkServiceTransport], + ] = ( + DataLinkServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., DataLinkServiceTransport], 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.ads.googleads.v24.services.DataLinkServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.DataLinkService", + "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.ads.googleads.v24.services.DataLinkService", + "credentialsType": None, + } + ), + ) + + def create_data_link( + self, + request: Optional[ + Union[data_link_service.CreateDataLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + data_link: Optional[gagr_data_link.DataLink] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> data_link_service.CreateDataLinkResponse: + r"""Creates a data link. The requesting Google Ads account name and + account ID will be shared with the third party (such as YouTube + creators for video links) to whom you are creating the link + with. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `DataLinkError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.CreateDataLinkRequest, dict]): + The request object. Request message for + [DataLinkService.CreateDataLink][google.ads.googleads.v24.services.DataLinkService.CreateDataLink]. + customer_id (str): + Required. The ID of the customer for + which the data link is created. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + data_link (google.ads.googleads.v24.resources.types.DataLink): + Required. The data link to be + created. + + This corresponds to the ``data_link`` 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.ads.googleads.v24.services.types.CreateDataLinkResponse: + Response message for + [DataLinkService.CreateDataLink][google.ads.googleads.v24.services.DataLinkService.CreateDataLink]. + + """ + # 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 = [customer_id, data_link] + 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, data_link_service.CreateDataLinkRequest): + request = data_link_service.CreateDataLinkRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if data_link is not None: + request.data_link = data_link + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.create_data_link] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 remove_data_link( + self, + request: Optional[ + Union[data_link_service.RemoveDataLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + resource_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]]] = (), + ) -> data_link_service.RemoveDataLinkResponse: + r"""Remove a data link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `DataLinkError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.RemoveDataLinkRequest, dict]): + The request object. Request message for + [DataLinkService.RemoveDataLink][google.ads.googleads.v24.services.DataLinkService.RemoveDataLink]. + customer_id (str): + Required. The ID of the customer for + which the data link is updated. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource_name (str): + Required. The data link is expected + to have a valid resource name. + + This corresponds to the ``resource_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.ads.googleads.v24.services.types.RemoveDataLinkResponse: + Response message for + [DataLinkService.RemoveDataLink][google.ads.googleads.v24.services.DataLinkService.RemoveDataLink]. + + """ + # 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 = [customer_id, resource_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, data_link_service.RemoveDataLinkRequest): + request = data_link_service.RemoveDataLinkRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.remove_data_link] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def update_data_link( + self, + request: Optional[ + Union[data_link_service.UpdateDataLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + data_link_status: Optional[ + gage_data_link_status.DataLinkStatusEnum.DataLinkStatus + ] = None, + resource_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]]] = (), + ) -> data_link_service.UpdateDataLinkResponse: + r"""Update a data link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `DataLinkError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.UpdateDataLinkRequest, dict]): + The request object. Request message for + [DataLinkService.UpdateDataLink][google.ads.googleads.v24.services.DataLinkService.UpdateDataLink]. + customer_id (str): + Required. The ID of the customer for + which the data link is created. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + data_link_status (google.ads.googleads.v24.enums.types.DataLinkStatusEnum.DataLinkStatus): + Required. The data link status to be + updated to. + + This corresponds to the ``data_link_status`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource_name (str): + Required. The data link is expected + to have a valid resource name. + + This corresponds to the ``resource_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.ads.googleads.v24.services.types.UpdateDataLinkResponse: + Response message for + [DataLinkService.UpdateDataLink][google.ads.googleads.v24.services.DataLinkService.UpdateDataLink]. + + """ + # 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 = [customer_id, data_link_status, resource_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, data_link_service.UpdateDataLinkRequest): + request = data_link_service.UpdateDataLinkRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if data_link_status is not None: + request.data_link_status = data_link_status + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.update_data_link] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "DataLinkServiceClient": + 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() + + +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__ = ("DataLinkServiceClient",) diff --git a/google/ads/googleads/v24/services/services/data_link_service/transports/README.rst b/google/ads/googleads/v24/services/services/data_link_service/transports/README.rst new file mode 100644 index 000000000..e74e7003b --- /dev/null +++ b/google/ads/googleads/v24/services/services/data_link_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`DataLinkServiceTransport` is the ABC for all transports. +- public child `DataLinkServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `DataLinkServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseDataLinkServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `DataLinkServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/data_link_service/transports/__init__.py b/google/ads/googleads/v24/services/services/data_link_service/transports/__init__.py new file mode 100644 index 000000000..cf59264c1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/data_link_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import DataLinkServiceTransport +from .grpc import DataLinkServiceGrpcTransport +from .grpc_asyncio import DataLinkServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[DataLinkServiceTransport]] +_transport_registry["grpc"] = DataLinkServiceGrpcTransport +_transport_registry["grpc_asyncio"] = DataLinkServiceGrpcAsyncIOTransport + +__all__ = ( + "DataLinkServiceTransport", + "DataLinkServiceGrpcTransport", + "DataLinkServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/data_link_service/transports/base.py b/google/ads/googleads/v24/services/services/data_link_service/transports/base.py new file mode 100644 index 000000000..79ef6b20e --- /dev/null +++ b/google/ads/googleads/v24/services/services/data_link_service/transports/base.py @@ -0,0 +1,207 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import data_link_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 DataLinkServiceTransport(abc.ABC): + """Abstract transport class for DataLinkService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.create_data_link: gapic_v1.method.wrap_method( + self.create_data_link, + default_timeout=None, + client_info=client_info, + ), + self.remove_data_link: gapic_v1.method.wrap_method( + self.remove_data_link, + default_timeout=None, + client_info=client_info, + ), + self.update_data_link: gapic_v1.method.wrap_method( + self.update_data_link, + 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 create_data_link( + self, + ) -> Callable[ + [data_link_service.CreateDataLinkRequest], + Union[ + data_link_service.CreateDataLinkResponse, + Awaitable[data_link_service.CreateDataLinkResponse], + ], + ]: + raise NotImplementedError() + + @property + def remove_data_link( + self, + ) -> Callable[ + [data_link_service.RemoveDataLinkRequest], + Union[ + data_link_service.RemoveDataLinkResponse, + Awaitable[data_link_service.RemoveDataLinkResponse], + ], + ]: + raise NotImplementedError() + + @property + def update_data_link( + self, + ) -> Callable[ + [data_link_service.UpdateDataLinkRequest], + Union[ + data_link_service.UpdateDataLinkResponse, + Awaitable[data_link_service.UpdateDataLinkResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("DataLinkServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/data_link_service/transports/grpc.py b/google/ads/googleads/v24/services/services/data_link_service/transports/grpc.py new file mode 100644 index 000000000..9c328631a --- /dev/null +++ b/google/ads/googleads/v24/services/services/data_link_service/transports/grpc.py @@ -0,0 +1,461 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import data_link_service +from .base import DataLinkServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.DataLinkService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.DataLinkService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class DataLinkServiceGrpcTransport(DataLinkServiceTransport): + """gRPC backend transport for DataLinkService. + + This service allows management of data links between a + Google Ads customer and another data entity. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 create_data_link( + self, + ) -> Callable[ + [data_link_service.CreateDataLinkRequest], + data_link_service.CreateDataLinkResponse, + ]: + r"""Return a callable for the create data link method over gRPC. + + Creates a data link. The requesting Google Ads account name and + account ID will be shared with the third party (such as YouTube + creators for video links) to whom you are creating the link + with. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `DataLinkError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.CreateDataLinkRequest], + ~.CreateDataLinkResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_data_link" not in self._stubs: + self._stubs["create_data_link"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.DataLinkService/CreateDataLink", + request_serializer=data_link_service.CreateDataLinkRequest.serialize, + response_deserializer=data_link_service.CreateDataLinkResponse.deserialize, + ) + return self._stubs["create_data_link"] + + @property + def remove_data_link( + self, + ) -> Callable[ + [data_link_service.RemoveDataLinkRequest], + data_link_service.RemoveDataLinkResponse, + ]: + r"""Return a callable for the remove data link method over gRPC. + + Remove a data link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `DataLinkError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.RemoveDataLinkRequest], + ~.RemoveDataLinkResponse]: + 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 "remove_data_link" not in self._stubs: + self._stubs["remove_data_link"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.DataLinkService/RemoveDataLink", + request_serializer=data_link_service.RemoveDataLinkRequest.serialize, + response_deserializer=data_link_service.RemoveDataLinkResponse.deserialize, + ) + return self._stubs["remove_data_link"] + + @property + def update_data_link( + self, + ) -> Callable[ + [data_link_service.UpdateDataLinkRequest], + data_link_service.UpdateDataLinkResponse, + ]: + r"""Return a callable for the update data link method over gRPC. + + Update a data link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `DataLinkError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.UpdateDataLinkRequest], + ~.UpdateDataLinkResponse]: + 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_data_link" not in self._stubs: + self._stubs["update_data_link"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.DataLinkService/UpdateDataLink", + request_serializer=data_link_service.UpdateDataLinkRequest.serialize, + response_deserializer=data_link_service.UpdateDataLinkResponse.deserialize, + ) + return self._stubs["update_data_link"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("DataLinkServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/data_link_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/data_link_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..3035b5f61 --- /dev/null +++ b/google/ads/googleads/v24/services/services/data_link_service/transports/grpc_asyncio.py @@ -0,0 +1,492 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import data_link_service +from .base import DataLinkServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.DataLinkService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.DataLinkService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class DataLinkServiceGrpcAsyncIOTransport(DataLinkServiceTransport): + """gRPC AsyncIO backend transport for DataLinkService. + + This service allows management of data links between a + Google Ads customer and another data entity. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 create_data_link( + self, + ) -> Callable[ + [data_link_service.CreateDataLinkRequest], + Awaitable[data_link_service.CreateDataLinkResponse], + ]: + r"""Return a callable for the create data link method over gRPC. + + Creates a data link. The requesting Google Ads account name and + account ID will be shared with the third party (such as YouTube + creators for video links) to whom you are creating the link + with. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `DataLinkError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.CreateDataLinkRequest], + Awaitable[~.CreateDataLinkResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_data_link" not in self._stubs: + self._stubs["create_data_link"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.DataLinkService/CreateDataLink", + request_serializer=data_link_service.CreateDataLinkRequest.serialize, + response_deserializer=data_link_service.CreateDataLinkResponse.deserialize, + ) + return self._stubs["create_data_link"] + + @property + def remove_data_link( + self, + ) -> Callable[ + [data_link_service.RemoveDataLinkRequest], + Awaitable[data_link_service.RemoveDataLinkResponse], + ]: + r"""Return a callable for the remove data link method over gRPC. + + Remove a data link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `DataLinkError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.RemoveDataLinkRequest], + Awaitable[~.RemoveDataLinkResponse]]: + 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 "remove_data_link" not in self._stubs: + self._stubs["remove_data_link"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.DataLinkService/RemoveDataLink", + request_serializer=data_link_service.RemoveDataLinkRequest.serialize, + response_deserializer=data_link_service.RemoveDataLinkResponse.deserialize, + ) + return self._stubs["remove_data_link"] + + @property + def update_data_link( + self, + ) -> Callable[ + [data_link_service.UpdateDataLinkRequest], + Awaitable[data_link_service.UpdateDataLinkResponse], + ]: + r"""Return a callable for the update data link method over gRPC. + + Update a data link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `DataLinkError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.UpdateDataLinkRequest], + Awaitable[~.UpdateDataLinkResponse]]: + 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_data_link" not in self._stubs: + self._stubs["update_data_link"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.DataLinkService/UpdateDataLink", + request_serializer=data_link_service.UpdateDataLinkRequest.serialize, + response_deserializer=data_link_service.UpdateDataLinkResponse.deserialize, + ) + return self._stubs["update_data_link"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.create_data_link: self._wrap_method( + self.create_data_link, + default_timeout=None, + client_info=client_info, + ), + self.remove_data_link: self._wrap_method( + self.remove_data_link, + default_timeout=None, + client_info=client_info, + ), + self.update_data_link: self._wrap_method( + self.update_data_link, + 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" + + +__all__ = ("DataLinkServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/experiment_arm_service/__init__.py b/google/ads/googleads/v24/services/services/experiment_arm_service/__init__.py new file mode 100644 index 000000000..ad612360d --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_arm_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ExperimentArmServiceClient +from .async_client import ExperimentArmServiceAsyncClient + +__all__ = ( + "ExperimentArmServiceClient", + "ExperimentArmServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/experiment_arm_service/async_client.py b/google/ads/googleads/v24/services/services/experiment_arm_service/async_client.py new file mode 100644 index 000000000..b14d90118 --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_arm_service/async_client.py @@ -0,0 +1,433 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import experiment_arm_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ExperimentArmServiceTransport, DEFAULT_CLIENT_INFO +from .client import ExperimentArmServiceClient + +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 ExperimentArmServiceAsyncClient: + """Service to manage experiment arms.""" + + _client: ExperimentArmServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ExperimentArmServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ExperimentArmServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + ExperimentArmServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ExperimentArmServiceClient._DEFAULT_UNIVERSE + + campaign_path = staticmethod(ExperimentArmServiceClient.campaign_path) + parse_campaign_path = staticmethod( + ExperimentArmServiceClient.parse_campaign_path + ) + experiment_path = staticmethod(ExperimentArmServiceClient.experiment_path) + parse_experiment_path = staticmethod( + ExperimentArmServiceClient.parse_experiment_path + ) + experiment_arm_path = staticmethod( + ExperimentArmServiceClient.experiment_arm_path + ) + parse_experiment_arm_path = staticmethod( + ExperimentArmServiceClient.parse_experiment_arm_path + ) + common_billing_account_path = staticmethod( + ExperimentArmServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ExperimentArmServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ExperimentArmServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ExperimentArmServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ExperimentArmServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ExperimentArmServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ExperimentArmServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ExperimentArmServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ExperimentArmServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ExperimentArmServiceClient.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: + ExperimentArmServiceAsyncClient: The constructed client. + """ + return ExperimentArmServiceClient.from_service_account_info.__func__(ExperimentArmServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ExperimentArmServiceAsyncClient: The constructed client. + """ + return ExperimentArmServiceClient.from_service_account_file.__func__(ExperimentArmServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ExperimentArmServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ExperimentArmServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ExperimentArmServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ExperimentArmServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ExperimentArmServiceTransport, + Callable[..., ExperimentArmServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the experiment arm 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,ExperimentArmServiceTransport,Callable[..., ExperimentArmServiceTransport]]]): + 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 ExperimentArmServiceTransport 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 = ExperimentArmServiceClient( + 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.ads.googleads.v24.services.ExperimentArmServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ExperimentArmService", + "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.ads.googleads.v24.services.ExperimentArmService", + "credentialsType": None, + } + ), + ) + + async def mutate_experiment_arms( + self, + request: Optional[ + Union[experiment_arm_service.MutateExperimentArmsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[experiment_arm_service.ExperimentArmOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> experiment_arm_service.MutateExperimentArmsResponse: + r"""Creates, updates, or removes experiment arms. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentArmError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateExperimentArmsRequest, dict]]): + The request object. Request message for + [ExperimentArmService.MutateExperimentArms][google.ads.googleads.v24.services.ExperimentArmService.MutateExperimentArms]. + customer_id (:class:`str`): + Required. The ID of the customer + whose experiments are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.ExperimentArmOperation]`): + Required. The list of operations to + perform on individual experiment arm. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateExperimentArmsResponse: + Response message for experiment arm + mutate. + + """ + # 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 = [customer_id, operations] + 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, experiment_arm_service.MutateExperimentArmsRequest + ): + request = experiment_arm_service.MutateExperimentArmsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_experiment_arms + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ExperimentArmServiceAsyncClient": + 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__ = ("ExperimentArmServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/experiment_arm_service/client.py b/google/ads/googleads/v24/services/services/experiment_arm_service/client.py new file mode 100644 index 000000000..e808c18c3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_arm_service/client.py @@ -0,0 +1,941 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import experiment_arm_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ExperimentArmServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import ExperimentArmServiceGrpcTransport +from .transports.grpc_asyncio import ExperimentArmServiceGrpcAsyncIOTransport + + +class ExperimentArmServiceClientMeta(type): + """Metaclass for the ExperimentArmService 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[ExperimentArmServiceTransport]] + _transport_registry["grpc"] = ExperimentArmServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + ExperimentArmServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ExperimentArmServiceTransport]: + """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 ExperimentArmServiceClient(metaclass=ExperimentArmServiceClientMeta): + """Service to manage experiment arms.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ExperimentArmServiceClient: 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: + ExperimentArmServiceClient: 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) -> ExperimentArmServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ExperimentArmServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def experiment_path( + customer_id: str, + trial_id: str, + ) -> str: + """Returns a fully-qualified experiment string.""" + return "customers/{customer_id}/experiments/{trial_id}".format( + customer_id=customer_id, + trial_id=trial_id, + ) + + @staticmethod + def parse_experiment_path(path: str) -> Dict[str, str]: + """Parses a experiment path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/experiments/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def experiment_arm_path( + customer_id: str, + trial_id: str, + trial_arm_id: str, + ) -> str: + """Returns a fully-qualified experiment_arm string.""" + return "customers/{customer_id}/experimentArms/{trial_id}~{trial_arm_id}".format( + customer_id=customer_id, + trial_id=trial_id, + trial_arm_id=trial_arm_id, + ) + + @staticmethod + def parse_experiment_arm_path(path: str) -> Dict[str, str]: + """Parses a experiment_arm path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/experimentArms/(?P.+?)~(?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 = ( + ExperimentArmServiceClient._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 = ( + ExperimentArmServiceClient._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 + ): + """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 = ExperimentArmServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ExperimentArmServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + ExperimentArmServiceClient._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 = ExperimentArmServiceClient._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): + """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, + ExperimentArmServiceTransport, + Callable[..., ExperimentArmServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the experiment arm 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,ExperimentArmServiceTransport,Callable[..., ExperimentArmServiceTransport]]]): + 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 ExperimentArmServiceTransport 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, + ) = ExperimentArmServiceClient._read_environment_variables() + self._client_cert_source = ( + ExperimentArmServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ExperimentArmServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ExperimentArmServiceTransport + ) + if transport_provided: + # transport is a ExperimentArmServiceTransport 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(ExperimentArmServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ExperimentArmServiceClient._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[ExperimentArmServiceTransport], + Callable[..., ExperimentArmServiceTransport], + ] = ( + ExperimentArmServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., ExperimentArmServiceTransport], 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.ads.googleads.v24.services.ExperimentArmServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ExperimentArmService", + "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.ads.googleads.v24.services.ExperimentArmService", + "credentialsType": None, + } + ), + ) + + def mutate_experiment_arms( + self, + request: Optional[ + Union[experiment_arm_service.MutateExperimentArmsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[experiment_arm_service.ExperimentArmOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> experiment_arm_service.MutateExperimentArmsResponse: + r"""Creates, updates, or removes experiment arms. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentArmError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateExperimentArmsRequest, dict]): + The request object. Request message for + [ExperimentArmService.MutateExperimentArms][google.ads.googleads.v24.services.ExperimentArmService.MutateExperimentArms]. + customer_id (str): + Required. The ID of the customer + whose experiments are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.ExperimentArmOperation]): + Required. The list of operations to + perform on individual experiment arm. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateExperimentArmsResponse: + Response message for experiment arm + mutate. + + """ + # 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 = [customer_id, operations] + 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, experiment_arm_service.MutateExperimentArmsRequest + ): + request = experiment_arm_service.MutateExperimentArmsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_experiment_arms + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "ExperimentArmServiceClient": + 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() + + +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__ = ("ExperimentArmServiceClient",) diff --git a/google/ads/googleads/v24/services/services/experiment_arm_service/transports/README.rst b/google/ads/googleads/v24/services/services/experiment_arm_service/transports/README.rst new file mode 100644 index 000000000..fa0ab7377 --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_arm_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ExperimentArmServiceTransport` is the ABC for all transports. +- public child `ExperimentArmServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ExperimentArmServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseExperimentArmServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ExperimentArmServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/experiment_arm_service/transports/__init__.py b/google/ads/googleads/v24/services/services/experiment_arm_service/transports/__init__.py new file mode 100644 index 000000000..4501cef09 --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_arm_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ExperimentArmServiceTransport +from .grpc import ExperimentArmServiceGrpcTransport +from .grpc_asyncio import ExperimentArmServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ExperimentArmServiceTransport]] +_transport_registry["grpc"] = ExperimentArmServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ExperimentArmServiceGrpcAsyncIOTransport + +__all__ = ( + "ExperimentArmServiceTransport", + "ExperimentArmServiceGrpcTransport", + "ExperimentArmServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/experiment_arm_service/transports/base.py b/google/ads/googleads/v24/services/services/experiment_arm_service/transports/base.py new file mode 100644 index 000000000..f0b176fcf --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_arm_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import experiment_arm_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 ExperimentArmServiceTransport(abc.ABC): + """Abstract transport class for ExperimentArmService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_experiment_arms: gapic_v1.method.wrap_method( + self.mutate_experiment_arms, + 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 mutate_experiment_arms( + self, + ) -> Callable[ + [experiment_arm_service.MutateExperimentArmsRequest], + Union[ + experiment_arm_service.MutateExperimentArmsResponse, + Awaitable[experiment_arm_service.MutateExperimentArmsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ExperimentArmServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/experiment_arm_service/transports/grpc.py b/google/ads/googleads/v24/services/services/experiment_arm_service/transports/grpc.py new file mode 100644 index 000000000..eb6b03e65 --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_arm_service/transports/grpc.py @@ -0,0 +1,389 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import experiment_arm_service +from .base import ExperimentArmServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ExperimentArmService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ExperimentArmService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ExperimentArmServiceGrpcTransport(ExperimentArmServiceTransport): + """gRPC backend transport for ExperimentArmService. + + Service to manage experiment arms. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_experiment_arms( + self, + ) -> Callable[ + [experiment_arm_service.MutateExperimentArmsRequest], + experiment_arm_service.MutateExperimentArmsResponse, + ]: + r"""Return a callable for the mutate experiment arms method over gRPC. + + Creates, updates, or removes experiment arms. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentArmError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateExperimentArmsRequest], + ~.MutateExperimentArmsResponse]: + 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 "mutate_experiment_arms" not in self._stubs: + self._stubs["mutate_experiment_arms"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ExperimentArmService/MutateExperimentArms", + request_serializer=experiment_arm_service.MutateExperimentArmsRequest.serialize, + response_deserializer=experiment_arm_service.MutateExperimentArmsResponse.deserialize, + ) + ) + return self._stubs["mutate_experiment_arms"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ExperimentArmServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/experiment_arm_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/experiment_arm_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..8225401da --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_arm_service/transports/grpc_asyncio.py @@ -0,0 +1,410 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import experiment_arm_service +from .base import ExperimentArmServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ExperimentArmService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ExperimentArmService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ExperimentArmServiceGrpcAsyncIOTransport(ExperimentArmServiceTransport): + """gRPC AsyncIO backend transport for ExperimentArmService. + + Service to manage experiment arms. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_experiment_arms( + self, + ) -> Callable[ + [experiment_arm_service.MutateExperimentArmsRequest], + Awaitable[experiment_arm_service.MutateExperimentArmsResponse], + ]: + r"""Return a callable for the mutate experiment arms method over gRPC. + + Creates, updates, or removes experiment arms. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentArmError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateExperimentArmsRequest], + Awaitable[~.MutateExperimentArmsResponse]]: + 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 "mutate_experiment_arms" not in self._stubs: + self._stubs["mutate_experiment_arms"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ExperimentArmService/MutateExperimentArms", + request_serializer=experiment_arm_service.MutateExperimentArmsRequest.serialize, + response_deserializer=experiment_arm_service.MutateExperimentArmsResponse.deserialize, + ) + ) + return self._stubs["mutate_experiment_arms"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_experiment_arms: self._wrap_method( + self.mutate_experiment_arms, + 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" + + +__all__ = ("ExperimentArmServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/experiment_service/__init__.py b/google/ads/googleads/v24/services/services/experiment_service/__init__.py new file mode 100644 index 000000000..e14fd8528 --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ExperimentServiceClient +from .async_client import ExperimentServiceAsyncClient + +__all__ = ( + "ExperimentServiceClient", + "ExperimentServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/experiment_service/async_client.py b/google/ads/googleads/v24/services/services/experiment_service/async_client.py new file mode 100644 index 000000000..e9f34a1f8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_service/async_client.py @@ -0,0 +1,977 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.services.experiment_service import pagers +from google.ads.googleads.v24.services.types import experiment_service +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore +from google.protobuf import empty_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore +from .transports.base import ExperimentServiceTransport, DEFAULT_CLIENT_INFO +from .client import ExperimentServiceClient + +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 ExperimentServiceAsyncClient: + """Service to manage experiments.""" + + _client: ExperimentServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ExperimentServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ExperimentServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + ExperimentServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ExperimentServiceClient._DEFAULT_UNIVERSE + + campaign_path = staticmethod(ExperimentServiceClient.campaign_path) + parse_campaign_path = staticmethod( + ExperimentServiceClient.parse_campaign_path + ) + campaign_budget_path = staticmethod( + ExperimentServiceClient.campaign_budget_path + ) + parse_campaign_budget_path = staticmethod( + ExperimentServiceClient.parse_campaign_budget_path + ) + experiment_path = staticmethod(ExperimentServiceClient.experiment_path) + parse_experiment_path = staticmethod( + ExperimentServiceClient.parse_experiment_path + ) + common_billing_account_path = staticmethod( + ExperimentServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ExperimentServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ExperimentServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ExperimentServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ExperimentServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ExperimentServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ExperimentServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ExperimentServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ExperimentServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ExperimentServiceClient.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: + ExperimentServiceAsyncClient: The constructed client. + """ + return ExperimentServiceClient.from_service_account_info.__func__(ExperimentServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ExperimentServiceAsyncClient: The constructed client. + """ + return ExperimentServiceClient.from_service_account_file.__func__(ExperimentServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ExperimentServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ExperimentServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ExperimentServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ExperimentServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ExperimentServiceTransport, + Callable[..., ExperimentServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the experiment 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,ExperimentServiceTransport,Callable[..., ExperimentServiceTransport]]]): + 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 ExperimentServiceTransport 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 = ExperimentServiceClient( + 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.ads.googleads.v24.services.ExperimentServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ExperimentService", + "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.ads.googleads.v24.services.ExperimentService", + "credentialsType": None, + } + ), + ) + + async def mutate_experiments( + self, + request: Optional[ + Union[experiment_service.MutateExperimentsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[experiment_service.ExperimentOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> experiment_service.MutateExperimentsResponse: + r"""Creates, updates, or removes experiments. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateExperimentsRequest, dict]]): + The request object. Request message for + [ExperimentService.MutateExperiments][google.ads.googleads.v24.services.ExperimentService.MutateExperiments]. + customer_id (:class:`str`): + Required. The ID of the customer + whose experiments are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.ExperimentOperation]`): + Required. The list of operations to + perform on individual experiments. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateExperimentsResponse: + Response message for experiment + mutate. + + """ + # 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 = [customer_id, operations] + 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, experiment_service.MutateExperimentsRequest): + request = experiment_service.MutateExperimentsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_experiments + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 end_experiment( + self, + request: Optional[ + Union[experiment_service.EndExperimentRequest, dict] + ] = None, + *, + experiment: 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"""Immediately ends an experiment, changing the experiment's + scheduled end date and without waiting for end of day. End date + is updated to be the time of the request. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.EndExperimentRequest, dict]]): + The request object. Request message for + [ExperimentService.EndExperiment][google.ads.googleads.v24.services.ExperimentService.EndExperiment]. + experiment (:class:`str`): + Required. The resource name of the + campaign experiment to end. + + This corresponds to the ``experiment`` 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 = [experiment] + 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, experiment_service.EndExperimentRequest): + request = experiment_service.EndExperimentRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if experiment is not None: + request.experiment = experiment + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.end_experiment + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("experiment", request.experiment),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + async def list_experiment_async_errors( + self, + request: Optional[ + Union[experiment_service.ListExperimentAsyncErrorsRequest, dict] + ] = None, + *, + resource_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]]] = (), + ) -> pagers.ListExperimentAsyncErrorsAsyncPager: + r"""Returns all errors that occurred during the last Experiment + update (either scheduling or promotion). Supports standard list + paging. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListExperimentAsyncErrorsRequest, dict]]): + The request object. Request message for + [ExperimentService.ListExperimentAsyncErrors][google.ads.googleads.v24.services.ExperimentService.ListExperimentAsyncErrors]. + resource_name (:class:`str`): + Required. The name of the experiment + from which to retrieve the async errors. + + This corresponds to the ``resource_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.ads.googleads.v24.services.services.experiment_service.pagers.ListExperimentAsyncErrorsAsyncPager: + Response message for + [ExperimentService.ListExperimentAsyncErrors][google.ads.googleads.v24.services.ExperimentService.ListExperimentAsyncErrors]. + + 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 = [resource_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, experiment_service.ListExperimentAsyncErrorsRequest + ): + request = experiment_service.ListExperimentAsyncErrorsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_experiment_async_errors + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_name),) + ), + ) + + # 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.ListExperimentAsyncErrorsAsyncPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def graduate_experiment( + self, + request: Optional[ + Union[experiment_service.GraduateExperimentRequest, dict] + ] = None, + *, + experiment: Optional[str] = None, + campaign_budget_mappings: Optional[ + MutableSequence[experiment_service.CampaignBudgetMapping] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Graduates an experiment to a full campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GraduateExperimentRequest, dict]]): + The request object. Request message for + [ExperimentService.GraduateExperiment][google.ads.googleads.v24.services.ExperimentService.GraduateExperiment]. + experiment (:class:`str`): + Required. The experiment to be + graduated. + + This corresponds to the ``experiment`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + campaign_budget_mappings (:class:`MutableSequence[google.ads.googleads.v24.services.types.CampaignBudgetMapping]`): + Required. List of campaign budget + mappings for graduation. Each campaign + that appears here will graduate, and + will be assigned a new budget that is + paired with it in the mapping. The + maximum size is one. + + This corresponds to the ``campaign_budget_mappings`` 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 = [experiment, campaign_budget_mappings] + 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, experiment_service.GraduateExperimentRequest + ): + request = experiment_service.GraduateExperimentRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if experiment is not None: + request.experiment = experiment + if campaign_budget_mappings: + request.campaign_budget_mappings.extend(campaign_budget_mappings) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.graduate_experiment + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("experiment", request.experiment),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + async def schedule_experiment( + self, + request: Optional[ + Union[experiment_service.ScheduleExperimentRequest, dict] + ] = None, + *, + resource_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]]] = (), + ) -> operation_async.AsyncOperation: + r"""Schedule an experiment. The in design campaign will be converted + into a real campaign (called the experiment campaign) that will + begin serving ads if successfully created. + + The experiment is scheduled immediately with status + INITIALIZING. This method returns a long running operation that + tracks the forking of the in design campaign. If the forking + fails, a list of errors can be retrieved using the + ListExperimentAsyncErrors method. The operation's metadata will + be a string containing the resource name of the created + experiment. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DateRangeError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ScheduleExperimentRequest, dict]]): + The request object. Request message for + [ExperimentService.ScheduleExperiment][google.ads.googleads.v24.services.ExperimentService.ScheduleExperiment]. + resource_name (:class:`str`): + Required. The scheduled experiment. + This corresponds to the ``resource_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.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 = [resource_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, experiment_service.ScheduleExperimentRequest + ): + request = experiment_service.ScheduleExperimentRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.schedule_experiment + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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=experiment_service.ScheduleExperimentMetadata, + ) + + # Done; return the response. + return response + + async def promote_experiment( + self, + request: Optional[ + Union[experiment_service.PromoteExperimentRequest, dict] + ] = None, + *, + resource_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]]] = (), + ) -> operation_async.AsyncOperation: + r"""Promotes the trial campaign thus applying changes in the trial + campaign to the base campaign. This method returns a long + running operation that tracks the promotion of the experiment + campaign. If it fails, a list of errors can be retrieved using + the ListExperimentAsyncErrors method. The operation's metadata + will be a string containing the resource name of the created + experiment. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.PromoteExperimentRequest, dict]]): + The request object. Request message for + [ExperimentService.PromoteExperiment][google.ads.googleads.v24.services.ExperimentService.PromoteExperiment]. + resource_name (:class:`str`): + Required. The resource name of the + experiment to promote. + + This corresponds to the ``resource_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.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 = [resource_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, experiment_service.PromoteExperimentRequest): + request = experiment_service.PromoteExperimentRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.promote_experiment + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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=experiment_service.PromoteExperimentMetadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ExperimentServiceAsyncClient": + 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__ = ("ExperimentServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/experiment_service/client.py b/google/ads/googleads/v24/services/services/experiment_service/client.py new file mode 100644 index 000000000..eef265da0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_service/client.py @@ -0,0 +1,1466 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.services.experiment_service import pagers +from google.ads.googleads.v24.services.types import experiment_service +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore +from google.protobuf import empty_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore +from .transports.base import ExperimentServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import ExperimentServiceGrpcTransport +from .transports.grpc_asyncio import ExperimentServiceGrpcAsyncIOTransport + + +class ExperimentServiceClientMeta(type): + """Metaclass for the ExperimentService 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[ExperimentServiceTransport]] + _transport_registry["grpc"] = ExperimentServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ExperimentServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ExperimentServiceTransport]: + """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 ExperimentServiceClient(metaclass=ExperimentServiceClientMeta): + """Service to manage experiments.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ExperimentServiceClient: 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: + ExperimentServiceClient: 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) -> ExperimentServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ExperimentServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_budget_path( + customer_id: str, + campaign_budget_id: str, + ) -> str: + """Returns a fully-qualified campaign_budget string.""" + return "customers/{customer_id}/campaignBudgets/{campaign_budget_id}".format( + customer_id=customer_id, + campaign_budget_id=campaign_budget_id, + ) + + @staticmethod + def parse_campaign_budget_path(path: str) -> Dict[str, str]: + """Parses a campaign_budget path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignBudgets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def experiment_path( + customer_id: str, + trial_id: str, + ) -> str: + """Returns a fully-qualified experiment string.""" + return "customers/{customer_id}/experiments/{trial_id}".format( + customer_id=customer_id, + trial_id=trial_id, + ) + + @staticmethod + def parse_experiment_path(path: str) -> Dict[str, str]: + """Parses a experiment path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/experiments/(?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 = ExperimentServiceClient._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 = ExperimentServiceClient._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 + ): + """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 = ExperimentServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ExperimentServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + ExperimentServiceClient._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 = ExperimentServiceClient._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): + """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, + ExperimentServiceTransport, + Callable[..., ExperimentServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the experiment 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,ExperimentServiceTransport,Callable[..., ExperimentServiceTransport]]]): + 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 ExperimentServiceTransport 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, + ) = ExperimentServiceClient._read_environment_variables() + self._client_cert_source = ( + ExperimentServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ExperimentServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ExperimentServiceTransport) + if transport_provided: + # transport is a ExperimentServiceTransport 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(ExperimentServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ExperimentServiceClient._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[ExperimentServiceTransport], + Callable[..., ExperimentServiceTransport], + ] = ( + ExperimentServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., ExperimentServiceTransport], 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.ads.googleads.v24.services.ExperimentServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ExperimentService", + "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.ads.googleads.v24.services.ExperimentService", + "credentialsType": None, + } + ), + ) + + def mutate_experiments( + self, + request: Optional[ + Union[experiment_service.MutateExperimentsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[experiment_service.ExperimentOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> experiment_service.MutateExperimentsResponse: + r"""Creates, updates, or removes experiments. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateExperimentsRequest, dict]): + The request object. Request message for + [ExperimentService.MutateExperiments][google.ads.googleads.v24.services.ExperimentService.MutateExperiments]. + customer_id (str): + Required. The ID of the customer + whose experiments are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.ExperimentOperation]): + Required. The list of operations to + perform on individual experiments. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateExperimentsResponse: + Response message for experiment + mutate. + + """ + # 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 = [customer_id, operations] + 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, experiment_service.MutateExperimentsRequest): + request = experiment_service.MutateExperimentsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_experiments + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 end_experiment( + self, + request: Optional[ + Union[experiment_service.EndExperimentRequest, dict] + ] = None, + *, + experiment: 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"""Immediately ends an experiment, changing the experiment's + scheduled end date and without waiting for end of day. End date + is updated to be the time of the request. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.EndExperimentRequest, dict]): + The request object. Request message for + [ExperimentService.EndExperiment][google.ads.googleads.v24.services.ExperimentService.EndExperiment]. + experiment (str): + Required. The resource name of the + campaign experiment to end. + + This corresponds to the ``experiment`` 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`. + """ + # 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 = [experiment] + 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, experiment_service.EndExperimentRequest): + request = experiment_service.EndExperimentRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if experiment is not None: + request.experiment = experiment + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.end_experiment] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("experiment", request.experiment),) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + def list_experiment_async_errors( + self, + request: Optional[ + Union[experiment_service.ListExperimentAsyncErrorsRequest, dict] + ] = None, + *, + resource_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]]] = (), + ) -> pagers.ListExperimentAsyncErrorsPager: + r"""Returns all errors that occurred during the last Experiment + update (either scheduling or promotion). Supports standard list + paging. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListExperimentAsyncErrorsRequest, dict]): + The request object. Request message for + [ExperimentService.ListExperimentAsyncErrors][google.ads.googleads.v24.services.ExperimentService.ListExperimentAsyncErrors]. + resource_name (str): + Required. The name of the experiment + from which to retrieve the async errors. + + This corresponds to the ``resource_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.ads.googleads.v24.services.services.experiment_service.pagers.ListExperimentAsyncErrorsPager: + Response message for + [ExperimentService.ListExperimentAsyncErrors][google.ads.googleads.v24.services.ExperimentService.ListExperimentAsyncErrors]. + + 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 = [resource_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, experiment_service.ListExperimentAsyncErrorsRequest + ): + request = experiment_service.ListExperimentAsyncErrorsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_experiment_async_errors + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_name),) + ), + ) + + # 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.ListExperimentAsyncErrorsPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def graduate_experiment( + self, + request: Optional[ + Union[experiment_service.GraduateExperimentRequest, dict] + ] = None, + *, + experiment: Optional[str] = None, + campaign_budget_mappings: Optional[ + MutableSequence[experiment_service.CampaignBudgetMapping] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Graduates an experiment to a full campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GraduateExperimentRequest, dict]): + The request object. Request message for + [ExperimentService.GraduateExperiment][google.ads.googleads.v24.services.ExperimentService.GraduateExperiment]. + experiment (str): + Required. The experiment to be + graduated. + + This corresponds to the ``experiment`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + campaign_budget_mappings (MutableSequence[google.ads.googleads.v24.services.types.CampaignBudgetMapping]): + Required. List of campaign budget + mappings for graduation. Each campaign + that appears here will graduate, and + will be assigned a new budget that is + paired with it in the mapping. The + maximum size is one. + + This corresponds to the ``campaign_budget_mappings`` 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`. + """ + # 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 = [experiment, campaign_budget_mappings] + 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, experiment_service.GraduateExperimentRequest + ): + request = experiment_service.GraduateExperimentRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if experiment is not None: + request.experiment = experiment + if campaign_budget_mappings is not None: + request.campaign_budget_mappings = campaign_budget_mappings + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.graduate_experiment + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("experiment", request.experiment),) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + def schedule_experiment( + self, + request: Optional[ + Union[experiment_service.ScheduleExperimentRequest, dict] + ] = None, + *, + resource_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]]] = (), + ) -> operation.Operation: + r"""Schedule an experiment. The in design campaign will be converted + into a real campaign (called the experiment campaign) that will + begin serving ads if successfully created. + + The experiment is scheduled immediately with status + INITIALIZING. This method returns a long running operation that + tracks the forking of the in design campaign. If the forking + fails, a list of errors can be retrieved using the + ListExperimentAsyncErrors method. The operation's metadata will + be a string containing the resource name of the created + experiment. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DateRangeError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ScheduleExperimentRequest, dict]): + The request object. Request message for + [ExperimentService.ScheduleExperiment][google.ads.googleads.v24.services.ExperimentService.ScheduleExperiment]. + resource_name (str): + Required. The scheduled experiment. + This corresponds to the ``resource_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.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 = [resource_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, experiment_service.ScheduleExperimentRequest + ): + request = experiment_service.ScheduleExperimentRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.schedule_experiment + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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=experiment_service.ScheduleExperimentMetadata, + ) + + # Done; return the response. + return response + + def promote_experiment( + self, + request: Optional[ + Union[experiment_service.PromoteExperimentRequest, dict] + ] = None, + *, + resource_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]]] = (), + ) -> operation.Operation: + r"""Promotes the trial campaign thus applying changes in the trial + campaign to the base campaign. This method returns a long + running operation that tracks the promotion of the experiment + campaign. If it fails, a list of errors can be retrieved using + the ListExperimentAsyncErrors method. The operation's metadata + will be a string containing the resource name of the created + experiment. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.PromoteExperimentRequest, dict]): + The request object. Request message for + [ExperimentService.PromoteExperiment][google.ads.googleads.v24.services.ExperimentService.PromoteExperiment]. + resource_name (str): + Required. The resource name of the + experiment to promote. + + This corresponds to the ``resource_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.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 = [resource_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, experiment_service.PromoteExperimentRequest): + request = experiment_service.PromoteExperimentRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.promote_experiment + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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=experiment_service.PromoteExperimentMetadata, + ) + + # Done; return the response. + return response + + def __enter__(self) -> "ExperimentServiceClient": + 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() + + +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__ = ("ExperimentServiceClient",) diff --git a/google/ads/googleads/v24/services/services/experiment_service/pagers.py b/google/ads/googleads/v24/services/services/experiment_service/pagers.py new file mode 100644 index 000000000..501fefc12 --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_service/pagers.py @@ -0,0 +1,208 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import retry_async as retries_async +from typing import ( + Any, + AsyncIterator, + Awaitable, + Callable, + Sequence, + Tuple, + Iterator, + Union, +) + +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.ads.googleads.v24.services.types import experiment_service +from google.rpc import status_pb2 # type: ignore + + +class ListExperimentAsyncErrorsPager: + """A pager for iterating through ``list_experiment_async_errors`` requests. + + This class thinly wraps an initial + :class:`google.ads.googleads.v24.services.types.ListExperimentAsyncErrorsResponse` object, and + provides an ``__iter__`` method to iterate through its + ``errors`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``ListExperimentAsyncErrors`` requests and continue to iterate + through the ``errors`` field on the + corresponding responses. + + All the usual :class:`google.ads.googleads.v24.services.types.ListExperimentAsyncErrorsResponse` + 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[ + ..., experiment_service.ListExperimentAsyncErrorsResponse + ], + request: experiment_service.ListExperimentAsyncErrorsRequest, + response: experiment_service.ListExperimentAsyncErrorsResponse, + *, + 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.ads.googleads.v24.services.types.ListExperimentAsyncErrorsRequest): + The initial request object. + response (google.ads.googleads.v24.services.types.ListExperimentAsyncErrorsResponse): + 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 = experiment_service.ListExperimentAsyncErrorsRequest( + 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[experiment_service.ListExperimentAsyncErrorsResponse]: + 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[status_pb2.Status]: + for page in self.pages: + yield from page.errors + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListExperimentAsyncErrorsAsyncPager: + """A pager for iterating through ``list_experiment_async_errors`` requests. + + This class thinly wraps an initial + :class:`google.ads.googleads.v24.services.types.ListExperimentAsyncErrorsResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``errors`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``ListExperimentAsyncErrors`` requests and continue to iterate + through the ``errors`` field on the + corresponding responses. + + All the usual :class:`google.ads.googleads.v24.services.types.ListExperimentAsyncErrorsResponse` + 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[experiment_service.ListExperimentAsyncErrorsResponse] + ], + request: experiment_service.ListExperimentAsyncErrorsRequest, + response: experiment_service.ListExperimentAsyncErrorsResponse, + *, + 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.ads.googleads.v24.services.types.ListExperimentAsyncErrorsRequest): + The initial request object. + response (google.ads.googleads.v24.services.types.ListExperimentAsyncErrorsResponse): + 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 = experiment_service.ListExperimentAsyncErrorsRequest( + 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[experiment_service.ListExperimentAsyncErrorsResponse]: + 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[status_pb2.Status]: + async def async_generator(): + async for page in self.pages: + for response in page.errors: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/google/ads/googleads/v24/services/services/experiment_service/transports/README.rst b/google/ads/googleads/v24/services/services/experiment_service/transports/README.rst new file mode 100644 index 000000000..4d175aed8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ExperimentServiceTransport` is the ABC for all transports. +- public child `ExperimentServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ExperimentServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseExperimentServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ExperimentServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/experiment_service/transports/__init__.py b/google/ads/googleads/v24/services/services/experiment_service/transports/__init__.py new file mode 100644 index 000000000..6155460f5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ExperimentServiceTransport +from .grpc import ExperimentServiceGrpcTransport +from .grpc_asyncio import ExperimentServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ExperimentServiceTransport]] +_transport_registry["grpc"] = ExperimentServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ExperimentServiceGrpcAsyncIOTransport + +__all__ = ( + "ExperimentServiceTransport", + "ExperimentServiceGrpcTransport", + "ExperimentServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/experiment_service/transports/base.py b/google/ads/googleads/v24/services/services/experiment_service/transports/base.py new file mode 100644 index 000000000..d43acca16 --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_service/transports/base.py @@ -0,0 +1,253 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import experiment_service +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import empty_pb2 # type: ignore + +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 ExperimentServiceTransport(abc.ABC): + """Abstract transport class for ExperimentService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_experiments: gapic_v1.method.wrap_method( + self.mutate_experiments, + default_timeout=None, + client_info=client_info, + ), + self.end_experiment: gapic_v1.method.wrap_method( + self.end_experiment, + default_timeout=None, + client_info=client_info, + ), + self.list_experiment_async_errors: gapic_v1.method.wrap_method( + self.list_experiment_async_errors, + default_timeout=None, + client_info=client_info, + ), + self.graduate_experiment: gapic_v1.method.wrap_method( + self.graduate_experiment, + default_timeout=None, + client_info=client_info, + ), + self.schedule_experiment: gapic_v1.method.wrap_method( + self.schedule_experiment, + default_timeout=None, + client_info=client_info, + ), + self.promote_experiment: gapic_v1.method.wrap_method( + self.promote_experiment, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def operations_client(self): + """Return the client designed to process long-running operations.""" + raise NotImplementedError() + + @property + def mutate_experiments( + self, + ) -> Callable[ + [experiment_service.MutateExperimentsRequest], + Union[ + experiment_service.MutateExperimentsResponse, + Awaitable[experiment_service.MutateExperimentsResponse], + ], + ]: + raise NotImplementedError() + + @property + def end_experiment( + self, + ) -> Callable[ + [experiment_service.EndExperimentRequest], + Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]], + ]: + raise NotImplementedError() + + @property + def list_experiment_async_errors( + self, + ) -> Callable[ + [experiment_service.ListExperimentAsyncErrorsRequest], + Union[ + experiment_service.ListExperimentAsyncErrorsResponse, + Awaitable[experiment_service.ListExperimentAsyncErrorsResponse], + ], + ]: + raise NotImplementedError() + + @property + def graduate_experiment( + self, + ) -> Callable[ + [experiment_service.GraduateExperimentRequest], + Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]], + ]: + raise NotImplementedError() + + @property + def schedule_experiment( + self, + ) -> Callable[ + [experiment_service.ScheduleExperimentRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def promote_experiment( + self, + ) -> Callable[ + [experiment_service.PromoteExperimentRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ExperimentServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/experiment_service/transports/grpc.py b/google/ads/googleads/v24/services/services/experiment_service/transports/grpc.py new file mode 100644 index 000000000..22c293cd3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_service/transports/grpc.py @@ -0,0 +1,601 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import experiment_service +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import empty_pb2 # type: ignore +from .base import ExperimentServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ExperimentService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ExperimentService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ExperimentServiceGrpcTransport(ExperimentServiceTransport): + """gRPC backend transport for ExperimentService. + + Service to manage experiments. + + 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 = "googleads.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: 'googleads.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. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client: Optional[operations_v1.OperationsClient] = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if 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 = "googleads.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 operations_client(self) -> operations_v1.OperationsClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Quick check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsClient( + self._logged_channel + ) + + # Return the client from cache. + return self._operations_client + + @property + def mutate_experiments( + self, + ) -> Callable[ + [experiment_service.MutateExperimentsRequest], + experiment_service.MutateExperimentsResponse, + ]: + r"""Return a callable for the mutate experiments method over gRPC. + + Creates, updates, or removes experiments. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateExperimentsRequest], + ~.MutateExperimentsResponse]: + 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 "mutate_experiments" not in self._stubs: + self._stubs["mutate_experiments"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ExperimentService/MutateExperiments", + request_serializer=experiment_service.MutateExperimentsRequest.serialize, + response_deserializer=experiment_service.MutateExperimentsResponse.deserialize, + ) + ) + return self._stubs["mutate_experiments"] + + @property + def end_experiment( + self, + ) -> Callable[[experiment_service.EndExperimentRequest], empty_pb2.Empty]: + r"""Return a callable for the end experiment method over gRPC. + + Immediately ends an experiment, changing the experiment's + scheduled end date and without waiting for end of day. End date + is updated to be the time of the request. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.EndExperimentRequest], + ~.Empty]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "end_experiment" not in self._stubs: + self._stubs["end_experiment"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ExperimentService/EndExperiment", + request_serializer=experiment_service.EndExperimentRequest.serialize, + response_deserializer=empty_pb2.Empty.FromString, + ) + return self._stubs["end_experiment"] + + @property + def list_experiment_async_errors( + self, + ) -> Callable[ + [experiment_service.ListExperimentAsyncErrorsRequest], + experiment_service.ListExperimentAsyncErrorsResponse, + ]: + r"""Return a callable for the list experiment async errors method over gRPC. + + Returns all errors that occurred during the last Experiment + update (either scheduling or promotion). Supports standard list + paging. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListExperimentAsyncErrorsRequest], + ~.ListExperimentAsyncErrorsResponse]: + 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_experiment_async_errors" not in self._stubs: + self._stubs["list_experiment_async_errors"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ExperimentService/ListExperimentAsyncErrors", + request_serializer=experiment_service.ListExperimentAsyncErrorsRequest.serialize, + response_deserializer=experiment_service.ListExperimentAsyncErrorsResponse.deserialize, + ) + ) + return self._stubs["list_experiment_async_errors"] + + @property + def graduate_experiment( + self, + ) -> Callable[ + [experiment_service.GraduateExperimentRequest], empty_pb2.Empty + ]: + r"""Return a callable for the graduate experiment method over gRPC. + + Graduates an experiment to a full campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GraduateExperimentRequest], + ~.Empty]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "graduate_experiment" not in self._stubs: + self._stubs["graduate_experiment"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ExperimentService/GraduateExperiment", + request_serializer=experiment_service.GraduateExperimentRequest.serialize, + response_deserializer=empty_pb2.Empty.FromString, + ) + ) + return self._stubs["graduate_experiment"] + + @property + def schedule_experiment( + self, + ) -> Callable[ + [experiment_service.ScheduleExperimentRequest], operations_pb2.Operation + ]: + r"""Return a callable for the schedule experiment method over gRPC. + + Schedule an experiment. The in design campaign will be converted + into a real campaign (called the experiment campaign) that will + begin serving ads if successfully created. + + The experiment is scheduled immediately with status + INITIALIZING. This method returns a long running operation that + tracks the forking of the in design campaign. If the forking + fails, a list of errors can be retrieved using the + ListExperimentAsyncErrors method. The operation's metadata will + be a string containing the resource name of the created + experiment. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DateRangeError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ScheduleExperimentRequest], + ~.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 "schedule_experiment" not in self._stubs: + self._stubs["schedule_experiment"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ExperimentService/ScheduleExperiment", + request_serializer=experiment_service.ScheduleExperimentRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + ) + return self._stubs["schedule_experiment"] + + @property + def promote_experiment( + self, + ) -> Callable[ + [experiment_service.PromoteExperimentRequest], operations_pb2.Operation + ]: + r"""Return a callable for the promote experiment method over gRPC. + + Promotes the trial campaign thus applying changes in the trial + campaign to the base campaign. This method returns a long + running operation that tracks the promotion of the experiment + campaign. If it fails, a list of errors can be retrieved using + the ListExperimentAsyncErrors method. The operation's metadata + will be a string containing the resource name of the created + experiment. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.PromoteExperimentRequest], + ~.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 "promote_experiment" not in self._stubs: + self._stubs["promote_experiment"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ExperimentService/PromoteExperiment", + request_serializer=experiment_service.PromoteExperimentRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + ) + return self._stubs["promote_experiment"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ExperimentServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/experiment_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/experiment_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..ab4613230 --- /dev/null +++ b/google/ads/googleads/v24/services/services/experiment_service/transports/grpc_asyncio.py @@ -0,0 +1,654 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import experiment_service +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import empty_pb2 # type: ignore +from .base import ExperimentServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ExperimentService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ExperimentService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ExperimentServiceGrpcAsyncIOTransport(ExperimentServiceTransport): + """gRPC AsyncIO backend transport for ExperimentService. + + Service to manage experiments. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client: Optional[ + operations_v1.OperationsAsyncClient + ] = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if 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 operations_client(self) -> operations_v1.OperationsAsyncClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Quick check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsAsyncClient( + self._logged_channel + ) + + # Return the client from cache. + return self._operations_client + + @property + def mutate_experiments( + self, + ) -> Callable[ + [experiment_service.MutateExperimentsRequest], + Awaitable[experiment_service.MutateExperimentsResponse], + ]: + r"""Return a callable for the mutate experiments method over gRPC. + + Creates, updates, or removes experiments. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateExperimentsRequest], + Awaitable[~.MutateExperimentsResponse]]: + 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 "mutate_experiments" not in self._stubs: + self._stubs["mutate_experiments"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ExperimentService/MutateExperiments", + request_serializer=experiment_service.MutateExperimentsRequest.serialize, + response_deserializer=experiment_service.MutateExperimentsResponse.deserialize, + ) + ) + return self._stubs["mutate_experiments"] + + @property + def end_experiment( + self, + ) -> Callable[ + [experiment_service.EndExperimentRequest], Awaitable[empty_pb2.Empty] + ]: + r"""Return a callable for the end experiment method over gRPC. + + Immediately ends an experiment, changing the experiment's + scheduled end date and without waiting for end of day. End date + is updated to be the time of the request. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.EndExperimentRequest], + Awaitable[~.Empty]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "end_experiment" not in self._stubs: + self._stubs["end_experiment"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ExperimentService/EndExperiment", + request_serializer=experiment_service.EndExperimentRequest.serialize, + response_deserializer=empty_pb2.Empty.FromString, + ) + return self._stubs["end_experiment"] + + @property + def list_experiment_async_errors( + self, + ) -> Callable[ + [experiment_service.ListExperimentAsyncErrorsRequest], + Awaitable[experiment_service.ListExperimentAsyncErrorsResponse], + ]: + r"""Return a callable for the list experiment async errors method over gRPC. + + Returns all errors that occurred during the last Experiment + update (either scheduling or promotion). Supports standard list + paging. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListExperimentAsyncErrorsRequest], + Awaitable[~.ListExperimentAsyncErrorsResponse]]: + 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_experiment_async_errors" not in self._stubs: + self._stubs["list_experiment_async_errors"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ExperimentService/ListExperimentAsyncErrors", + request_serializer=experiment_service.ListExperimentAsyncErrorsRequest.serialize, + response_deserializer=experiment_service.ListExperimentAsyncErrorsResponse.deserialize, + ) + ) + return self._stubs["list_experiment_async_errors"] + + @property + def graduate_experiment( + self, + ) -> Callable[ + [experiment_service.GraduateExperimentRequest], + Awaitable[empty_pb2.Empty], + ]: + r"""Return a callable for the graduate experiment method over gRPC. + + Graduates an experiment to a full campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GraduateExperimentRequest], + Awaitable[~.Empty]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "graduate_experiment" not in self._stubs: + self._stubs["graduate_experiment"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ExperimentService/GraduateExperiment", + request_serializer=experiment_service.GraduateExperimentRequest.serialize, + response_deserializer=empty_pb2.Empty.FromString, + ) + ) + return self._stubs["graduate_experiment"] + + @property + def schedule_experiment( + self, + ) -> Callable[ + [experiment_service.ScheduleExperimentRequest], + Awaitable[operations_pb2.Operation], + ]: + r"""Return a callable for the schedule experiment method over gRPC. + + Schedule an experiment. The in design campaign will be converted + into a real campaign (called the experiment campaign) that will + begin serving ads if successfully created. + + The experiment is scheduled immediately with status + INITIALIZING. This method returns a long running operation that + tracks the forking of the in design campaign. If the forking + fails, a list of errors can be retrieved using the + ListExperimentAsyncErrors method. The operation's metadata will + be a string containing the resource name of the created + experiment. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DateRangeError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ScheduleExperimentRequest], + 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 "schedule_experiment" not in self._stubs: + self._stubs["schedule_experiment"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ExperimentService/ScheduleExperiment", + request_serializer=experiment_service.ScheduleExperimentRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + ) + return self._stubs["schedule_experiment"] + + @property + def promote_experiment( + self, + ) -> Callable[ + [experiment_service.PromoteExperimentRequest], + Awaitable[operations_pb2.Operation], + ]: + r"""Return a callable for the promote experiment method over gRPC. + + Promotes the trial campaign thus applying changes in the trial + campaign to the base campaign. This method returns a long + running operation that tracks the promotion of the experiment + campaign. If it fails, a list of errors can be retrieved using + the ListExperimentAsyncErrors method. The operation's metadata + will be a string containing the resource name of the created + experiment. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ExperimentError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.PromoteExperimentRequest], + 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 "promote_experiment" not in self._stubs: + self._stubs["promote_experiment"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ExperimentService/PromoteExperiment", + request_serializer=experiment_service.PromoteExperimentRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + ) + return self._stubs["promote_experiment"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_experiments: self._wrap_method( + self.mutate_experiments, + default_timeout=None, + client_info=client_info, + ), + self.end_experiment: self._wrap_method( + self.end_experiment, + default_timeout=None, + client_info=client_info, + ), + self.list_experiment_async_errors: self._wrap_method( + self.list_experiment_async_errors, + default_timeout=None, + client_info=client_info, + ), + self.graduate_experiment: self._wrap_method( + self.graduate_experiment, + default_timeout=None, + client_info=client_info, + ), + self.schedule_experiment: self._wrap_method( + self.schedule_experiment, + default_timeout=None, + client_info=client_info, + ), + self.promote_experiment: self._wrap_method( + self.promote_experiment, + 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" + + +__all__ = ("ExperimentServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/geo_target_constant_service/__init__.py b/google/ads/googleads/v24/services/services/geo_target_constant_service/__init__.py new file mode 100644 index 000000000..619d428da --- /dev/null +++ b/google/ads/googleads/v24/services/services/geo_target_constant_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import GeoTargetConstantServiceClient +from .async_client import GeoTargetConstantServiceAsyncClient + +__all__ = ( + "GeoTargetConstantServiceClient", + "GeoTargetConstantServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/geo_target_constant_service/async_client.py b/google/ads/googleads/v24/services/services/geo_target_constant_service/async_client.py new file mode 100644 index 000000000..0789893dd --- /dev/null +++ b/google/ads/googleads/v24/services/services/geo_target_constant_service/async_client.py @@ -0,0 +1,388 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import geo_target_constant_service +from .transports.base import ( + GeoTargetConstantServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import GeoTargetConstantServiceClient + +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 GeoTargetConstantServiceAsyncClient: + """Service to fetch geo target constants.""" + + _client: GeoTargetConstantServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = GeoTargetConstantServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = GeoTargetConstantServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + GeoTargetConstantServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = GeoTargetConstantServiceClient._DEFAULT_UNIVERSE + + geo_target_constant_path = staticmethod( + GeoTargetConstantServiceClient.geo_target_constant_path + ) + parse_geo_target_constant_path = staticmethod( + GeoTargetConstantServiceClient.parse_geo_target_constant_path + ) + common_billing_account_path = staticmethod( + GeoTargetConstantServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GeoTargetConstantServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + GeoTargetConstantServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + GeoTargetConstantServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + GeoTargetConstantServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GeoTargetConstantServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + GeoTargetConstantServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + GeoTargetConstantServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + GeoTargetConstantServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + GeoTargetConstantServiceClient.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: + GeoTargetConstantServiceAsyncClient: The constructed client. + """ + return GeoTargetConstantServiceClient.from_service_account_info.__func__(GeoTargetConstantServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GeoTargetConstantServiceAsyncClient: The constructed client. + """ + return GeoTargetConstantServiceClient.from_service_account_file.__func__(GeoTargetConstantServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return GeoTargetConstantServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> GeoTargetConstantServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GeoTargetConstantServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = GeoTargetConstantServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + GeoTargetConstantServiceTransport, + Callable[..., GeoTargetConstantServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the geo target constant 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,GeoTargetConstantServiceTransport,Callable[..., GeoTargetConstantServiceTransport]]]): + 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 GeoTargetConstantServiceTransport 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 = GeoTargetConstantServiceClient( + 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.ads.googleads.v24.services.GeoTargetConstantServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.GeoTargetConstantService", + "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.ads.googleads.v24.services.GeoTargetConstantService", + "credentialsType": None, + } + ), + ) + + async def suggest_geo_target_constants( + self, + request: Optional[ + Union[ + geo_target_constant_service.SuggestGeoTargetConstantsRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> geo_target_constant_service.SuggestGeoTargetConstantsResponse: + r"""Returns GeoTargetConstant suggestions by location name or by + resource name. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ + `GeoTargetConstantSuggestionError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.SuggestGeoTargetConstantsRequest, dict]]): + The request object. Request message for + [GeoTargetConstantService.SuggestGeoTargetConstants][google.ads.googleads.v24.services.GeoTargetConstantService.SuggestGeoTargetConstants]. + 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.googleads.v24.services.types.SuggestGeoTargetConstantsResponse: + Response message for + [GeoTargetConstantService.SuggestGeoTargetConstants][google.ads.googleads.v24.services.GeoTargetConstantService.SuggestGeoTargetConstants]. + + """ + # 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, + geo_target_constant_service.SuggestGeoTargetConstantsRequest, + ): + request = ( + geo_target_constant_service.SuggestGeoTargetConstantsRequest( + request + ) + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.suggest_geo_target_constants + ] + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "GeoTargetConstantServiceAsyncClient": + 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__ = ("GeoTargetConstantServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/geo_target_constant_service/client.py b/google/ads/googleads/v24/services/services/geo_target_constant_service/client.py new file mode 100644 index 000000000..3ac0da1bd --- /dev/null +++ b/google/ads/googleads/v24/services/services/geo_target_constant_service/client.py @@ -0,0 +1,852 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import geo_target_constant_service +from .transports.base import ( + GeoTargetConstantServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import GeoTargetConstantServiceGrpcTransport +from .transports.grpc_asyncio import ( + GeoTargetConstantServiceGrpcAsyncIOTransport, +) + + +class GeoTargetConstantServiceClientMeta(type): + """Metaclass for the GeoTargetConstantService 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[GeoTargetConstantServiceTransport]] + _transport_registry["grpc"] = GeoTargetConstantServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + GeoTargetConstantServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[GeoTargetConstantServiceTransport]: + """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 GeoTargetConstantServiceClient( + metaclass=GeoTargetConstantServiceClientMeta +): + """Service to fetch geo target constants.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + GeoTargetConstantServiceClient: 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: + GeoTargetConstantServiceClient: 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) -> GeoTargetConstantServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GeoTargetConstantServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def geo_target_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified geo_target_constant string.""" + return "geoTargetConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_geo_target_constant_path(path: str) -> Dict[str, str]: + """Parses a geo_target_constant path into its component segments.""" + m = re.match(r"^geoTargetConstants/(?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 = ( + GeoTargetConstantServiceClient._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 = ( + GeoTargetConstantServiceClient._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 + ): + """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 = GeoTargetConstantServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = GeoTargetConstantServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = GeoTargetConstantServiceClient._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 = GeoTargetConstantServiceClient._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): + """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, + GeoTargetConstantServiceTransport, + Callable[..., GeoTargetConstantServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the geo target constant 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,GeoTargetConstantServiceTransport,Callable[..., GeoTargetConstantServiceTransport]]]): + 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 GeoTargetConstantServiceTransport 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, + ) = GeoTargetConstantServiceClient._read_environment_variables() + self._client_cert_source = ( + GeoTargetConstantServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + GeoTargetConstantServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, GeoTargetConstantServiceTransport + ) + if transport_provided: + # transport is a GeoTargetConstantServiceTransport 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(GeoTargetConstantServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or GeoTargetConstantServiceClient._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[GeoTargetConstantServiceTransport], + Callable[..., GeoTargetConstantServiceTransport], + ] = ( + GeoTargetConstantServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., GeoTargetConstantServiceTransport], 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.ads.googleads.v24.services.GeoTargetConstantServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.GeoTargetConstantService", + "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.ads.googleads.v24.services.GeoTargetConstantService", + "credentialsType": None, + } + ), + ) + + def suggest_geo_target_constants( + self, + request: Optional[ + Union[ + geo_target_constant_service.SuggestGeoTargetConstantsRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> geo_target_constant_service.SuggestGeoTargetConstantsResponse: + r"""Returns GeoTargetConstant suggestions by location name or by + resource name. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ + `GeoTargetConstantSuggestionError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.SuggestGeoTargetConstantsRequest, dict]): + The request object. Request message for + [GeoTargetConstantService.SuggestGeoTargetConstants][google.ads.googleads.v24.services.GeoTargetConstantService.SuggestGeoTargetConstants]. + 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.googleads.v24.services.types.SuggestGeoTargetConstantsResponse: + Response message for + [GeoTargetConstantService.SuggestGeoTargetConstants][google.ads.googleads.v24.services.GeoTargetConstantService.SuggestGeoTargetConstants]. + + """ + # 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, + geo_target_constant_service.SuggestGeoTargetConstantsRequest, + ): + request = ( + geo_target_constant_service.SuggestGeoTargetConstantsRequest( + request + ) + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.suggest_geo_target_constants + ] + + # 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) -> "GeoTargetConstantServiceClient": + 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() + + +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__ = ("GeoTargetConstantServiceClient",) diff --git a/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/README.rst b/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/README.rst new file mode 100644 index 000000000..d77692ff9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`GeoTargetConstantServiceTransport` is the ABC for all transports. +- public child `GeoTargetConstantServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `GeoTargetConstantServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseGeoTargetConstantServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `GeoTargetConstantServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/__init__.py b/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/__init__.py new file mode 100644 index 000000000..bfd5c7eec --- /dev/null +++ b/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import GeoTargetConstantServiceTransport +from .grpc import GeoTargetConstantServiceGrpcTransport +from .grpc_asyncio import GeoTargetConstantServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[GeoTargetConstantServiceTransport]] +_transport_registry["grpc"] = GeoTargetConstantServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + GeoTargetConstantServiceGrpcAsyncIOTransport +) + +__all__ = ( + "GeoTargetConstantServiceTransport", + "GeoTargetConstantServiceGrpcTransport", + "GeoTargetConstantServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/base.py b/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/base.py new file mode 100644 index 000000000..8c177ff6b --- /dev/null +++ b/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import geo_target_constant_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 GeoTargetConstantServiceTransport(abc.ABC): + """Abstract transport class for GeoTargetConstantService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.suggest_geo_target_constants: gapic_v1.method.wrap_method( + self.suggest_geo_target_constants, + 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 suggest_geo_target_constants( + self, + ) -> Callable[ + [geo_target_constant_service.SuggestGeoTargetConstantsRequest], + Union[ + geo_target_constant_service.SuggestGeoTargetConstantsResponse, + Awaitable[ + geo_target_constant_service.SuggestGeoTargetConstantsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("GeoTargetConstantServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/grpc.py b/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/grpc.py new file mode 100644 index 000000000..d6eb6b28a --- /dev/null +++ b/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/grpc.py @@ -0,0 +1,389 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import geo_target_constant_service +from .base import GeoTargetConstantServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.GeoTargetConstantService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.GeoTargetConstantService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class GeoTargetConstantServiceGrpcTransport(GeoTargetConstantServiceTransport): + """gRPC backend transport for GeoTargetConstantService. + + Service to fetch geo target constants. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 suggest_geo_target_constants( + self, + ) -> Callable[ + [geo_target_constant_service.SuggestGeoTargetConstantsRequest], + geo_target_constant_service.SuggestGeoTargetConstantsResponse, + ]: + r"""Return a callable for the suggest geo target constants method over gRPC. + + Returns GeoTargetConstant suggestions by location name or by + resource name. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ + `GeoTargetConstantSuggestionError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.SuggestGeoTargetConstantsRequest], + ~.SuggestGeoTargetConstantsResponse]: + 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 "suggest_geo_target_constants" not in self._stubs: + self._stubs["suggest_geo_target_constants"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.GeoTargetConstantService/SuggestGeoTargetConstants", + request_serializer=geo_target_constant_service.SuggestGeoTargetConstantsRequest.serialize, + response_deserializer=geo_target_constant_service.SuggestGeoTargetConstantsResponse.deserialize, + ) + ) + return self._stubs["suggest_geo_target_constants"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("GeoTargetConstantServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..bdca00be7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/geo_target_constant_service/transports/grpc_asyncio.py @@ -0,0 +1,414 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import geo_target_constant_service +from .base import GeoTargetConstantServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.GeoTargetConstantService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.GeoTargetConstantService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class GeoTargetConstantServiceGrpcAsyncIOTransport( + GeoTargetConstantServiceTransport +): + """gRPC AsyncIO backend transport for GeoTargetConstantService. + + Service to fetch geo target constants. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 suggest_geo_target_constants( + self, + ) -> Callable[ + [geo_target_constant_service.SuggestGeoTargetConstantsRequest], + Awaitable[ + geo_target_constant_service.SuggestGeoTargetConstantsResponse + ], + ]: + r"""Return a callable for the suggest geo target constants method over gRPC. + + Returns GeoTargetConstant suggestions by location name or by + resource name. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ + `GeoTargetConstantSuggestionError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.SuggestGeoTargetConstantsRequest], + Awaitable[~.SuggestGeoTargetConstantsResponse]]: + 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 "suggest_geo_target_constants" not in self._stubs: + self._stubs["suggest_geo_target_constants"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.GeoTargetConstantService/SuggestGeoTargetConstants", + request_serializer=geo_target_constant_service.SuggestGeoTargetConstantsRequest.serialize, + response_deserializer=geo_target_constant_service.SuggestGeoTargetConstantsResponse.deserialize, + ) + ) + return self._stubs["suggest_geo_target_constants"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.suggest_geo_target_constants: self._wrap_method( + self.suggest_geo_target_constants, + 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" + + +__all__ = ("GeoTargetConstantServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/goal_service/__init__.py b/google/ads/googleads/v24/services/services/goal_service/__init__.py new file mode 100644 index 000000000..f4aca1827 --- /dev/null +++ b/google/ads/googleads/v24/services/services/goal_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import GoalServiceClient +from .async_client import GoalServiceAsyncClient + +__all__ = ( + "GoalServiceClient", + "GoalServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/goal_service/async_client.py b/google/ads/googleads/v24/services/services/goal_service/async_client.py new file mode 100644 index 000000000..c86d1a03f --- /dev/null +++ b/google/ads/googleads/v24/services/services/goal_service/async_client.py @@ -0,0 +1,404 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import goal_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import GoalServiceTransport, DEFAULT_CLIENT_INFO +from .client import GoalServiceClient + +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 GoalServiceAsyncClient: + """Service to manage goals.""" + + _client: GoalServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = GoalServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = GoalServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = GoalServiceClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = GoalServiceClient._DEFAULT_UNIVERSE + + customer_path = staticmethod(GoalServiceClient.customer_path) + parse_customer_path = staticmethod(GoalServiceClient.parse_customer_path) + goal_path = staticmethod(GoalServiceClient.goal_path) + parse_goal_path = staticmethod(GoalServiceClient.parse_goal_path) + common_billing_account_path = staticmethod( + GoalServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GoalServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(GoalServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + GoalServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + GoalServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GoalServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod(GoalServiceClient.common_project_path) + parse_common_project_path = staticmethod( + GoalServiceClient.parse_common_project_path + ) + common_location_path = staticmethod(GoalServiceClient.common_location_path) + parse_common_location_path = staticmethod( + GoalServiceClient.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: + GoalServiceAsyncClient: The constructed client. + """ + return GoalServiceClient.from_service_account_info.__func__(GoalServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GoalServiceAsyncClient: The constructed client. + """ + return GoalServiceClient.from_service_account_file.__func__(GoalServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return GoalServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> GoalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GoalServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = GoalServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, GoalServiceTransport, Callable[..., GoalServiceTransport] + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the goal 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,GoalServiceTransport,Callable[..., GoalServiceTransport]]]): + 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 GoalServiceTransport 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 = GoalServiceClient( + 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.ads.googleads.v24.services.GoalServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.GoalService", + "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.ads.googleads.v24.services.GoalService", + "credentialsType": None, + } + ), + ) + + async def mutate_goals( + self, + request: Optional[Union[goal_service.MutateGoalsRequest, dict]] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[goal_service.GoalOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> goal_service.MutateGoalsResponse: + r"""Create or update goals. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + `GoalError <>`__ `GoalServicesError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateGoalsRequest, dict]]): + The request object. Request message for + [GoalService.MutateGoals][google.ads.googleads.v24.services.GoalService.MutateGoals]. + customer_id (:class:`str`): + Required. The ID of the customer + whose goals are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.GoalOperation]`): + Required. The list of operations to + perform on the goals. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateGoalsResponse: + Response message for a goal mutate. + """ + # 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 = [customer_id, operations] + 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, goal_service.MutateGoalsRequest): + request = goal_service.MutateGoalsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_goals + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "GoalServiceAsyncClient": + 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__ = ("GoalServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/goal_service/client.py b/google/ads/googleads/v24/services/services/goal_service/client.py new file mode 100644 index 000000000..67ae7d9e5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/goal_service/client.py @@ -0,0 +1,886 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import goal_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import GoalServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import GoalServiceGrpcTransport +from .transports.grpc_asyncio import GoalServiceGrpcAsyncIOTransport + + +class GoalServiceClientMeta(type): + """Metaclass for the GoalService 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[GoalServiceTransport]] + _transport_registry["grpc"] = GoalServiceGrpcTransport + _transport_registry["grpc_asyncio"] = GoalServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[GoalServiceTransport]: + """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 GoalServiceClient(metaclass=GoalServiceClientMeta): + """Service to manage goals.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + GoalServiceClient: 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: + GoalServiceClient: 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) -> GoalServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GoalServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def goal_path( + customer_id: str, + unified_goal_id: str, + ) -> str: + """Returns a fully-qualified goal string.""" + return "customers/{customer_id}/goals/{unified_goal_id}".format( + customer_id=customer_id, + unified_goal_id=unified_goal_id, + ) + + @staticmethod + def parse_goal_path(path: str) -> Dict[str, str]: + """Parses a goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/goals/(?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 = GoalServiceClient._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 = GoalServiceClient._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 + ): + """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 = GoalServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = GoalServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = GoalServiceClient._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 = GoalServiceClient._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): + """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, GoalServiceTransport, Callable[..., GoalServiceTransport] + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the goal 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,GoalServiceTransport,Callable[..., GoalServiceTransport]]]): + 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 GoalServiceTransport 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, + ) = GoalServiceClient._read_environment_variables() + self._client_cert_source = GoalServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = GoalServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, GoalServiceTransport) + if transport_provided: + # transport is a GoalServiceTransport 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(GoalServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or GoalServiceClient._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[GoalServiceTransport], Callable[..., GoalServiceTransport] + ] = ( + GoalServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., GoalServiceTransport], 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.ads.googleads.v24.services.GoalServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.GoalService", + "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.ads.googleads.v24.services.GoalService", + "credentialsType": None, + } + ), + ) + + def mutate_goals( + self, + request: Optional[Union[goal_service.MutateGoalsRequest, dict]] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[goal_service.GoalOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> goal_service.MutateGoalsResponse: + r"""Create or update goals. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + `GoalError <>`__ `GoalServicesError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateGoalsRequest, dict]): + The request object. Request message for + [GoalService.MutateGoals][google.ads.googleads.v24.services.GoalService.MutateGoals]. + customer_id (str): + Required. The ID of the customer + whose goals are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.GoalOperation]): + Required. The list of operations to + perform on the goals. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateGoalsResponse: + Response message for a goal mutate. + """ + # 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 = [customer_id, operations] + 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, goal_service.MutateGoalsRequest): + request = goal_service.MutateGoalsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.mutate_goals] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "GoalServiceClient": + 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() + + +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__ = ("GoalServiceClient",) diff --git a/google/ads/googleads/v24/services/services/goal_service/transports/README.rst b/google/ads/googleads/v24/services/services/goal_service/transports/README.rst new file mode 100644 index 000000000..829459e5e --- /dev/null +++ b/google/ads/googleads/v24/services/services/goal_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`GoalServiceTransport` is the ABC for all transports. +- public child `GoalServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `GoalServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseGoalServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `GoalServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/goal_service/transports/__init__.py b/google/ads/googleads/v24/services/services/goal_service/transports/__init__.py new file mode 100644 index 000000000..bad9461b5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/goal_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import GoalServiceTransport +from .grpc import GoalServiceGrpcTransport +from .grpc_asyncio import GoalServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[GoalServiceTransport]] +_transport_registry["grpc"] = GoalServiceGrpcTransport +_transport_registry["grpc_asyncio"] = GoalServiceGrpcAsyncIOTransport + +__all__ = ( + "GoalServiceTransport", + "GoalServiceGrpcTransport", + "GoalServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/goal_service/transports/base.py b/google/ads/googleads/v24/services/services/goal_service/transports/base.py new file mode 100644 index 000000000..3faab43d1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/goal_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import goal_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 GoalServiceTransport(abc.ABC): + """Abstract transport class for GoalService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_goals: gapic_v1.method.wrap_method( + self.mutate_goals, + 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 mutate_goals( + self, + ) -> Callable[ + [goal_service.MutateGoalsRequest], + Union[ + goal_service.MutateGoalsResponse, + Awaitable[goal_service.MutateGoalsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("GoalServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/goal_service/transports/grpc.py b/google/ads/googleads/v24/services/services/goal_service/transports/grpc.py new file mode 100644 index 000000000..baa021152 --- /dev/null +++ b/google/ads/googleads/v24/services/services/goal_service/transports/grpc.py @@ -0,0 +1,385 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import goal_service +from .base import GoalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.GoalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.GoalService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class GoalServiceGrpcTransport(GoalServiceTransport): + """gRPC backend transport for GoalService. + + Service to manage goals. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_goals( + self, + ) -> Callable[ + [goal_service.MutateGoalsRequest], goal_service.MutateGoalsResponse + ]: + r"""Return a callable for the mutate goals method over gRPC. + + Create or update goals. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + `GoalError <>`__ `GoalServicesError <>`__ + + Returns: + Callable[[~.MutateGoalsRequest], + ~.MutateGoalsResponse]: + 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 "mutate_goals" not in self._stubs: + self._stubs["mutate_goals"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.GoalService/MutateGoals", + request_serializer=goal_service.MutateGoalsRequest.serialize, + response_deserializer=goal_service.MutateGoalsResponse.deserialize, + ) + return self._stubs["mutate_goals"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("GoalServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/goal_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/goal_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..d79ef27d3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/goal_service/transports/grpc_asyncio.py @@ -0,0 +1,407 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import goal_service +from .base import GoalServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.GoalService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.GoalService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class GoalServiceGrpcAsyncIOTransport(GoalServiceTransport): + """gRPC AsyncIO backend transport for GoalService. + + Service to manage goals. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_goals( + self, + ) -> Callable[ + [goal_service.MutateGoalsRequest], + Awaitable[goal_service.MutateGoalsResponse], + ]: + r"""Return a callable for the mutate goals method over gRPC. + + Create or update goals. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + `GoalError <>`__ `GoalServicesError <>`__ + + Returns: + Callable[[~.MutateGoalsRequest], + Awaitable[~.MutateGoalsResponse]]: + 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 "mutate_goals" not in self._stubs: + self._stubs["mutate_goals"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.GoalService/MutateGoals", + request_serializer=goal_service.MutateGoalsRequest.serialize, + response_deserializer=goal_service.MutateGoalsResponse.deserialize, + ) + return self._stubs["mutate_goals"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_goals: self._wrap_method( + self.mutate_goals, + 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" + + +__all__ = ("GoalServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/google_ads_field_service/__init__.py b/google/ads/googleads/v24/services/services/google_ads_field_service/__init__.py new file mode 100644 index 000000000..906ecac6c --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_field_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import GoogleAdsFieldServiceClient +from .async_client import GoogleAdsFieldServiceAsyncClient + +__all__ = ( + "GoogleAdsFieldServiceClient", + "GoogleAdsFieldServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/google_ads_field_service/async_client.py b/google/ads/googleads/v24/services/services/google_ads_field_service/async_client.py new file mode 100644 index 000000000..fe0869df1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_field_service/async_client.py @@ -0,0 +1,514 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.resources.types import google_ads_field +from google.ads.googleads.v24.services.services.google_ads_field_service import ( + pagers, +) +from google.ads.googleads.v24.services.types import google_ads_field_service +from .transports.base import GoogleAdsFieldServiceTransport, DEFAULT_CLIENT_INFO +from .client import GoogleAdsFieldServiceClient + +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 GoogleAdsFieldServiceAsyncClient: + """Service to fetch Google Ads API fields.""" + + _client: GoogleAdsFieldServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = GoogleAdsFieldServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = GoogleAdsFieldServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + GoogleAdsFieldServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = GoogleAdsFieldServiceClient._DEFAULT_UNIVERSE + + google_ads_field_path = staticmethod( + GoogleAdsFieldServiceClient.google_ads_field_path + ) + parse_google_ads_field_path = staticmethod( + GoogleAdsFieldServiceClient.parse_google_ads_field_path + ) + common_billing_account_path = staticmethod( + GoogleAdsFieldServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GoogleAdsFieldServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + GoogleAdsFieldServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + GoogleAdsFieldServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + GoogleAdsFieldServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GoogleAdsFieldServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + GoogleAdsFieldServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + GoogleAdsFieldServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + GoogleAdsFieldServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + GoogleAdsFieldServiceClient.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: + GoogleAdsFieldServiceAsyncClient: The constructed client. + """ + return GoogleAdsFieldServiceClient.from_service_account_info.__func__(GoogleAdsFieldServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GoogleAdsFieldServiceAsyncClient: The constructed client. + """ + return GoogleAdsFieldServiceClient.from_service_account_file.__func__(GoogleAdsFieldServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return GoogleAdsFieldServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> GoogleAdsFieldServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GoogleAdsFieldServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = GoogleAdsFieldServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + GoogleAdsFieldServiceTransport, + Callable[..., GoogleAdsFieldServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the google ads field 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,GoogleAdsFieldServiceTransport,Callable[..., GoogleAdsFieldServiceTransport]]]): + 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 GoogleAdsFieldServiceTransport 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 = GoogleAdsFieldServiceClient( + 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.ads.googleads.v24.services.GoogleAdsFieldServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.GoogleAdsFieldService", + "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.ads.googleads.v24.services.GoogleAdsFieldService", + "credentialsType": None, + } + ), + ) + + async def get_google_ads_field( + self, + request: Optional[ + Union[google_ads_field_service.GetGoogleAdsFieldRequest, dict] + ] = None, + *, + resource_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]]] = (), + ) -> google_ads_field.GoogleAdsField: + r"""Returns just the requested field. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GetGoogleAdsFieldRequest, dict]]): + The request object. Request message for + [GoogleAdsFieldService.GetGoogleAdsField][google.ads.googleads.v24.services.GoogleAdsFieldService.GetGoogleAdsField]. + resource_name (:class:`str`): + Required. The resource name of the + field to get. + + This corresponds to the ``resource_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.ads.googleads.v24.resources.types.GoogleAdsField: + A field or resource (artifact) used + by GoogleAdsService. + + """ + # 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 = [resource_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, google_ads_field_service.GetGoogleAdsFieldRequest + ): + request = google_ads_field_service.GetGoogleAdsFieldRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_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_google_ads_field + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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 search_google_ads_fields( + self, + request: Optional[ + Union[google_ads_field_service.SearchGoogleAdsFieldsRequest, dict] + ] = None, + *, + query: 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.SearchGoogleAdsFieldsAsyncPager: + r"""Returns all fields that match the search query. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QueryError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.SearchGoogleAdsFieldsRequest, dict]]): + The request object. Request message for + [GoogleAdsFieldService.SearchGoogleAdsFields][google.ads.googleads.v24.services.GoogleAdsFieldService.SearchGoogleAdsFields]. + query (:class:`str`): + Required. The query string. + This corresponds to the ``query`` 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.ads.googleads.v24.services.services.google_ads_field_service.pagers.SearchGoogleAdsFieldsAsyncPager: + Response message for + [GoogleAdsFieldService.SearchGoogleAdsFields][google.ads.googleads.v24.services.GoogleAdsFieldService.SearchGoogleAdsFields]. + + 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 = [query] + 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, google_ads_field_service.SearchGoogleAdsFieldsRequest + ): + request = google_ads_field_service.SearchGoogleAdsFieldsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if query is not None: + request.query = query + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.search_google_ads_fields + ] + + # 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.SearchGoogleAdsFieldsAsyncPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "GoogleAdsFieldServiceAsyncClient": + 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__ = ("GoogleAdsFieldServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/google_ads_field_service/client.py b/google/ads/googleads/v24/services/services/google_ads_field_service/client.py new file mode 100644 index 000000000..627eda660 --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_field_service/client.py @@ -0,0 +1,974 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.resources.types import google_ads_field +from google.ads.googleads.v24.services.services.google_ads_field_service import ( + pagers, +) +from google.ads.googleads.v24.services.types import google_ads_field_service +from .transports.base import GoogleAdsFieldServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import GoogleAdsFieldServiceGrpcTransport +from .transports.grpc_asyncio import GoogleAdsFieldServiceGrpcAsyncIOTransport + + +class GoogleAdsFieldServiceClientMeta(type): + """Metaclass for the GoogleAdsFieldService 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[GoogleAdsFieldServiceTransport]] + _transport_registry["grpc"] = GoogleAdsFieldServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + GoogleAdsFieldServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[GoogleAdsFieldServiceTransport]: + """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 GoogleAdsFieldServiceClient(metaclass=GoogleAdsFieldServiceClientMeta): + """Service to fetch Google Ads API fields.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + GoogleAdsFieldServiceClient: 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: + GoogleAdsFieldServiceClient: 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) -> GoogleAdsFieldServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GoogleAdsFieldServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def google_ads_field_path( + google_ads_field: str, + ) -> str: + """Returns a fully-qualified google_ads_field string.""" + return "googleAdsFields/{google_ads_field}".format( + google_ads_field=google_ads_field, + ) + + @staticmethod + def parse_google_ads_field_path(path: str) -> Dict[str, str]: + """Parses a google_ads_field path into its component segments.""" + m = re.match(r"^googleAdsFields/(?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 = ( + GoogleAdsFieldServiceClient._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 = ( + GoogleAdsFieldServiceClient._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 + ): + """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 = GoogleAdsFieldServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = GoogleAdsFieldServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + GoogleAdsFieldServiceClient._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 = GoogleAdsFieldServiceClient._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): + """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, + GoogleAdsFieldServiceTransport, + Callable[..., GoogleAdsFieldServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the google ads field 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,GoogleAdsFieldServiceTransport,Callable[..., GoogleAdsFieldServiceTransport]]]): + 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 GoogleAdsFieldServiceTransport 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, + ) = GoogleAdsFieldServiceClient._read_environment_variables() + self._client_cert_source = ( + GoogleAdsFieldServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + GoogleAdsFieldServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, GoogleAdsFieldServiceTransport + ) + if transport_provided: + # transport is a GoogleAdsFieldServiceTransport 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(GoogleAdsFieldServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or GoogleAdsFieldServiceClient._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[GoogleAdsFieldServiceTransport], + Callable[..., GoogleAdsFieldServiceTransport], + ] = ( + GoogleAdsFieldServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., GoogleAdsFieldServiceTransport], 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.ads.googleads.v24.services.GoogleAdsFieldServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.GoogleAdsFieldService", + "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.ads.googleads.v24.services.GoogleAdsFieldService", + "credentialsType": None, + } + ), + ) + + def get_google_ads_field( + self, + request: Optional[ + Union[google_ads_field_service.GetGoogleAdsFieldRequest, dict] + ] = None, + *, + resource_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]]] = (), + ) -> google_ads_field.GoogleAdsField: + r"""Returns just the requested field. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GetGoogleAdsFieldRequest, dict]): + The request object. Request message for + [GoogleAdsFieldService.GetGoogleAdsField][google.ads.googleads.v24.services.GoogleAdsFieldService.GetGoogleAdsField]. + resource_name (str): + Required. The resource name of the + field to get. + + This corresponds to the ``resource_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.ads.googleads.v24.resources.types.GoogleAdsField: + A field or resource (artifact) used + by GoogleAdsService. + + """ + # 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 = [resource_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, google_ads_field_service.GetGoogleAdsFieldRequest + ): + request = google_ads_field_service.GetGoogleAdsFieldRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.get_google_ads_field + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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 search_google_ads_fields( + self, + request: Optional[ + Union[google_ads_field_service.SearchGoogleAdsFieldsRequest, dict] + ] = None, + *, + query: 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.SearchGoogleAdsFieldsPager: + r"""Returns all fields that match the search query. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QueryError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.SearchGoogleAdsFieldsRequest, dict]): + The request object. Request message for + [GoogleAdsFieldService.SearchGoogleAdsFields][google.ads.googleads.v24.services.GoogleAdsFieldService.SearchGoogleAdsFields]. + query (str): + Required. The query string. + This corresponds to the ``query`` 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.ads.googleads.v24.services.services.google_ads_field_service.pagers.SearchGoogleAdsFieldsPager: + Response message for + [GoogleAdsFieldService.SearchGoogleAdsFields][google.ads.googleads.v24.services.GoogleAdsFieldService.SearchGoogleAdsFields]. + + 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 = [query] + 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, google_ads_field_service.SearchGoogleAdsFieldsRequest + ): + request = google_ads_field_service.SearchGoogleAdsFieldsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if query is not None: + request.query = query + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.search_google_ads_fields + ] + + # 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.SearchGoogleAdsFieldsPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def __enter__(self) -> "GoogleAdsFieldServiceClient": + 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() + + +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__ = ("GoogleAdsFieldServiceClient",) diff --git a/google/ads/googleads/v24/services/services/google_ads_field_service/pagers.py b/google/ads/googleads/v24/services/services/google_ads_field_service/pagers.py new file mode 100644 index 000000000..a45fc75c2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_field_service/pagers.py @@ -0,0 +1,209 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import retry_async as retries_async +from typing import ( + Any, + AsyncIterator, + Awaitable, + Callable, + Sequence, + Tuple, + Iterator, + Union, +) + +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.ads.googleads.v24.resources.types import google_ads_field +from google.ads.googleads.v24.services.types import google_ads_field_service + + +class SearchGoogleAdsFieldsPager: + """A pager for iterating through ``search_google_ads_fields`` requests. + + This class thinly wraps an initial + :class:`google.ads.googleads.v24.services.types.SearchGoogleAdsFieldsResponse` object, and + provides an ``__iter__`` method to iterate through its + ``results`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``SearchGoogleAdsFields`` requests and continue to iterate + through the ``results`` field on the + corresponding responses. + + All the usual :class:`google.ads.googleads.v24.services.types.SearchGoogleAdsFieldsResponse` + 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[ + ..., google_ads_field_service.SearchGoogleAdsFieldsResponse + ], + request: google_ads_field_service.SearchGoogleAdsFieldsRequest, + response: google_ads_field_service.SearchGoogleAdsFieldsResponse, + *, + 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.ads.googleads.v24.services.types.SearchGoogleAdsFieldsRequest): + The initial request object. + response (google.ads.googleads.v24.services.types.SearchGoogleAdsFieldsResponse): + 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 = google_ads_field_service.SearchGoogleAdsFieldsRequest( + 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[google_ads_field_service.SearchGoogleAdsFieldsResponse]: + 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[google_ads_field.GoogleAdsField]: + for page in self.pages: + yield from page.results + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class SearchGoogleAdsFieldsAsyncPager: + """A pager for iterating through ``search_google_ads_fields`` requests. + + This class thinly wraps an initial + :class:`google.ads.googleads.v24.services.types.SearchGoogleAdsFieldsResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``results`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``SearchGoogleAdsFields`` requests and continue to iterate + through the ``results`` field on the + corresponding responses. + + All the usual :class:`google.ads.googleads.v24.services.types.SearchGoogleAdsFieldsResponse` + 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[google_ads_field_service.SearchGoogleAdsFieldsResponse], + ], + request: google_ads_field_service.SearchGoogleAdsFieldsRequest, + response: google_ads_field_service.SearchGoogleAdsFieldsResponse, + *, + 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.ads.googleads.v24.services.types.SearchGoogleAdsFieldsRequest): + The initial request object. + response (google.ads.googleads.v24.services.types.SearchGoogleAdsFieldsResponse): + 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 = google_ads_field_service.SearchGoogleAdsFieldsRequest( + 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[google_ads_field_service.SearchGoogleAdsFieldsResponse]: + 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[google_ads_field.GoogleAdsField]: + async def async_generator(): + async for page in self.pages: + for response in page.results: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/google/ads/googleads/v24/services/services/google_ads_field_service/transports/README.rst b/google/ads/googleads/v24/services/services/google_ads_field_service/transports/README.rst new file mode 100644 index 000000000..278723344 --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_field_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`GoogleAdsFieldServiceTransport` is the ABC for all transports. +- public child `GoogleAdsFieldServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `GoogleAdsFieldServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseGoogleAdsFieldServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `GoogleAdsFieldServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/google_ads_field_service/transports/__init__.py b/google/ads/googleads/v24/services/services/google_ads_field_service/transports/__init__.py new file mode 100644 index 000000000..b1fbff20a --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_field_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import GoogleAdsFieldServiceTransport +from .grpc import GoogleAdsFieldServiceGrpcTransport +from .grpc_asyncio import GoogleAdsFieldServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[GoogleAdsFieldServiceTransport]] +_transport_registry["grpc"] = GoogleAdsFieldServiceGrpcTransport +_transport_registry["grpc_asyncio"] = GoogleAdsFieldServiceGrpcAsyncIOTransport + +__all__ = ( + "GoogleAdsFieldServiceTransport", + "GoogleAdsFieldServiceGrpcTransport", + "GoogleAdsFieldServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/google_ads_field_service/transports/base.py b/google/ads/googleads/v24/services/services/google_ads_field_service/transports/base.py new file mode 100644 index 000000000..11de58f23 --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_field_service/transports/base.py @@ -0,0 +1,191 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.resources.types import google_ads_field +from google.ads.googleads.v24.services.types import google_ads_field_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 GoogleAdsFieldServiceTransport(abc.ABC): + """Abstract transport class for GoogleAdsFieldService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.get_google_ads_field: gapic_v1.method.wrap_method( + self.get_google_ads_field, + default_timeout=None, + client_info=client_info, + ), + self.search_google_ads_fields: gapic_v1.method.wrap_method( + self.search_google_ads_fields, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def get_google_ads_field( + self, + ) -> Callable[ + [google_ads_field_service.GetGoogleAdsFieldRequest], + Union[ + google_ads_field.GoogleAdsField, + Awaitable[google_ads_field.GoogleAdsField], + ], + ]: + raise NotImplementedError() + + @property + def search_google_ads_fields( + self, + ) -> Callable[ + [google_ads_field_service.SearchGoogleAdsFieldsRequest], + Union[ + google_ads_field_service.SearchGoogleAdsFieldsResponse, + Awaitable[google_ads_field_service.SearchGoogleAdsFieldsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("GoogleAdsFieldServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/google_ads_field_service/transports/grpc.py b/google/ads/googleads/v24/services/services/google_ads_field_service/transports/grpc.py new file mode 100644 index 000000000..7c2d6d9ed --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_field_service/transports/grpc.py @@ -0,0 +1,424 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import google_ads_field +from google.ads.googleads.v24.services.types import google_ads_field_service +from .base import GoogleAdsFieldServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.GoogleAdsFieldService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.GoogleAdsFieldService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class GoogleAdsFieldServiceGrpcTransport(GoogleAdsFieldServiceTransport): + """gRPC backend transport for GoogleAdsFieldService. + + Service to fetch Google Ads API fields. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 get_google_ads_field( + self, + ) -> Callable[ + [google_ads_field_service.GetGoogleAdsFieldRequest], + google_ads_field.GoogleAdsField, + ]: + r"""Return a callable for the get google ads field method over gRPC. + + Returns just the requested field. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GetGoogleAdsFieldRequest], + ~.GoogleAdsField]: + 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_google_ads_field" not in self._stubs: + self._stubs["get_google_ads_field"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.GoogleAdsFieldService/GetGoogleAdsField", + request_serializer=google_ads_field_service.GetGoogleAdsFieldRequest.serialize, + response_deserializer=google_ads_field.GoogleAdsField.deserialize, + ) + ) + return self._stubs["get_google_ads_field"] + + @property + def search_google_ads_fields( + self, + ) -> Callable[ + [google_ads_field_service.SearchGoogleAdsFieldsRequest], + google_ads_field_service.SearchGoogleAdsFieldsResponse, + ]: + r"""Return a callable for the search google ads fields method over gRPC. + + Returns all fields that match the search query. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QueryError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.SearchGoogleAdsFieldsRequest], + ~.SearchGoogleAdsFieldsResponse]: + 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 "search_google_ads_fields" not in self._stubs: + self._stubs["search_google_ads_fields"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.GoogleAdsFieldService/SearchGoogleAdsFields", + request_serializer=google_ads_field_service.SearchGoogleAdsFieldsRequest.serialize, + response_deserializer=google_ads_field_service.SearchGoogleAdsFieldsResponse.deserialize, + ) + ) + return self._stubs["search_google_ads_fields"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("GoogleAdsFieldServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/google_ads_field_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/google_ads_field_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..1d0c40d3b --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_field_service/transports/grpc_asyncio.py @@ -0,0 +1,450 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.resources.types import google_ads_field +from google.ads.googleads.v24.services.types import google_ads_field_service +from .base import GoogleAdsFieldServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.GoogleAdsFieldService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.GoogleAdsFieldService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class GoogleAdsFieldServiceGrpcAsyncIOTransport(GoogleAdsFieldServiceTransport): + """gRPC AsyncIO backend transport for GoogleAdsFieldService. + + Service to fetch Google Ads API fields. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 get_google_ads_field( + self, + ) -> Callable[ + [google_ads_field_service.GetGoogleAdsFieldRequest], + Awaitable[google_ads_field.GoogleAdsField], + ]: + r"""Return a callable for the get google ads field method over gRPC. + + Returns just the requested field. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GetGoogleAdsFieldRequest], + Awaitable[~.GoogleAdsField]]: + 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_google_ads_field" not in self._stubs: + self._stubs["get_google_ads_field"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.GoogleAdsFieldService/GetGoogleAdsField", + request_serializer=google_ads_field_service.GetGoogleAdsFieldRequest.serialize, + response_deserializer=google_ads_field.GoogleAdsField.deserialize, + ) + ) + return self._stubs["get_google_ads_field"] + + @property + def search_google_ads_fields( + self, + ) -> Callable[ + [google_ads_field_service.SearchGoogleAdsFieldsRequest], + Awaitable[google_ads_field_service.SearchGoogleAdsFieldsResponse], + ]: + r"""Return a callable for the search google ads fields method over gRPC. + + Returns all fields that match the search query. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QueryError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.SearchGoogleAdsFieldsRequest], + Awaitable[~.SearchGoogleAdsFieldsResponse]]: + 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 "search_google_ads_fields" not in self._stubs: + self._stubs["search_google_ads_fields"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.GoogleAdsFieldService/SearchGoogleAdsFields", + request_serializer=google_ads_field_service.SearchGoogleAdsFieldsRequest.serialize, + response_deserializer=google_ads_field_service.SearchGoogleAdsFieldsResponse.deserialize, + ) + ) + return self._stubs["search_google_ads_fields"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.get_google_ads_field: self._wrap_method( + self.get_google_ads_field, + default_timeout=None, + client_info=client_info, + ), + self.search_google_ads_fields: self._wrap_method( + self.search_google_ads_fields, + 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" + + +__all__ = ("GoogleAdsFieldServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/google_ads_service/__init__.py b/google/ads/googleads/v24/services/services/google_ads_service/__init__.py new file mode 100644 index 000000000..de4a59e94 --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import GoogleAdsServiceClient +from .async_client import GoogleAdsServiceAsyncClient + +__all__ = ( + "GoogleAdsServiceClient", + "GoogleAdsServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/google_ads_service/async_client.py b/google/ads/googleads/v24/services/services/google_ads_service/async_client.py new file mode 100644 index 000000000..83260d8d1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_service/async_client.py @@ -0,0 +1,1747 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import ( + Callable, + MutableSequence, + Optional, + AsyncIterable, + Awaitable, + Sequence, + Tuple, + Union, +) + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.services.google_ads_service import pagers +from google.ads.googleads.v24.services.types import google_ads_service +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore +from .transports.base import GoogleAdsServiceTransport, DEFAULT_CLIENT_INFO +from .client import GoogleAdsServiceClient + +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 GoogleAdsServiceAsyncClient: + """Service to fetch data and metrics across resources.""" + + _client: GoogleAdsServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = GoogleAdsServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = GoogleAdsServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + GoogleAdsServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = GoogleAdsServiceClient._DEFAULT_UNIVERSE + + accessible_bidding_strategy_path = staticmethod( + GoogleAdsServiceClient.accessible_bidding_strategy_path + ) + parse_accessible_bidding_strategy_path = staticmethod( + GoogleAdsServiceClient.parse_accessible_bidding_strategy_path + ) + account_budget_path = staticmethod( + GoogleAdsServiceClient.account_budget_path + ) + parse_account_budget_path = staticmethod( + GoogleAdsServiceClient.parse_account_budget_path + ) + account_budget_proposal_path = staticmethod( + GoogleAdsServiceClient.account_budget_proposal_path + ) + parse_account_budget_proposal_path = staticmethod( + GoogleAdsServiceClient.parse_account_budget_proposal_path + ) + account_link_path = staticmethod(GoogleAdsServiceClient.account_link_path) + parse_account_link_path = staticmethod( + GoogleAdsServiceClient.parse_account_link_path + ) + ad_path = staticmethod(GoogleAdsServiceClient.ad_path) + parse_ad_path = staticmethod(GoogleAdsServiceClient.parse_ad_path) + ad_group_path = staticmethod(GoogleAdsServiceClient.ad_group_path) + parse_ad_group_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_path + ) + ad_group_ad_path = staticmethod(GoogleAdsServiceClient.ad_group_ad_path) + parse_ad_group_ad_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_ad_path + ) + ad_group_ad_asset_combination_view_path = staticmethod( + GoogleAdsServiceClient.ad_group_ad_asset_combination_view_path + ) + parse_ad_group_ad_asset_combination_view_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_ad_asset_combination_view_path + ) + ad_group_ad_asset_view_path = staticmethod( + GoogleAdsServiceClient.ad_group_ad_asset_view_path + ) + parse_ad_group_ad_asset_view_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_ad_asset_view_path + ) + ad_group_ad_label_path = staticmethod( + GoogleAdsServiceClient.ad_group_ad_label_path + ) + parse_ad_group_ad_label_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_ad_label_path + ) + ad_group_asset_path = staticmethod( + GoogleAdsServiceClient.ad_group_asset_path + ) + parse_ad_group_asset_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_asset_path + ) + ad_group_asset_set_path = staticmethod( + GoogleAdsServiceClient.ad_group_asset_set_path + ) + parse_ad_group_asset_set_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_asset_set_path + ) + ad_group_audience_view_path = staticmethod( + GoogleAdsServiceClient.ad_group_audience_view_path + ) + parse_ad_group_audience_view_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_audience_view_path + ) + ad_group_bid_modifier_path = staticmethod( + GoogleAdsServiceClient.ad_group_bid_modifier_path + ) + parse_ad_group_bid_modifier_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_bid_modifier_path + ) + ad_group_criterion_path = staticmethod( + GoogleAdsServiceClient.ad_group_criterion_path + ) + parse_ad_group_criterion_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_criterion_path + ) + ad_group_criterion_customizer_path = staticmethod( + GoogleAdsServiceClient.ad_group_criterion_customizer_path + ) + parse_ad_group_criterion_customizer_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_criterion_customizer_path + ) + ad_group_criterion_label_path = staticmethod( + GoogleAdsServiceClient.ad_group_criterion_label_path + ) + parse_ad_group_criterion_label_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_criterion_label_path + ) + ad_group_criterion_simulation_path = staticmethod( + GoogleAdsServiceClient.ad_group_criterion_simulation_path + ) + parse_ad_group_criterion_simulation_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_criterion_simulation_path + ) + ad_group_customizer_path = staticmethod( + GoogleAdsServiceClient.ad_group_customizer_path + ) + parse_ad_group_customizer_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_customizer_path + ) + ad_group_label_path = staticmethod( + GoogleAdsServiceClient.ad_group_label_path + ) + parse_ad_group_label_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_label_path + ) + ad_group_simulation_path = staticmethod( + GoogleAdsServiceClient.ad_group_simulation_path + ) + parse_ad_group_simulation_path = staticmethod( + GoogleAdsServiceClient.parse_ad_group_simulation_path + ) + ad_parameter_path = staticmethod(GoogleAdsServiceClient.ad_parameter_path) + parse_ad_parameter_path = staticmethod( + GoogleAdsServiceClient.parse_ad_parameter_path + ) + ad_schedule_view_path = staticmethod( + GoogleAdsServiceClient.ad_schedule_view_path + ) + parse_ad_schedule_view_path = staticmethod( + GoogleAdsServiceClient.parse_ad_schedule_view_path + ) + age_range_view_path = staticmethod( + GoogleAdsServiceClient.age_range_view_path + ) + parse_age_range_view_path = staticmethod( + GoogleAdsServiceClient.parse_age_range_view_path + ) + ai_max_search_term_ad_combination_view_path = staticmethod( + GoogleAdsServiceClient.ai_max_search_term_ad_combination_view_path + ) + parse_ai_max_search_term_ad_combination_view_path = staticmethod( + GoogleAdsServiceClient.parse_ai_max_search_term_ad_combination_view_path + ) + android_privacy_shared_key_google_ad_group_path = staticmethod( + GoogleAdsServiceClient.android_privacy_shared_key_google_ad_group_path + ) + parse_android_privacy_shared_key_google_ad_group_path = staticmethod( + GoogleAdsServiceClient.parse_android_privacy_shared_key_google_ad_group_path + ) + android_privacy_shared_key_google_campaign_path = staticmethod( + GoogleAdsServiceClient.android_privacy_shared_key_google_campaign_path + ) + parse_android_privacy_shared_key_google_campaign_path = staticmethod( + GoogleAdsServiceClient.parse_android_privacy_shared_key_google_campaign_path + ) + android_privacy_shared_key_google_network_type_path = staticmethod( + GoogleAdsServiceClient.android_privacy_shared_key_google_network_type_path + ) + parse_android_privacy_shared_key_google_network_type_path = staticmethod( + GoogleAdsServiceClient.parse_android_privacy_shared_key_google_network_type_path + ) + applied_incentive_path = staticmethod( + GoogleAdsServiceClient.applied_incentive_path + ) + parse_applied_incentive_path = staticmethod( + GoogleAdsServiceClient.parse_applied_incentive_path + ) + app_top_combination_view_path = staticmethod( + GoogleAdsServiceClient.app_top_combination_view_path + ) + parse_app_top_combination_view_path = staticmethod( + GoogleAdsServiceClient.parse_app_top_combination_view_path + ) + asset_path = staticmethod(GoogleAdsServiceClient.asset_path) + parse_asset_path = staticmethod(GoogleAdsServiceClient.parse_asset_path) + asset_field_type_view_path = staticmethod( + GoogleAdsServiceClient.asset_field_type_view_path + ) + parse_asset_field_type_view_path = staticmethod( + GoogleAdsServiceClient.parse_asset_field_type_view_path + ) + asset_group_path = staticmethod(GoogleAdsServiceClient.asset_group_path) + parse_asset_group_path = staticmethod( + GoogleAdsServiceClient.parse_asset_group_path + ) + asset_group_asset_path = staticmethod( + GoogleAdsServiceClient.asset_group_asset_path + ) + parse_asset_group_asset_path = staticmethod( + GoogleAdsServiceClient.parse_asset_group_asset_path + ) + asset_group_listing_group_filter_path = staticmethod( + GoogleAdsServiceClient.asset_group_listing_group_filter_path + ) + parse_asset_group_listing_group_filter_path = staticmethod( + GoogleAdsServiceClient.parse_asset_group_listing_group_filter_path + ) + asset_group_product_group_view_path = staticmethod( + GoogleAdsServiceClient.asset_group_product_group_view_path + ) + parse_asset_group_product_group_view_path = staticmethod( + GoogleAdsServiceClient.parse_asset_group_product_group_view_path + ) + asset_group_signal_path = staticmethod( + GoogleAdsServiceClient.asset_group_signal_path + ) + parse_asset_group_signal_path = staticmethod( + GoogleAdsServiceClient.parse_asset_group_signal_path + ) + asset_group_top_combination_view_path = staticmethod( + GoogleAdsServiceClient.asset_group_top_combination_view_path + ) + parse_asset_group_top_combination_view_path = staticmethod( + GoogleAdsServiceClient.parse_asset_group_top_combination_view_path + ) + asset_set_path = staticmethod(GoogleAdsServiceClient.asset_set_path) + parse_asset_set_path = staticmethod( + GoogleAdsServiceClient.parse_asset_set_path + ) + asset_set_asset_path = staticmethod( + GoogleAdsServiceClient.asset_set_asset_path + ) + parse_asset_set_asset_path = staticmethod( + GoogleAdsServiceClient.parse_asset_set_asset_path + ) + asset_set_type_view_path = staticmethod( + GoogleAdsServiceClient.asset_set_type_view_path + ) + parse_asset_set_type_view_path = staticmethod( + GoogleAdsServiceClient.parse_asset_set_type_view_path + ) + audience_path = staticmethod(GoogleAdsServiceClient.audience_path) + parse_audience_path = staticmethod( + GoogleAdsServiceClient.parse_audience_path + ) + batch_job_path = staticmethod(GoogleAdsServiceClient.batch_job_path) + parse_batch_job_path = staticmethod( + GoogleAdsServiceClient.parse_batch_job_path + ) + bidding_data_exclusion_path = staticmethod( + GoogleAdsServiceClient.bidding_data_exclusion_path + ) + parse_bidding_data_exclusion_path = staticmethod( + GoogleAdsServiceClient.parse_bidding_data_exclusion_path + ) + bidding_seasonality_adjustment_path = staticmethod( + GoogleAdsServiceClient.bidding_seasonality_adjustment_path + ) + parse_bidding_seasonality_adjustment_path = staticmethod( + GoogleAdsServiceClient.parse_bidding_seasonality_adjustment_path + ) + bidding_strategy_path = staticmethod( + GoogleAdsServiceClient.bidding_strategy_path + ) + parse_bidding_strategy_path = staticmethod( + GoogleAdsServiceClient.parse_bidding_strategy_path + ) + bidding_strategy_simulation_path = staticmethod( + GoogleAdsServiceClient.bidding_strategy_simulation_path + ) + parse_bidding_strategy_simulation_path = staticmethod( + GoogleAdsServiceClient.parse_bidding_strategy_simulation_path + ) + billing_setup_path = staticmethod(GoogleAdsServiceClient.billing_setup_path) + parse_billing_setup_path = staticmethod( + GoogleAdsServiceClient.parse_billing_setup_path + ) + call_view_path = staticmethod(GoogleAdsServiceClient.call_view_path) + parse_call_view_path = staticmethod( + GoogleAdsServiceClient.parse_call_view_path + ) + campaign_path = staticmethod(GoogleAdsServiceClient.campaign_path) + parse_campaign_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_path + ) + campaign_aggregate_asset_view_path = staticmethod( + GoogleAdsServiceClient.campaign_aggregate_asset_view_path + ) + parse_campaign_aggregate_asset_view_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_aggregate_asset_view_path + ) + campaign_asset_path = staticmethod( + GoogleAdsServiceClient.campaign_asset_path + ) + parse_campaign_asset_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_asset_path + ) + campaign_asset_set_path = staticmethod( + GoogleAdsServiceClient.campaign_asset_set_path + ) + parse_campaign_asset_set_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_asset_set_path + ) + campaign_audience_view_path = staticmethod( + GoogleAdsServiceClient.campaign_audience_view_path + ) + parse_campaign_audience_view_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_audience_view_path + ) + campaign_bid_modifier_path = staticmethod( + GoogleAdsServiceClient.campaign_bid_modifier_path + ) + parse_campaign_bid_modifier_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_bid_modifier_path + ) + campaign_budget_path = staticmethod( + GoogleAdsServiceClient.campaign_budget_path + ) + parse_campaign_budget_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_budget_path + ) + campaign_conversion_goal_path = staticmethod( + GoogleAdsServiceClient.campaign_conversion_goal_path + ) + parse_campaign_conversion_goal_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_conversion_goal_path + ) + campaign_criterion_path = staticmethod( + GoogleAdsServiceClient.campaign_criterion_path + ) + parse_campaign_criterion_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_criterion_path + ) + campaign_customizer_path = staticmethod( + GoogleAdsServiceClient.campaign_customizer_path + ) + parse_campaign_customizer_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_customizer_path + ) + campaign_draft_path = staticmethod( + GoogleAdsServiceClient.campaign_draft_path + ) + parse_campaign_draft_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_draft_path + ) + campaign_goal_config_path = staticmethod( + GoogleAdsServiceClient.campaign_goal_config_path + ) + parse_campaign_goal_config_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_goal_config_path + ) + campaign_group_path = staticmethod( + GoogleAdsServiceClient.campaign_group_path + ) + parse_campaign_group_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_group_path + ) + campaign_label_path = staticmethod( + GoogleAdsServiceClient.campaign_label_path + ) + parse_campaign_label_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_label_path + ) + campaign_lifecycle_goal_path = staticmethod( + GoogleAdsServiceClient.campaign_lifecycle_goal_path + ) + parse_campaign_lifecycle_goal_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_lifecycle_goal_path + ) + campaign_search_term_insight_path = staticmethod( + GoogleAdsServiceClient.campaign_search_term_insight_path + ) + parse_campaign_search_term_insight_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_search_term_insight_path + ) + campaign_search_term_view_path = staticmethod( + GoogleAdsServiceClient.campaign_search_term_view_path + ) + parse_campaign_search_term_view_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_search_term_view_path + ) + campaign_shared_set_path = staticmethod( + GoogleAdsServiceClient.campaign_shared_set_path + ) + parse_campaign_shared_set_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_shared_set_path + ) + campaign_simulation_path = staticmethod( + GoogleAdsServiceClient.campaign_simulation_path + ) + parse_campaign_simulation_path = staticmethod( + GoogleAdsServiceClient.parse_campaign_simulation_path + ) + carrier_constant_path = staticmethod( + GoogleAdsServiceClient.carrier_constant_path + ) + parse_carrier_constant_path = staticmethod( + GoogleAdsServiceClient.parse_carrier_constant_path + ) + cart_data_sales_view_path = staticmethod( + GoogleAdsServiceClient.cart_data_sales_view_path + ) + parse_cart_data_sales_view_path = staticmethod( + GoogleAdsServiceClient.parse_cart_data_sales_view_path + ) + change_event_path = staticmethod(GoogleAdsServiceClient.change_event_path) + parse_change_event_path = staticmethod( + GoogleAdsServiceClient.parse_change_event_path + ) + change_status_path = staticmethod(GoogleAdsServiceClient.change_status_path) + parse_change_status_path = staticmethod( + GoogleAdsServiceClient.parse_change_status_path + ) + channel_aggregate_asset_view_path = staticmethod( + GoogleAdsServiceClient.channel_aggregate_asset_view_path + ) + parse_channel_aggregate_asset_view_path = staticmethod( + GoogleAdsServiceClient.parse_channel_aggregate_asset_view_path + ) + click_view_path = staticmethod(GoogleAdsServiceClient.click_view_path) + parse_click_view_path = staticmethod( + GoogleAdsServiceClient.parse_click_view_path + ) + combined_audience_path = staticmethod( + GoogleAdsServiceClient.combined_audience_path + ) + parse_combined_audience_path = staticmethod( + GoogleAdsServiceClient.parse_combined_audience_path + ) + content_criterion_view_path = staticmethod( + GoogleAdsServiceClient.content_criterion_view_path + ) + parse_content_criterion_view_path = staticmethod( + GoogleAdsServiceClient.parse_content_criterion_view_path + ) + conversion_action_path = staticmethod( + GoogleAdsServiceClient.conversion_action_path + ) + parse_conversion_action_path = staticmethod( + GoogleAdsServiceClient.parse_conversion_action_path + ) + conversion_custom_variable_path = staticmethod( + GoogleAdsServiceClient.conversion_custom_variable_path + ) + parse_conversion_custom_variable_path = staticmethod( + GoogleAdsServiceClient.parse_conversion_custom_variable_path + ) + conversion_goal_campaign_config_path = staticmethod( + GoogleAdsServiceClient.conversion_goal_campaign_config_path + ) + parse_conversion_goal_campaign_config_path = staticmethod( + GoogleAdsServiceClient.parse_conversion_goal_campaign_config_path + ) + conversion_value_rule_path = staticmethod( + GoogleAdsServiceClient.conversion_value_rule_path + ) + parse_conversion_value_rule_path = staticmethod( + GoogleAdsServiceClient.parse_conversion_value_rule_path + ) + conversion_value_rule_set_path = staticmethod( + GoogleAdsServiceClient.conversion_value_rule_set_path + ) + parse_conversion_value_rule_set_path = staticmethod( + GoogleAdsServiceClient.parse_conversion_value_rule_set_path + ) + currency_constant_path = staticmethod( + GoogleAdsServiceClient.currency_constant_path + ) + parse_currency_constant_path = staticmethod( + GoogleAdsServiceClient.parse_currency_constant_path + ) + custom_audience_path = staticmethod( + GoogleAdsServiceClient.custom_audience_path + ) + parse_custom_audience_path = staticmethod( + GoogleAdsServiceClient.parse_custom_audience_path + ) + custom_conversion_goal_path = staticmethod( + GoogleAdsServiceClient.custom_conversion_goal_path + ) + parse_custom_conversion_goal_path = staticmethod( + GoogleAdsServiceClient.parse_custom_conversion_goal_path + ) + customer_path = staticmethod(GoogleAdsServiceClient.customer_path) + parse_customer_path = staticmethod( + GoogleAdsServiceClient.parse_customer_path + ) + customer_asset_path = staticmethod( + GoogleAdsServiceClient.customer_asset_path + ) + parse_customer_asset_path = staticmethod( + GoogleAdsServiceClient.parse_customer_asset_path + ) + customer_asset_set_path = staticmethod( + GoogleAdsServiceClient.customer_asset_set_path + ) + parse_customer_asset_set_path = staticmethod( + GoogleAdsServiceClient.parse_customer_asset_set_path + ) + customer_client_path = staticmethod( + GoogleAdsServiceClient.customer_client_path + ) + parse_customer_client_path = staticmethod( + GoogleAdsServiceClient.parse_customer_client_path + ) + customer_client_link_path = staticmethod( + GoogleAdsServiceClient.customer_client_link_path + ) + parse_customer_client_link_path = staticmethod( + GoogleAdsServiceClient.parse_customer_client_link_path + ) + customer_conversion_goal_path = staticmethod( + GoogleAdsServiceClient.customer_conversion_goal_path + ) + parse_customer_conversion_goal_path = staticmethod( + GoogleAdsServiceClient.parse_customer_conversion_goal_path + ) + customer_customizer_path = staticmethod( + GoogleAdsServiceClient.customer_customizer_path + ) + parse_customer_customizer_path = staticmethod( + GoogleAdsServiceClient.parse_customer_customizer_path + ) + customer_label_path = staticmethod( + GoogleAdsServiceClient.customer_label_path + ) + parse_customer_label_path = staticmethod( + GoogleAdsServiceClient.parse_customer_label_path + ) + customer_lifecycle_goal_path = staticmethod( + GoogleAdsServiceClient.customer_lifecycle_goal_path + ) + parse_customer_lifecycle_goal_path = staticmethod( + GoogleAdsServiceClient.parse_customer_lifecycle_goal_path + ) + customer_manager_link_path = staticmethod( + GoogleAdsServiceClient.customer_manager_link_path + ) + parse_customer_manager_link_path = staticmethod( + GoogleAdsServiceClient.parse_customer_manager_link_path + ) + customer_negative_criterion_path = staticmethod( + GoogleAdsServiceClient.customer_negative_criterion_path + ) + parse_customer_negative_criterion_path = staticmethod( + GoogleAdsServiceClient.parse_customer_negative_criterion_path + ) + customer_search_term_insight_path = staticmethod( + GoogleAdsServiceClient.customer_search_term_insight_path + ) + parse_customer_search_term_insight_path = staticmethod( + GoogleAdsServiceClient.parse_customer_search_term_insight_path + ) + customer_user_access_path = staticmethod( + GoogleAdsServiceClient.customer_user_access_path + ) + parse_customer_user_access_path = staticmethod( + GoogleAdsServiceClient.parse_customer_user_access_path + ) + customer_user_access_invitation_path = staticmethod( + GoogleAdsServiceClient.customer_user_access_invitation_path + ) + parse_customer_user_access_invitation_path = staticmethod( + GoogleAdsServiceClient.parse_customer_user_access_invitation_path + ) + custom_interest_path = staticmethod( + GoogleAdsServiceClient.custom_interest_path + ) + parse_custom_interest_path = staticmethod( + GoogleAdsServiceClient.parse_custom_interest_path + ) + customizer_attribute_path = staticmethod( + GoogleAdsServiceClient.customizer_attribute_path + ) + parse_customizer_attribute_path = staticmethod( + GoogleAdsServiceClient.parse_customizer_attribute_path + ) + data_link_path = staticmethod(GoogleAdsServiceClient.data_link_path) + parse_data_link_path = staticmethod( + GoogleAdsServiceClient.parse_data_link_path + ) + detail_content_suitability_placement_view_path = staticmethod( + GoogleAdsServiceClient.detail_content_suitability_placement_view_path + ) + parse_detail_content_suitability_placement_view_path = staticmethod( + GoogleAdsServiceClient.parse_detail_content_suitability_placement_view_path + ) + detailed_demographic_path = staticmethod( + GoogleAdsServiceClient.detailed_demographic_path + ) + parse_detailed_demographic_path = staticmethod( + GoogleAdsServiceClient.parse_detailed_demographic_path + ) + detail_placement_view_path = staticmethod( + GoogleAdsServiceClient.detail_placement_view_path + ) + parse_detail_placement_view_path = staticmethod( + GoogleAdsServiceClient.parse_detail_placement_view_path + ) + display_keyword_view_path = staticmethod( + GoogleAdsServiceClient.display_keyword_view_path + ) + parse_display_keyword_view_path = staticmethod( + GoogleAdsServiceClient.parse_display_keyword_view_path + ) + distance_view_path = staticmethod(GoogleAdsServiceClient.distance_view_path) + parse_distance_view_path = staticmethod( + GoogleAdsServiceClient.parse_distance_view_path + ) + domain_category_path = staticmethod( + GoogleAdsServiceClient.domain_category_path + ) + parse_domain_category_path = staticmethod( + GoogleAdsServiceClient.parse_domain_category_path + ) + dynamic_search_ads_search_term_view_path = staticmethod( + GoogleAdsServiceClient.dynamic_search_ads_search_term_view_path + ) + parse_dynamic_search_ads_search_term_view_path = staticmethod( + GoogleAdsServiceClient.parse_dynamic_search_ads_search_term_view_path + ) + expanded_landing_page_view_path = staticmethod( + GoogleAdsServiceClient.expanded_landing_page_view_path + ) + parse_expanded_landing_page_view_path = staticmethod( + GoogleAdsServiceClient.parse_expanded_landing_page_view_path + ) + experiment_path = staticmethod(GoogleAdsServiceClient.experiment_path) + parse_experiment_path = staticmethod( + GoogleAdsServiceClient.parse_experiment_path + ) + experiment_arm_path = staticmethod( + GoogleAdsServiceClient.experiment_arm_path + ) + parse_experiment_arm_path = staticmethod( + GoogleAdsServiceClient.parse_experiment_arm_path + ) + final_url_expansion_asset_view_path = staticmethod( + GoogleAdsServiceClient.final_url_expansion_asset_view_path + ) + parse_final_url_expansion_asset_view_path = staticmethod( + GoogleAdsServiceClient.parse_final_url_expansion_asset_view_path + ) + gender_view_path = staticmethod(GoogleAdsServiceClient.gender_view_path) + parse_gender_view_path = staticmethod( + GoogleAdsServiceClient.parse_gender_view_path + ) + geographic_view_path = staticmethod( + GoogleAdsServiceClient.geographic_view_path + ) + parse_geographic_view_path = staticmethod( + GoogleAdsServiceClient.parse_geographic_view_path + ) + geo_target_constant_path = staticmethod( + GoogleAdsServiceClient.geo_target_constant_path + ) + parse_geo_target_constant_path = staticmethod( + GoogleAdsServiceClient.parse_geo_target_constant_path + ) + goal_path = staticmethod(GoogleAdsServiceClient.goal_path) + parse_goal_path = staticmethod(GoogleAdsServiceClient.parse_goal_path) + group_content_suitability_placement_view_path = staticmethod( + GoogleAdsServiceClient.group_content_suitability_placement_view_path + ) + parse_group_content_suitability_placement_view_path = staticmethod( + GoogleAdsServiceClient.parse_group_content_suitability_placement_view_path + ) + group_placement_view_path = staticmethod( + GoogleAdsServiceClient.group_placement_view_path + ) + parse_group_placement_view_path = staticmethod( + GoogleAdsServiceClient.parse_group_placement_view_path + ) + hotel_group_view_path = staticmethod( + GoogleAdsServiceClient.hotel_group_view_path + ) + parse_hotel_group_view_path = staticmethod( + GoogleAdsServiceClient.parse_hotel_group_view_path + ) + hotel_performance_view_path = staticmethod( + GoogleAdsServiceClient.hotel_performance_view_path + ) + parse_hotel_performance_view_path = staticmethod( + GoogleAdsServiceClient.parse_hotel_performance_view_path + ) + hotel_reconciliation_path = staticmethod( + GoogleAdsServiceClient.hotel_reconciliation_path + ) + parse_hotel_reconciliation_path = staticmethod( + GoogleAdsServiceClient.parse_hotel_reconciliation_path + ) + income_range_view_path = staticmethod( + GoogleAdsServiceClient.income_range_view_path + ) + parse_income_range_view_path = staticmethod( + GoogleAdsServiceClient.parse_income_range_view_path + ) + keyword_plan_path = staticmethod(GoogleAdsServiceClient.keyword_plan_path) + parse_keyword_plan_path = staticmethod( + GoogleAdsServiceClient.parse_keyword_plan_path + ) + keyword_plan_ad_group_path = staticmethod( + GoogleAdsServiceClient.keyword_plan_ad_group_path + ) + parse_keyword_plan_ad_group_path = staticmethod( + GoogleAdsServiceClient.parse_keyword_plan_ad_group_path + ) + keyword_plan_ad_group_keyword_path = staticmethod( + GoogleAdsServiceClient.keyword_plan_ad_group_keyword_path + ) + parse_keyword_plan_ad_group_keyword_path = staticmethod( + GoogleAdsServiceClient.parse_keyword_plan_ad_group_keyword_path + ) + keyword_plan_campaign_path = staticmethod( + GoogleAdsServiceClient.keyword_plan_campaign_path + ) + parse_keyword_plan_campaign_path = staticmethod( + GoogleAdsServiceClient.parse_keyword_plan_campaign_path + ) + keyword_plan_campaign_keyword_path = staticmethod( + GoogleAdsServiceClient.keyword_plan_campaign_keyword_path + ) + parse_keyword_plan_campaign_keyword_path = staticmethod( + GoogleAdsServiceClient.parse_keyword_plan_campaign_keyword_path + ) + keyword_theme_constant_path = staticmethod( + GoogleAdsServiceClient.keyword_theme_constant_path + ) + parse_keyword_theme_constant_path = staticmethod( + GoogleAdsServiceClient.parse_keyword_theme_constant_path + ) + keyword_view_path = staticmethod(GoogleAdsServiceClient.keyword_view_path) + parse_keyword_view_path = staticmethod( + GoogleAdsServiceClient.parse_keyword_view_path + ) + label_path = staticmethod(GoogleAdsServiceClient.label_path) + parse_label_path = staticmethod(GoogleAdsServiceClient.parse_label_path) + landing_page_view_path = staticmethod( + GoogleAdsServiceClient.landing_page_view_path + ) + parse_landing_page_view_path = staticmethod( + GoogleAdsServiceClient.parse_landing_page_view_path + ) + language_constant_path = staticmethod( + GoogleAdsServiceClient.language_constant_path + ) + parse_language_constant_path = staticmethod( + GoogleAdsServiceClient.parse_language_constant_path + ) + lead_form_submission_data_path = staticmethod( + GoogleAdsServiceClient.lead_form_submission_data_path + ) + parse_lead_form_submission_data_path = staticmethod( + GoogleAdsServiceClient.parse_lead_form_submission_data_path + ) + life_event_path = staticmethod(GoogleAdsServiceClient.life_event_path) + parse_life_event_path = staticmethod( + GoogleAdsServiceClient.parse_life_event_path + ) + local_services_employee_path = staticmethod( + GoogleAdsServiceClient.local_services_employee_path + ) + parse_local_services_employee_path = staticmethod( + GoogleAdsServiceClient.parse_local_services_employee_path + ) + local_services_lead_path = staticmethod( + GoogleAdsServiceClient.local_services_lead_path + ) + parse_local_services_lead_path = staticmethod( + GoogleAdsServiceClient.parse_local_services_lead_path + ) + local_services_lead_conversation_path = staticmethod( + GoogleAdsServiceClient.local_services_lead_conversation_path + ) + parse_local_services_lead_conversation_path = staticmethod( + GoogleAdsServiceClient.parse_local_services_lead_conversation_path + ) + local_services_verification_artifact_path = staticmethod( + GoogleAdsServiceClient.local_services_verification_artifact_path + ) + parse_local_services_verification_artifact_path = staticmethod( + GoogleAdsServiceClient.parse_local_services_verification_artifact_path + ) + location_interest_view_path = staticmethod( + GoogleAdsServiceClient.location_interest_view_path + ) + parse_location_interest_view_path = staticmethod( + GoogleAdsServiceClient.parse_location_interest_view_path + ) + location_view_path = staticmethod(GoogleAdsServiceClient.location_view_path) + parse_location_view_path = staticmethod( + GoogleAdsServiceClient.parse_location_view_path + ) + managed_placement_view_path = staticmethod( + GoogleAdsServiceClient.managed_placement_view_path + ) + parse_managed_placement_view_path = staticmethod( + GoogleAdsServiceClient.parse_managed_placement_view_path + ) + matched_location_interest_view_path = staticmethod( + GoogleAdsServiceClient.matched_location_interest_view_path + ) + parse_matched_location_interest_view_path = staticmethod( + GoogleAdsServiceClient.parse_matched_location_interest_view_path + ) + media_file_path = staticmethod(GoogleAdsServiceClient.media_file_path) + parse_media_file_path = staticmethod( + GoogleAdsServiceClient.parse_media_file_path + ) + mobile_app_category_constant_path = staticmethod( + GoogleAdsServiceClient.mobile_app_category_constant_path + ) + parse_mobile_app_category_constant_path = staticmethod( + GoogleAdsServiceClient.parse_mobile_app_category_constant_path + ) + mobile_device_constant_path = staticmethod( + GoogleAdsServiceClient.mobile_device_constant_path + ) + parse_mobile_device_constant_path = staticmethod( + GoogleAdsServiceClient.parse_mobile_device_constant_path + ) + offline_conversion_upload_client_summary_path = staticmethod( + GoogleAdsServiceClient.offline_conversion_upload_client_summary_path + ) + parse_offline_conversion_upload_client_summary_path = staticmethod( + GoogleAdsServiceClient.parse_offline_conversion_upload_client_summary_path + ) + offline_conversion_upload_conversion_action_summary_path = staticmethod( + GoogleAdsServiceClient.offline_conversion_upload_conversion_action_summary_path + ) + parse_offline_conversion_upload_conversion_action_summary_path = staticmethod( + GoogleAdsServiceClient.parse_offline_conversion_upload_conversion_action_summary_path + ) + offline_user_data_job_path = staticmethod( + GoogleAdsServiceClient.offline_user_data_job_path + ) + parse_offline_user_data_job_path = staticmethod( + GoogleAdsServiceClient.parse_offline_user_data_job_path + ) + operating_system_version_constant_path = staticmethod( + GoogleAdsServiceClient.operating_system_version_constant_path + ) + parse_operating_system_version_constant_path = staticmethod( + GoogleAdsServiceClient.parse_operating_system_version_constant_path + ) + paid_organic_search_term_view_path = staticmethod( + GoogleAdsServiceClient.paid_organic_search_term_view_path + ) + parse_paid_organic_search_term_view_path = staticmethod( + GoogleAdsServiceClient.parse_paid_organic_search_term_view_path + ) + parental_status_view_path = staticmethod( + GoogleAdsServiceClient.parental_status_view_path + ) + parse_parental_status_view_path = staticmethod( + GoogleAdsServiceClient.parse_parental_status_view_path + ) + payments_account_path = staticmethod( + GoogleAdsServiceClient.payments_account_path + ) + parse_payments_account_path = staticmethod( + GoogleAdsServiceClient.parse_payments_account_path + ) + performance_max_placement_view_path = staticmethod( + GoogleAdsServiceClient.performance_max_placement_view_path + ) + parse_performance_max_placement_view_path = staticmethod( + GoogleAdsServiceClient.parse_performance_max_placement_view_path + ) + per_store_view_path = staticmethod( + GoogleAdsServiceClient.per_store_view_path + ) + parse_per_store_view_path = staticmethod( + GoogleAdsServiceClient.parse_per_store_view_path + ) + product_category_constant_path = staticmethod( + GoogleAdsServiceClient.product_category_constant_path + ) + parse_product_category_constant_path = staticmethod( + GoogleAdsServiceClient.parse_product_category_constant_path + ) + product_group_view_path = staticmethod( + GoogleAdsServiceClient.product_group_view_path + ) + parse_product_group_view_path = staticmethod( + GoogleAdsServiceClient.parse_product_group_view_path + ) + product_link_path = staticmethod(GoogleAdsServiceClient.product_link_path) + parse_product_link_path = staticmethod( + GoogleAdsServiceClient.parse_product_link_path + ) + product_link_invitation_path = staticmethod( + GoogleAdsServiceClient.product_link_invitation_path + ) + parse_product_link_invitation_path = staticmethod( + GoogleAdsServiceClient.parse_product_link_invitation_path + ) + qualifying_question_path = staticmethod( + GoogleAdsServiceClient.qualifying_question_path + ) + parse_qualifying_question_path = staticmethod( + GoogleAdsServiceClient.parse_qualifying_question_path + ) + recommendation_path = staticmethod( + GoogleAdsServiceClient.recommendation_path + ) + parse_recommendation_path = staticmethod( + GoogleAdsServiceClient.parse_recommendation_path + ) + recommendation_subscription_path = staticmethod( + GoogleAdsServiceClient.recommendation_subscription_path + ) + parse_recommendation_subscription_path = staticmethod( + GoogleAdsServiceClient.parse_recommendation_subscription_path + ) + remarketing_action_path = staticmethod( + GoogleAdsServiceClient.remarketing_action_path + ) + parse_remarketing_action_path = staticmethod( + GoogleAdsServiceClient.parse_remarketing_action_path + ) + search_term_view_path = staticmethod( + GoogleAdsServiceClient.search_term_view_path + ) + parse_search_term_view_path = staticmethod( + GoogleAdsServiceClient.parse_search_term_view_path + ) + shared_criterion_path = staticmethod( + GoogleAdsServiceClient.shared_criterion_path + ) + parse_shared_criterion_path = staticmethod( + GoogleAdsServiceClient.parse_shared_criterion_path + ) + shared_set_path = staticmethod(GoogleAdsServiceClient.shared_set_path) + parse_shared_set_path = staticmethod( + GoogleAdsServiceClient.parse_shared_set_path + ) + shopping_performance_view_path = staticmethod( + GoogleAdsServiceClient.shopping_performance_view_path + ) + parse_shopping_performance_view_path = staticmethod( + GoogleAdsServiceClient.parse_shopping_performance_view_path + ) + shopping_product_path = staticmethod( + GoogleAdsServiceClient.shopping_product_path + ) + parse_shopping_product_path = staticmethod( + GoogleAdsServiceClient.parse_shopping_product_path + ) + smart_campaign_search_term_view_path = staticmethod( + GoogleAdsServiceClient.smart_campaign_search_term_view_path + ) + parse_smart_campaign_search_term_view_path = staticmethod( + GoogleAdsServiceClient.parse_smart_campaign_search_term_view_path + ) + smart_campaign_setting_path = staticmethod( + GoogleAdsServiceClient.smart_campaign_setting_path + ) + parse_smart_campaign_setting_path = staticmethod( + GoogleAdsServiceClient.parse_smart_campaign_setting_path + ) + targeting_expansion_view_path = staticmethod( + GoogleAdsServiceClient.targeting_expansion_view_path + ) + parse_targeting_expansion_view_path = staticmethod( + GoogleAdsServiceClient.parse_targeting_expansion_view_path + ) + third_party_app_analytics_link_path = staticmethod( + GoogleAdsServiceClient.third_party_app_analytics_link_path + ) + parse_third_party_app_analytics_link_path = staticmethod( + GoogleAdsServiceClient.parse_third_party_app_analytics_link_path + ) + topic_constant_path = staticmethod( + GoogleAdsServiceClient.topic_constant_path + ) + parse_topic_constant_path = staticmethod( + GoogleAdsServiceClient.parse_topic_constant_path + ) + topic_view_path = staticmethod(GoogleAdsServiceClient.topic_view_path) + parse_topic_view_path = staticmethod( + GoogleAdsServiceClient.parse_topic_view_path + ) + travel_activity_group_view_path = staticmethod( + GoogleAdsServiceClient.travel_activity_group_view_path + ) + parse_travel_activity_group_view_path = staticmethod( + GoogleAdsServiceClient.parse_travel_activity_group_view_path + ) + travel_activity_performance_view_path = staticmethod( + GoogleAdsServiceClient.travel_activity_performance_view_path + ) + parse_travel_activity_performance_view_path = staticmethod( + GoogleAdsServiceClient.parse_travel_activity_performance_view_path + ) + user_interest_path = staticmethod(GoogleAdsServiceClient.user_interest_path) + parse_user_interest_path = staticmethod( + GoogleAdsServiceClient.parse_user_interest_path + ) + user_list_path = staticmethod(GoogleAdsServiceClient.user_list_path) + parse_user_list_path = staticmethod( + GoogleAdsServiceClient.parse_user_list_path + ) + user_list_customer_type_path = staticmethod( + GoogleAdsServiceClient.user_list_customer_type_path + ) + parse_user_list_customer_type_path = staticmethod( + GoogleAdsServiceClient.parse_user_list_customer_type_path + ) + user_location_view_path = staticmethod( + GoogleAdsServiceClient.user_location_view_path + ) + parse_user_location_view_path = staticmethod( + GoogleAdsServiceClient.parse_user_location_view_path + ) + video_path = staticmethod(GoogleAdsServiceClient.video_path) + parse_video_path = staticmethod(GoogleAdsServiceClient.parse_video_path) + video_enhancement_path = staticmethod( + GoogleAdsServiceClient.video_enhancement_path + ) + parse_video_enhancement_path = staticmethod( + GoogleAdsServiceClient.parse_video_enhancement_path + ) + webpage_view_path = staticmethod(GoogleAdsServiceClient.webpage_view_path) + parse_webpage_view_path = staticmethod( + GoogleAdsServiceClient.parse_webpage_view_path + ) + you_tube_video_upload_path = staticmethod( + GoogleAdsServiceClient.you_tube_video_upload_path + ) + parse_you_tube_video_upload_path = staticmethod( + GoogleAdsServiceClient.parse_you_tube_video_upload_path + ) + common_billing_account_path = staticmethod( + GoogleAdsServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GoogleAdsServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(GoogleAdsServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + GoogleAdsServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + GoogleAdsServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GoogleAdsServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + GoogleAdsServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + GoogleAdsServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + GoogleAdsServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + GoogleAdsServiceClient.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: + GoogleAdsServiceAsyncClient: The constructed client. + """ + return GoogleAdsServiceClient.from_service_account_info.__func__(GoogleAdsServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GoogleAdsServiceAsyncClient: The constructed client. + """ + return GoogleAdsServiceClient.from_service_account_file.__func__(GoogleAdsServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return GoogleAdsServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> GoogleAdsServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GoogleAdsServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = GoogleAdsServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + GoogleAdsServiceTransport, + Callable[..., GoogleAdsServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the google ads 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,GoogleAdsServiceTransport,Callable[..., GoogleAdsServiceTransport]]]): + 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 GoogleAdsServiceTransport 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 = GoogleAdsServiceClient( + 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.ads.googleads.v24.services.GoogleAdsServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.GoogleAdsService", + "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.ads.googleads.v24.services.GoogleAdsService", + "credentialsType": None, + } + ), + ) + + async def search( + self, + request: Optional[ + Union[google_ads_service.SearchGoogleAdsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + query: 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.SearchAsyncPager: + r"""Returns all rows that match the search query. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ChangeEventError <>`__ + `ChangeStatusError <>`__ `ClickViewError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QueryError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.SearchGoogleAdsRequest, dict]]): + The request object. Request message for + [GoogleAdsService.Search][google.ads.googleads.v24.services.GoogleAdsService.Search]. + customer_id (:class:`str`): + Required. The ID of the customer + being queried. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + query (:class:`str`): + Required. The query string. + This corresponds to the ``query`` 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.ads.googleads.v24.services.services.google_ads_service.pagers.SearchAsyncPager: + Response message for + [GoogleAdsService.Search][google.ads.googleads.v24.services.GoogleAdsService.Search]. + + 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 = [customer_id, query] + 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, google_ads_service.SearchGoogleAdsRequest): + request = google_ads_service.SearchGoogleAdsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if query is not None: + request.query = query + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.search + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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.SearchAsyncPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def search_stream( + self, + request: Optional[ + Union[google_ads_service.SearchGoogleAdsStreamRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + query: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> Awaitable[ + AsyncIterable[google_ads_service.SearchGoogleAdsStreamResponse] + ]: + r"""Returns all rows that match the search stream query. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ChangeEventError <>`__ + `ChangeStatusError <>`__ `ClickViewError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QueryError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.SearchGoogleAdsStreamRequest, dict]]): + The request object. Request message for + [GoogleAdsService.SearchStream][google.ads.googleads.v24.services.GoogleAdsService.SearchStream]. + customer_id (:class:`str`): + Required. The ID of the customer + being queried. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + query (:class:`str`): + Required. The query string. + This corresponds to the ``query`` 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: + AsyncIterable[google.ads.googleads.v24.services.types.SearchGoogleAdsStreamResponse]: + Response message for + [GoogleAdsService.SearchStream][google.ads.googleads.v24.services.GoogleAdsService.SearchStream]. + + """ + # 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 = [customer_id, query] + 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, google_ads_service.SearchGoogleAdsStreamRequest + ): + request = google_ads_service.SearchGoogleAdsStreamRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if query is not None: + request.query = query + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.search_stream + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 mutate( + self, + request: Optional[ + Union[google_ads_service.MutateGoogleAdsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + mutate_operations: Optional[ + MutableSequence[google_ads_service.MutateOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> google_ads_service.MutateGoogleAdsResponse: + r"""Executes mutate and actions operations. Mutate operations + create, update, or remove resources. Actions perform custom + operations. This method supports atomic transactions with + multiple types of resources and actions. For example, you can + atomically create a campaign and a campaign budget, or perform + up to thousands of mutates atomically. + + This method is essentially a wrapper around a series of mutate + methods. The only features it offers over calling those methods + directly are: + + - Atomic transactions + - Temp resource names (described below) + - Somewhat reduced latency over making a series of mutate calls + + Note: Only resources that support atomic transactions are + included, so this method can't replace all calls to individual + services. + + Atomic Transaction Benefits + --------------------------- + + Atomicity makes error handling much easier. If you're making a + series of changes and one fails, it can leave your account in an + inconsistent state. With atomicity, you either reach the chosen + state directly, or the request fails and you can retry. + + Temp Resource Names + ------------------- + + Temp resource names are a special type of resource name used to + create a resource and reference that resource in the same + request. For example, if a campaign budget is created with + ``resource_name`` equal to ``customers/123/campaignBudgets/-1``, + that resource name can be reused in the ``Campaign.budget`` + field in the same request. That way, the two resources are + created and linked atomically. + + To create a temp resource name, put a negative number in the + part of the name that the server would normally allocate. + + Note: + + - Resources must be created with a temp name before the name can + be reused. For example, the previous CampaignBudget+Campaign + example would fail if the mutate order was reversed. + - Temp names are not remembered across requests. + - There's no limit to the number of temp names in a request. + - Each temp name must use a unique negative number, even if the + resource types differ. + + Latency + ------- + + It's important to group mutates by resource type or the request + may time out and fail. Latency is roughly equal to a series of + calls to individual mutate methods, where each change in + resource type is a new call. For example, mutating 10 campaigns + then 10 ad groups is like 2 calls, while mutating 1 campaign, 1 + ad group, 1 campaign, 1 ad group is like 4 calls. + + List of thrown errors: `AdCustomizerError <>`__ `AdError <>`__ + `AdGroupAdError <>`__ `AdGroupCriterionError <>`__ + `AdGroupError <>`__ `AssetError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ `BiddingError <>`__ + `CampaignBudgetError <>`__ `CampaignCriterionError <>`__ + `CampaignError <>`__ `CampaignExperimentError <>`__ + `CampaignSharedSetError <>`__ `CollectionSizeError <>`__ + `ContextError <>`__ `ConversionActionError <>`__ + `CriterionError <>`__ `CustomerFeedError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DateRangeError <>`__ + `DistinctError <>`__ `ExtensionFeedItemError <>`__ + `ExtensionSettingError <>`__ `FeedAttributeReferenceError <>`__ + `FeedError <>`__ `FeedItemError <>`__ `FeedItemSetError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `ImageError <>`__ + `InternalError <>`__ `KeywordPlanAdGroupKeywordError <>`__ + `KeywordPlanCampaignError <>`__ `KeywordPlanError <>`__ + `LabelError <>`__ `ListOperationError <>`__ + `MediaUploadError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `PolicyFindingError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SettingError <>`__ `SharedSetError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ `UserListError <>`__ + `YoutubeVideoRegistrationError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateGoogleAdsRequest, dict]]): + The request object. Request message for + [GoogleAdsService.Mutate][google.ads.googleads.v24.services.GoogleAdsService.Mutate]. + customer_id (:class:`str`): + Required. The ID of the customer + whose resources are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + mutate_operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.MutateOperation]`): + Required. The list of operations to + perform on individual resources. + + This corresponds to the ``mutate_operations`` 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.ads.googleads.v24.services.types.MutateGoogleAdsResponse: + Response message for + [GoogleAdsService.Mutate][google.ads.googleads.v24.services.GoogleAdsService.Mutate]. + + """ + # 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 = [customer_id, mutate_operations] + 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, google_ads_service.MutateGoogleAdsRequest): + request = google_ads_service.MutateGoogleAdsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if mutate_operations: + request.mutate_operations.extend(mutate_operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "GoogleAdsServiceAsyncClient": + 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__ = ("GoogleAdsServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/google_ads_service/client.py b/google/ads/googleads/v24/services/services/google_ads_service/client.py new file mode 100644 index 000000000..8174ef1fb --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_service/client.py @@ -0,0 +1,5080 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Iterable, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.services.google_ads_service import pagers +from google.ads.googleads.v24.services.types import google_ads_service +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore +from .transports.base import GoogleAdsServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import GoogleAdsServiceGrpcTransport +from .transports.grpc_asyncio import GoogleAdsServiceGrpcAsyncIOTransport + + +class GoogleAdsServiceClientMeta(type): + """Metaclass for the GoogleAdsService 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[GoogleAdsServiceTransport]] + _transport_registry["grpc"] = GoogleAdsServiceGrpcTransport + _transport_registry["grpc_asyncio"] = GoogleAdsServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[GoogleAdsServiceTransport]: + """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 GoogleAdsServiceClient(metaclass=GoogleAdsServiceClientMeta): + """Service to fetch data and metrics across resources.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + GoogleAdsServiceClient: 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: + GoogleAdsServiceClient: 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) -> GoogleAdsServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GoogleAdsServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def accessible_bidding_strategy_path( + customer_id: str, + bidding_strategy_id: str, + ) -> str: + """Returns a fully-qualified accessible_bidding_strategy string.""" + return "customers/{customer_id}/accessibleBiddingStrategies/{bidding_strategy_id}".format( + customer_id=customer_id, + bidding_strategy_id=bidding_strategy_id, + ) + + @staticmethod + def parse_accessible_bidding_strategy_path(path: str) -> Dict[str, str]: + """Parses a accessible_bidding_strategy path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/accessibleBiddingStrategies/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def account_budget_path( + customer_id: str, + account_budget_id: str, + ) -> str: + """Returns a fully-qualified account_budget string.""" + return ( + "customers/{customer_id}/accountBudgets/{account_budget_id}".format( + customer_id=customer_id, + account_budget_id=account_budget_id, + ) + ) + + @staticmethod + def parse_account_budget_path(path: str) -> Dict[str, str]: + """Parses a account_budget path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/accountBudgets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def account_budget_proposal_path( + customer_id: str, + account_budget_proposal_id: str, + ) -> str: + """Returns a fully-qualified account_budget_proposal string.""" + return "customers/{customer_id}/accountBudgetProposals/{account_budget_proposal_id}".format( + customer_id=customer_id, + account_budget_proposal_id=account_budget_proposal_id, + ) + + @staticmethod + def parse_account_budget_proposal_path(path: str) -> Dict[str, str]: + """Parses a account_budget_proposal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/accountBudgetProposals/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def account_link_path( + customer_id: str, + account_link_id: str, + ) -> str: + """Returns a fully-qualified account_link string.""" + return "customers/{customer_id}/accountLinks/{account_link_id}".format( + customer_id=customer_id, + account_link_id=account_link_id, + ) + + @staticmethod + def parse_account_link_path(path: str) -> Dict[str, str]: + """Parses a account_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/accountLinks/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_path( + customer_id: str, + ad_id: str, + ) -> str: + """Returns a fully-qualified ad string.""" + return "customers/{customer_id}/ads/{ad_id}".format( + customer_id=customer_id, + ad_id=ad_id, + ) + + @staticmethod + def parse_ad_path(path: str) -> Dict[str, str]: + """Parses a ad path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/ads/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_path( + customer_id: str, + ad_group_id: str, + ) -> str: + """Returns a fully-qualified ad_group string.""" + return "customers/{customer_id}/adGroups/{ad_group_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ) + + @staticmethod + def parse_ad_group_path(path: str) -> Dict[str, str]: + """Parses a ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_ad_path( + customer_id: str, + ad_group_id: str, + ad_id: str, + ) -> str: + """Returns a fully-qualified ad_group_ad string.""" + return ( + "customers/{customer_id}/adGroupAds/{ad_group_id}~{ad_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ad_id=ad_id, + ) + ) + + @staticmethod + def parse_ad_group_ad_path(path: str) -> Dict[str, str]: + """Parses a ad_group_ad path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAds/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_ad_asset_combination_view_path( + customer_id: str, + ad_group_id: str, + ad_id: str, + asset_combination_id_low: str, + asset_combination_id_high: str, + ) -> str: + """Returns a fully-qualified ad_group_ad_asset_combination_view string.""" + return "customers/{customer_id}/adGroupAdAssetCombinationViews/{ad_group_id}~{ad_id}~{asset_combination_id_low}~{asset_combination_id_high}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ad_id=ad_id, + asset_combination_id_low=asset_combination_id_low, + asset_combination_id_high=asset_combination_id_high, + ) + + @staticmethod + def parse_ad_group_ad_asset_combination_view_path( + path: str, + ) -> Dict[str, str]: + """Parses a ad_group_ad_asset_combination_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAdAssetCombinationViews/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_ad_asset_view_path( + customer_id: str, + ad_group_id: str, + ad_id: str, + asset_id: str, + field_type: str, + ) -> str: + """Returns a fully-qualified ad_group_ad_asset_view string.""" + return "customers/{customer_id}/adGroupAdAssetViews/{ad_group_id}~{ad_id}~{asset_id}~{field_type}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ad_id=ad_id, + asset_id=asset_id, + field_type=field_type, + ) + + @staticmethod + def parse_ad_group_ad_asset_view_path(path: str) -> Dict[str, str]: + """Parses a ad_group_ad_asset_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAdAssetViews/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_ad_label_path( + customer_id: str, + ad_group_id: str, + ad_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified ad_group_ad_label string.""" + return "customers/{customer_id}/adGroupAdLabels/{ad_group_id}~{ad_id}~{label_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ad_id=ad_id, + label_id=label_id, + ) + + @staticmethod + def parse_ad_group_ad_label_path(path: str) -> Dict[str, str]: + """Parses a ad_group_ad_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAdLabels/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_asset_path( + customer_id: str, + ad_group_id: str, + asset_id: str, + field_type: str, + ) -> str: + """Returns a fully-qualified ad_group_asset string.""" + return "customers/{customer_id}/adGroupAssets/{ad_group_id}~{asset_id}~{field_type}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + asset_id=asset_id, + field_type=field_type, + ) + + @staticmethod + def parse_ad_group_asset_path(path: str) -> Dict[str, str]: + """Parses a ad_group_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAssets/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_asset_set_path( + customer_id: str, + ad_group_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified ad_group_asset_set string.""" + return "customers/{customer_id}/adGroupAssetSets/{ad_group_id}~{asset_set_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + asset_set_id=asset_set_id, + ) + + @staticmethod + def parse_ad_group_asset_set_path(path: str) -> Dict[str, str]: + """Parses a ad_group_asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAssetSets/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_audience_view_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified ad_group_audience_view string.""" + return "customers/{customer_id}/adGroupAudienceViews/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_ad_group_audience_view_path(path: str) -> Dict[str, str]: + """Parses a ad_group_audience_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupAudienceViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_bid_modifier_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified ad_group_bid_modifier string.""" + return "customers/{customer_id}/adGroupBidModifiers/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_ad_group_bid_modifier_path(path: str) -> Dict[str, str]: + """Parses a ad_group_bid_modifier path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupBidModifiers/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_criterion_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified ad_group_criterion string.""" + return "customers/{customer_id}/adGroupCriteria/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_ad_group_criterion_path(path: str) -> Dict[str, str]: + """Parses a ad_group_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCriteria/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_criterion_customizer_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified ad_group_criterion_customizer string.""" + return "customers/{customer_id}/adGroupCriterionCustomizers/{ad_group_id}~{criterion_id}~{customizer_attribute_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_ad_group_criterion_customizer_path(path: str) -> Dict[str, str]: + """Parses a ad_group_criterion_customizer path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCriterionCustomizers/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_criterion_label_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified ad_group_criterion_label string.""" + return "customers/{customer_id}/adGroupCriterionLabels/{ad_group_id}~{criterion_id}~{label_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + label_id=label_id, + ) + + @staticmethod + def parse_ad_group_criterion_label_path(path: str) -> Dict[str, str]: + """Parses a ad_group_criterion_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCriterionLabels/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_criterion_simulation_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + type: str, + modification_method: str, + start_date: str, + end_date: str, + ) -> str: + """Returns a fully-qualified ad_group_criterion_simulation string.""" + return "customers/{customer_id}/adGroupCriterionSimulations/{ad_group_id}~{criterion_id}~{type}~{modification_method}~{start_date}~{end_date}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + type=type, + modification_method=modification_method, + start_date=start_date, + end_date=end_date, + ) + + @staticmethod + def parse_ad_group_criterion_simulation_path(path: str) -> Dict[str, str]: + """Parses a ad_group_criterion_simulation path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCriterionSimulations/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_customizer_path( + customer_id: str, + ad_group_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified ad_group_customizer string.""" + return "customers/{customer_id}/adGroupCustomizers/{ad_group_id}~{customizer_attribute_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_ad_group_customizer_path(path: str) -> Dict[str, str]: + """Parses a ad_group_customizer path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupCustomizers/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_label_path( + customer_id: str, + ad_group_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified ad_group_label string.""" + return "customers/{customer_id}/adGroupLabels/{ad_group_id}~{label_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + label_id=label_id, + ) + + @staticmethod + def parse_ad_group_label_path(path: str) -> Dict[str, str]: + """Parses a ad_group_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupLabels/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_simulation_path( + customer_id: str, + ad_group_id: str, + type: str, + modification_method: str, + start_date: str, + end_date: str, + ) -> str: + """Returns a fully-qualified ad_group_simulation string.""" + return "customers/{customer_id}/adGroupSimulations/{ad_group_id}~{type}~{modification_method}~{start_date}~{end_date}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + type=type, + modification_method=modification_method, + start_date=start_date, + end_date=end_date, + ) + + @staticmethod + def parse_ad_group_simulation_path(path: str) -> Dict[str, str]: + """Parses a ad_group_simulation path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupSimulations/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_parameter_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + parameter_index: str, + ) -> str: + """Returns a fully-qualified ad_parameter string.""" + return "customers/{customer_id}/adParameters/{ad_group_id}~{criterion_id}~{parameter_index}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + parameter_index=parameter_index, + ) + + @staticmethod + def parse_ad_parameter_path(path: str) -> Dict[str, str]: + """Parses a ad_parameter path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adParameters/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_schedule_view_path( + customer_id: str, + campaign_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified ad_schedule_view string.""" + return "customers/{customer_id}/adScheduleViews/{campaign_id}~{criterion_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_ad_schedule_view_path(path: str) -> Dict[str, str]: + """Parses a ad_schedule_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adScheduleViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def age_range_view_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified age_range_view string.""" + return "customers/{customer_id}/ageRangeViews/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_age_range_view_path(path: str) -> Dict[str, str]: + """Parses a age_range_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/ageRangeViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ai_max_search_term_ad_combination_view_path( + customer_id: str, + ad_group_id: str, + search_term: str, + landing_page: str, + headline: str, + ) -> str: + """Returns a fully-qualified ai_max_search_term_ad_combination_view string.""" + return "customers/{customer_id}/aiMaxSearchTermAdCombinationViews/{ad_group_id}~{search_term}~{landing_page}~{headline}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + search_term=search_term, + landing_page=landing_page, + headline=headline, + ) + + @staticmethod + def parse_ai_max_search_term_ad_combination_view_path( + path: str, + ) -> Dict[str, str]: + """Parses a ai_max_search_term_ad_combination_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/aiMaxSearchTermAdCombinationViews/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def android_privacy_shared_key_google_ad_group_path( + customer_id: str, + campaign_id: str, + ad_group_id: str, + android_privacy_interaction_type: str, + android_privacy_network_type: str, + android_privacy_interaction_date: str, + ) -> str: + """Returns a fully-qualified android_privacy_shared_key_google_ad_group string.""" + return "customers/{customer_id}/androidPrivacySharedKeyGoogleAdGroups/{campaign_id}~{ad_group_id}~{android_privacy_interaction_type}~{android_privacy_network_type}~{android_privacy_interaction_date}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ad_group_id=ad_group_id, + android_privacy_interaction_type=android_privacy_interaction_type, + android_privacy_network_type=android_privacy_network_type, + android_privacy_interaction_date=android_privacy_interaction_date, + ) + + @staticmethod + def parse_android_privacy_shared_key_google_ad_group_path( + path: str, + ) -> Dict[str, str]: + """Parses a android_privacy_shared_key_google_ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/androidPrivacySharedKeyGoogleAdGroups/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def android_privacy_shared_key_google_campaign_path( + customer_id: str, + campaign_id: str, + android_privacy_interaction_type: str, + android_privacy_interaction_date: str, + ) -> str: + """Returns a fully-qualified android_privacy_shared_key_google_campaign string.""" + return "customers/{customer_id}/androidPrivacySharedKeyGoogleCampaigns/{campaign_id}~{android_privacy_interaction_type}~{android_privacy_interaction_date}".format( + customer_id=customer_id, + campaign_id=campaign_id, + android_privacy_interaction_type=android_privacy_interaction_type, + android_privacy_interaction_date=android_privacy_interaction_date, + ) + + @staticmethod + def parse_android_privacy_shared_key_google_campaign_path( + path: str, + ) -> Dict[str, str]: + """Parses a android_privacy_shared_key_google_campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/androidPrivacySharedKeyGoogleCampaigns/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def android_privacy_shared_key_google_network_type_path( + customer_id: str, + campaign_id: str, + android_privacy_interaction_type: str, + android_privacy_network_type: str, + android_privacy_interaction_date: str, + ) -> str: + """Returns a fully-qualified android_privacy_shared_key_google_network_type string.""" + return "customers/{customer_id}/androidPrivacySharedKeyGoogleNetworkTypes/{campaign_id}~{android_privacy_interaction_type}~{android_privacy_network_type}~{android_privacy_interaction_date}".format( + customer_id=customer_id, + campaign_id=campaign_id, + android_privacy_interaction_type=android_privacy_interaction_type, + android_privacy_network_type=android_privacy_network_type, + android_privacy_interaction_date=android_privacy_interaction_date, + ) + + @staticmethod + def parse_android_privacy_shared_key_google_network_type_path( + path: str, + ) -> Dict[str, str]: + """Parses a android_privacy_shared_key_google_network_type path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/androidPrivacySharedKeyGoogleNetworkTypes/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def applied_incentive_path( + customer_id: str, + coupon_code: str, + ) -> str: + """Returns a fully-qualified applied_incentive string.""" + return "customers/{customer_id}/appliedIncentives/{coupon_code}".format( + customer_id=customer_id, + coupon_code=coupon_code, + ) + + @staticmethod + def parse_applied_incentive_path(path: str) -> Dict[str, str]: + """Parses a applied_incentive path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/appliedIncentives/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def app_top_combination_view_path( + customer_id: str, + ad_group_id: str, + ad_id: str, + asset_combination_category: str, + ) -> str: + """Returns a fully-qualified app_top_combination_view string.""" + return "customers/{customer_id}/appTopCombinationViews/{ad_group_id}~{ad_id}~{asset_combination_category}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ad_id=ad_id, + asset_combination_category=asset_combination_category, + ) + + @staticmethod + def parse_app_top_combination_view_path(path: str) -> Dict[str, str]: + """Parses a app_top_combination_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/appTopCombinationViews/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_path( + customer_id: str, + asset_id: str, + ) -> str: + """Returns a fully-qualified asset string.""" + return "customers/{customer_id}/assets/{asset_id}".format( + customer_id=customer_id, + asset_id=asset_id, + ) + + @staticmethod + def parse_asset_path(path: str) -> Dict[str, str]: + """Parses a asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assets/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_field_type_view_path( + customer_id: str, + field_type: str, + ) -> str: + """Returns a fully-qualified asset_field_type_view string.""" + return ( + "customers/{customer_id}/assetFieldTypeViews/{field_type}".format( + customer_id=customer_id, + field_type=field_type, + ) + ) + + @staticmethod + def parse_asset_field_type_view_path(path: str) -> Dict[str, str]: + """Parses a asset_field_type_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetFieldTypeViews/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_path( + customer_id: str, + asset_group_id: str, + ) -> str: + """Returns a fully-qualified asset_group string.""" + return "customers/{customer_id}/assetGroups/{asset_group_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + ) + + @staticmethod + def parse_asset_group_path(path: str) -> Dict[str, str]: + """Parses a asset_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_asset_path( + customer_id: str, + asset_group_id: str, + asset_id: str, + field_type: str, + ) -> str: + """Returns a fully-qualified asset_group_asset string.""" + return "customers/{customer_id}/assetGroupAssets/{asset_group_id}~{asset_id}~{field_type}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + asset_id=asset_id, + field_type=field_type, + ) + + @staticmethod + def parse_asset_group_asset_path(path: str) -> Dict[str, str]: + """Parses a asset_group_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroupAssets/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_listing_group_filter_path( + customer_id: str, + asset_group_id: str, + listing_group_filter_id: str, + ) -> str: + """Returns a fully-qualified asset_group_listing_group_filter string.""" + return "customers/{customer_id}/assetGroupListingGroupFilters/{asset_group_id}~{listing_group_filter_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + listing_group_filter_id=listing_group_filter_id, + ) + + @staticmethod + def parse_asset_group_listing_group_filter_path( + path: str, + ) -> Dict[str, str]: + """Parses a asset_group_listing_group_filter path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroupListingGroupFilters/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_product_group_view_path( + customer_id: str, + asset_group_id: str, + listing_group_filter_id: str, + ) -> str: + """Returns a fully-qualified asset_group_product_group_view string.""" + return "customers/{customer_id}/assetGroupProductGroupViews/{asset_group_id}~{listing_group_filter_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + listing_group_filter_id=listing_group_filter_id, + ) + + @staticmethod + def parse_asset_group_product_group_view_path(path: str) -> Dict[str, str]: + """Parses a asset_group_product_group_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroupProductGroupViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_signal_path( + customer_id: str, + asset_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified asset_group_signal string.""" + return "customers/{customer_id}/assetGroupSignals/{asset_group_id}~{criterion_id}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_asset_group_signal_path(path: str) -> Dict[str, str]: + """Parses a asset_group_signal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroupSignals/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_group_top_combination_view_path( + customer_id: str, + asset_group_id: str, + asset_combination_category: str, + ) -> str: + """Returns a fully-qualified asset_group_top_combination_view string.""" + return "customers/{customer_id}/assetGroupTopCombinationViews/{asset_group_id}~{asset_combination_category}".format( + customer_id=customer_id, + asset_group_id=asset_group_id, + asset_combination_category=asset_combination_category, + ) + + @staticmethod + def parse_asset_group_top_combination_view_path( + path: str, + ) -> Dict[str, str]: + """Parses a asset_group_top_combination_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetGroupTopCombinationViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_set_path( + customer_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified asset_set string.""" + return "customers/{customer_id}/assetSets/{asset_set_id}".format( + customer_id=customer_id, + asset_set_id=asset_set_id, + ) + + @staticmethod + def parse_asset_set_path(path: str) -> Dict[str, str]: + """Parses a asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetSets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_set_asset_path( + customer_id: str, + asset_set_id: str, + asset_id: str, + ) -> str: + """Returns a fully-qualified asset_set_asset string.""" + return "customers/{customer_id}/assetSetAssets/{asset_set_id}~{asset_id}".format( + customer_id=customer_id, + asset_set_id=asset_set_id, + asset_id=asset_id, + ) + + @staticmethod + def parse_asset_set_asset_path(path: str) -> Dict[str, str]: + """Parses a asset_set_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetSetAssets/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_set_type_view_path( + customer_id: str, + asset_set_type: str, + ) -> str: + """Returns a fully-qualified asset_set_type_view string.""" + return ( + "customers/{customer_id}/assetSetTypeViews/{asset_set_type}".format( + customer_id=customer_id, + asset_set_type=asset_set_type, + ) + ) + + @staticmethod + def parse_asset_set_type_view_path(path: str) -> Dict[str, str]: + """Parses a asset_set_type_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assetSetTypeViews/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def audience_path( + customer_id: str, + audience_id: str, + ) -> str: + """Returns a fully-qualified audience string.""" + return "customers/{customer_id}/audiences/{audience_id}".format( + customer_id=customer_id, + audience_id=audience_id, + ) + + @staticmethod + def parse_audience_path(path: str) -> Dict[str, str]: + """Parses a audience path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/audiences/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def batch_job_path( + customer_id: str, + batch_job_id: str, + ) -> str: + """Returns a fully-qualified batch_job string.""" + return "customers/{customer_id}/batchJobs/{batch_job_id}".format( + customer_id=customer_id, + batch_job_id=batch_job_id, + ) + + @staticmethod + def parse_batch_job_path(path: str) -> Dict[str, str]: + """Parses a batch_job path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/batchJobs/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def bidding_data_exclusion_path( + customer_id: str, + seasonality_event_id: str, + ) -> str: + """Returns a fully-qualified bidding_data_exclusion string.""" + return "customers/{customer_id}/biddingDataExclusions/{seasonality_event_id}".format( + customer_id=customer_id, + seasonality_event_id=seasonality_event_id, + ) + + @staticmethod + def parse_bidding_data_exclusion_path(path: str) -> Dict[str, str]: + """Parses a bidding_data_exclusion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/biddingDataExclusions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def bidding_seasonality_adjustment_path( + customer_id: str, + seasonality_event_id: str, + ) -> str: + """Returns a fully-qualified bidding_seasonality_adjustment string.""" + return "customers/{customer_id}/biddingSeasonalityAdjustments/{seasonality_event_id}".format( + customer_id=customer_id, + seasonality_event_id=seasonality_event_id, + ) + + @staticmethod + def parse_bidding_seasonality_adjustment_path(path: str) -> Dict[str, str]: + """Parses a bidding_seasonality_adjustment path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/biddingSeasonalityAdjustments/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def bidding_strategy_path( + customer_id: str, + bidding_strategy_id: str, + ) -> str: + """Returns a fully-qualified bidding_strategy string.""" + return "customers/{customer_id}/biddingStrategies/{bidding_strategy_id}".format( + customer_id=customer_id, + bidding_strategy_id=bidding_strategy_id, + ) + + @staticmethod + def parse_bidding_strategy_path(path: str) -> Dict[str, str]: + """Parses a bidding_strategy path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/biddingStrategies/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def bidding_strategy_simulation_path( + customer_id: str, + bidding_strategy_id: str, + type: str, + modification_method: str, + start_date: str, + end_date: str, + ) -> str: + """Returns a fully-qualified bidding_strategy_simulation string.""" + return "customers/{customer_id}/biddingStrategySimulations/{bidding_strategy_id}~{type}~{modification_method}~{start_date}~{end_date}".format( + customer_id=customer_id, + bidding_strategy_id=bidding_strategy_id, + type=type, + modification_method=modification_method, + start_date=start_date, + end_date=end_date, + ) + + @staticmethod + def parse_bidding_strategy_simulation_path(path: str) -> Dict[str, str]: + """Parses a bidding_strategy_simulation path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/biddingStrategySimulations/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def billing_setup_path( + customer_id: str, + billing_setup_id: str, + ) -> str: + """Returns a fully-qualified billing_setup string.""" + return ( + "customers/{customer_id}/billingSetups/{billing_setup_id}".format( + customer_id=customer_id, + billing_setup_id=billing_setup_id, + ) + ) + + @staticmethod + def parse_billing_setup_path(path: str) -> Dict[str, str]: + """Parses a billing_setup path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/billingSetups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def call_view_path( + customer_id: str, + call_detail_id: str, + ) -> str: + """Returns a fully-qualified call_view string.""" + return "customers/{customer_id}/callViews/{call_detail_id}".format( + customer_id=customer_id, + call_detail_id=call_detail_id, + ) + + @staticmethod + def parse_call_view_path(path: str) -> Dict[str, str]: + """Parses a call_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/callViews/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_aggregate_asset_view_path( + customer_id: str, + campaign_id: str, + asset_id: str, + asset_link_source: str, + field_type: str, + ) -> str: + """Returns a fully-qualified campaign_aggregate_asset_view string.""" + return "customers/{customer_id}/campaignAggregateAssetViews/{campaign_id}~{asset_id}~{asset_link_source}~{field_type}".format( + customer_id=customer_id, + campaign_id=campaign_id, + asset_id=asset_id, + asset_link_source=asset_link_source, + field_type=field_type, + ) + + @staticmethod + def parse_campaign_aggregate_asset_view_path(path: str) -> Dict[str, str]: + """Parses a campaign_aggregate_asset_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignAggregateAssetViews/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_asset_path( + customer_id: str, + campaign_id: str, + asset_id: str, + field_type: str, + ) -> str: + """Returns a fully-qualified campaign_asset string.""" + return "customers/{customer_id}/campaignAssets/{campaign_id}~{asset_id}~{field_type}".format( + customer_id=customer_id, + campaign_id=campaign_id, + asset_id=asset_id, + field_type=field_type, + ) + + @staticmethod + def parse_campaign_asset_path(path: str) -> Dict[str, str]: + """Parses a campaign_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignAssets/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_asset_set_path( + customer_id: str, + campaign_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified campaign_asset_set string.""" + return "customers/{customer_id}/campaignAssetSets/{campaign_id}~{asset_set_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + asset_set_id=asset_set_id, + ) + + @staticmethod + def parse_campaign_asset_set_path(path: str) -> Dict[str, str]: + """Parses a campaign_asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignAssetSets/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_audience_view_path( + customer_id: str, + campaign_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified campaign_audience_view string.""" + return "customers/{customer_id}/campaignAudienceViews/{campaign_id}~{criterion_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_campaign_audience_view_path(path: str) -> Dict[str, str]: + """Parses a campaign_audience_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignAudienceViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_bid_modifier_path( + customer_id: str, + campaign_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified campaign_bid_modifier string.""" + return "customers/{customer_id}/campaignBidModifiers/{campaign_id}~{criterion_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_campaign_bid_modifier_path(path: str) -> Dict[str, str]: + """Parses a campaign_bid_modifier path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignBidModifiers/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_budget_path( + customer_id: str, + campaign_budget_id: str, + ) -> str: + """Returns a fully-qualified campaign_budget string.""" + return "customers/{customer_id}/campaignBudgets/{campaign_budget_id}".format( + customer_id=customer_id, + campaign_budget_id=campaign_budget_id, + ) + + @staticmethod + def parse_campaign_budget_path(path: str) -> Dict[str, str]: + """Parses a campaign_budget path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignBudgets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_conversion_goal_path( + customer_id: str, + campaign_id: str, + category: str, + source: str, + ) -> str: + """Returns a fully-qualified campaign_conversion_goal string.""" + return "customers/{customer_id}/campaignConversionGoals/{campaign_id}~{category}~{source}".format( + customer_id=customer_id, + campaign_id=campaign_id, + category=category, + source=source, + ) + + @staticmethod + def parse_campaign_conversion_goal_path(path: str) -> Dict[str, str]: + """Parses a campaign_conversion_goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignConversionGoals/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_criterion_path( + customer_id: str, + campaign_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified campaign_criterion string.""" + return "customers/{customer_id}/campaignCriteria/{campaign_id}~{criterion_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_campaign_criterion_path(path: str) -> Dict[str, str]: + """Parses a campaign_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignCriteria/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_customizer_path( + customer_id: str, + campaign_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified campaign_customizer string.""" + return "customers/{customer_id}/campaignCustomizers/{campaign_id}~{customizer_attribute_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_campaign_customizer_path(path: str) -> Dict[str, str]: + """Parses a campaign_customizer path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignCustomizers/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_draft_path( + customer_id: str, + base_campaign_id: str, + draft_id: str, + ) -> str: + """Returns a fully-qualified campaign_draft string.""" + return "customers/{customer_id}/campaignDrafts/{base_campaign_id}~{draft_id}".format( + customer_id=customer_id, + base_campaign_id=base_campaign_id, + draft_id=draft_id, + ) + + @staticmethod + def parse_campaign_draft_path(path: str) -> Dict[str, str]: + """Parses a campaign_draft path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignDrafts/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_goal_config_path( + customer_id: str, + campaign_id: str, + unified_goal_id: str, + ) -> str: + """Returns a fully-qualified campaign_goal_config string.""" + return "customers/{customer_id}/campaignGoalConfigs/{campaign_id}~{unified_goal_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + unified_goal_id=unified_goal_id, + ) + + @staticmethod + def parse_campaign_goal_config_path(path: str) -> Dict[str, str]: + """Parses a campaign_goal_config path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignGoalConfigs/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_group_path( + customer_id: str, + campaign_group_id: str, + ) -> str: + """Returns a fully-qualified campaign_group string.""" + return ( + "customers/{customer_id}/campaignGroups/{campaign_group_id}".format( + customer_id=customer_id, + campaign_group_id=campaign_group_id, + ) + ) + + @staticmethod + def parse_campaign_group_path(path: str) -> Dict[str, str]: + """Parses a campaign_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_label_path( + customer_id: str, + campaign_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified campaign_label string.""" + return "customers/{customer_id}/campaignLabels/{campaign_id}~{label_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + label_id=label_id, + ) + + @staticmethod + def parse_campaign_label_path(path: str) -> Dict[str, str]: + """Parses a campaign_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignLabels/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_lifecycle_goal_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign_lifecycle_goal string.""" + return "customers/{customer_id}/campaignLifecycleGoals/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_lifecycle_goal_path(path: str) -> Dict[str, str]: + """Parses a campaign_lifecycle_goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignLifecycleGoals/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_search_term_insight_path( + customer_id: str, + campaign_id: str, + cluster_id: str, + ) -> str: + """Returns a fully-qualified campaign_search_term_insight string.""" + return "customers/{customer_id}/campaignSearchTermInsights/{campaign_id}~{cluster_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + cluster_id=cluster_id, + ) + + @staticmethod + def parse_campaign_search_term_insight_path(path: str) -> Dict[str, str]: + """Parses a campaign_search_term_insight path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignSearchTermInsights/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_search_term_view_path( + customer_id: str, + campaign_id: str, + query: str, + ) -> str: + """Returns a fully-qualified campaign_search_term_view string.""" + return "customers/{customer_id}/campaignSearchTermViews/{campaign_id}~{query}".format( + customer_id=customer_id, + campaign_id=campaign_id, + query=query, + ) + + @staticmethod + def parse_campaign_search_term_view_path(path: str) -> Dict[str, str]: + """Parses a campaign_search_term_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignSearchTermViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_shared_set_path( + customer_id: str, + campaign_id: str, + shared_set_id: str, + ) -> str: + """Returns a fully-qualified campaign_shared_set string.""" + return "customers/{customer_id}/campaignSharedSets/{campaign_id}~{shared_set_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + shared_set_id=shared_set_id, + ) + + @staticmethod + def parse_campaign_shared_set_path(path: str) -> Dict[str, str]: + """Parses a campaign_shared_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignSharedSets/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_simulation_path( + customer_id: str, + campaign_id: str, + type: str, + modification_method: str, + start_date: str, + end_date: str, + ) -> str: + """Returns a fully-qualified campaign_simulation string.""" + return "customers/{customer_id}/campaignSimulations/{campaign_id}~{type}~{modification_method}~{start_date}~{end_date}".format( + customer_id=customer_id, + campaign_id=campaign_id, + type=type, + modification_method=modification_method, + start_date=start_date, + end_date=end_date, + ) + + @staticmethod + def parse_campaign_simulation_path(path: str) -> Dict[str, str]: + """Parses a campaign_simulation path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignSimulations/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def carrier_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified carrier_constant string.""" + return "carrierConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_carrier_constant_path(path: str) -> Dict[str, str]: + """Parses a carrier_constant path into its component segments.""" + m = re.match(r"^carrierConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def cart_data_sales_view_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified cart_data_sales_view string.""" + return "customers/{customer_id}/cartDataSalesView".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_cart_data_sales_view_path(path: str) -> Dict[str, str]: + """Parses a cart_data_sales_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/cartDataSalesView$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def change_event_path( + customer_id: str, + timestamp_micros: str, + command_index: str, + mutate_index: str, + ) -> str: + """Returns a fully-qualified change_event string.""" + return "customers/{customer_id}/changeEvents/{timestamp_micros}~{command_index}~{mutate_index}".format( + customer_id=customer_id, + timestamp_micros=timestamp_micros, + command_index=command_index, + mutate_index=mutate_index, + ) + + @staticmethod + def parse_change_event_path(path: str) -> Dict[str, str]: + """Parses a change_event path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/changeEvents/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def change_status_path( + customer_id: str, + change_status_id: str, + ) -> str: + """Returns a fully-qualified change_status string.""" + return "customers/{customer_id}/changeStatus/{change_status_id}".format( + customer_id=customer_id, + change_status_id=change_status_id, + ) + + @staticmethod + def parse_change_status_path(path: str) -> Dict[str, str]: + """Parses a change_status path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/changeStatus/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def channel_aggregate_asset_view_path( + customer_id: str, + advertising_channel_type: str, + asset_id: str, + asset_source: str, + field_type: str, + ) -> str: + """Returns a fully-qualified channel_aggregate_asset_view string.""" + return "customers/{customer_id}/channelAggregateAssetViews/{advertising_channel_type}~{asset_id}~{asset_source}~{field_type}".format( + customer_id=customer_id, + advertising_channel_type=advertising_channel_type, + asset_id=asset_id, + asset_source=asset_source, + field_type=field_type, + ) + + @staticmethod + def parse_channel_aggregate_asset_view_path(path: str) -> Dict[str, str]: + """Parses a channel_aggregate_asset_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/channelAggregateAssetViews/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def click_view_path( + customer_id: str, + date: str, + gclid: str, + ) -> str: + """Returns a fully-qualified click_view string.""" + return "customers/{customer_id}/clickViews/{date}~{gclid}".format( + customer_id=customer_id, + date=date, + gclid=gclid, + ) + + @staticmethod + def parse_click_view_path(path: str) -> Dict[str, str]: + """Parses a click_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/clickViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def combined_audience_path( + customer_id: str, + combined_audience_id: str, + ) -> str: + """Returns a fully-qualified combined_audience string.""" + return "customers/{customer_id}/combinedAudiences/{combined_audience_id}".format( + customer_id=customer_id, + combined_audience_id=combined_audience_id, + ) + + @staticmethod + def parse_combined_audience_path(path: str) -> Dict[str, str]: + """Parses a combined_audience path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/combinedAudiences/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def content_criterion_view_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified content_criterion_view string.""" + return "customers/{customer_id}/contentCriterionViews/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_content_criterion_view_path(path: str) -> Dict[str, str]: + """Parses a content_criterion_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/contentCriterionViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_action_path( + customer_id: str, + conversion_action_id: str, + ) -> str: + """Returns a fully-qualified conversion_action string.""" + return "customers/{customer_id}/conversionActions/{conversion_action_id}".format( + customer_id=customer_id, + conversion_action_id=conversion_action_id, + ) + + @staticmethod + def parse_conversion_action_path(path: str) -> Dict[str, str]: + """Parses a conversion_action path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionActions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_custom_variable_path( + customer_id: str, + conversion_custom_variable_id: str, + ) -> str: + """Returns a fully-qualified conversion_custom_variable string.""" + return "customers/{customer_id}/conversionCustomVariables/{conversion_custom_variable_id}".format( + customer_id=customer_id, + conversion_custom_variable_id=conversion_custom_variable_id, + ) + + @staticmethod + def parse_conversion_custom_variable_path(path: str) -> Dict[str, str]: + """Parses a conversion_custom_variable path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionCustomVariables/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_goal_campaign_config_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified conversion_goal_campaign_config string.""" + return "customers/{customer_id}/conversionGoalCampaignConfigs/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_conversion_goal_campaign_config_path(path: str) -> Dict[str, str]: + """Parses a conversion_goal_campaign_config path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionGoalCampaignConfigs/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_value_rule_path( + customer_id: str, + conversion_value_rule_id: str, + ) -> str: + """Returns a fully-qualified conversion_value_rule string.""" + return "customers/{customer_id}/conversionValueRules/{conversion_value_rule_id}".format( + customer_id=customer_id, + conversion_value_rule_id=conversion_value_rule_id, + ) + + @staticmethod + def parse_conversion_value_rule_path(path: str) -> Dict[str, str]: + """Parses a conversion_value_rule path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionValueRules/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_value_rule_set_path( + customer_id: str, + conversion_value_rule_set_id: str, + ) -> str: + """Returns a fully-qualified conversion_value_rule_set string.""" + return "customers/{customer_id}/conversionValueRuleSets/{conversion_value_rule_set_id}".format( + customer_id=customer_id, + conversion_value_rule_set_id=conversion_value_rule_set_id, + ) + + @staticmethod + def parse_conversion_value_rule_set_path(path: str) -> Dict[str, str]: + """Parses a conversion_value_rule_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionValueRuleSets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def currency_constant_path( + code: str, + ) -> str: + """Returns a fully-qualified currency_constant string.""" + return "currencyConstants/{code}".format( + code=code, + ) + + @staticmethod + def parse_currency_constant_path(path: str) -> Dict[str, str]: + """Parses a currency_constant path into its component segments.""" + m = re.match(r"^currencyConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def custom_audience_path( + customer_id: str, + custom_audience_id: str, + ) -> str: + """Returns a fully-qualified custom_audience string.""" + return "customers/{customer_id}/customAudiences/{custom_audience_id}".format( + customer_id=customer_id, + custom_audience_id=custom_audience_id, + ) + + @staticmethod + def parse_custom_audience_path(path: str) -> Dict[str, str]: + """Parses a custom_audience path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customAudiences/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def custom_conversion_goal_path( + customer_id: str, + goal_id: str, + ) -> str: + """Returns a fully-qualified custom_conversion_goal string.""" + return "customers/{customer_id}/customConversionGoals/{goal_id}".format( + customer_id=customer_id, + goal_id=goal_id, + ) + + @staticmethod + def parse_custom_conversion_goal_path(path: str) -> Dict[str, str]: + """Parses a custom_conversion_goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customConversionGoals/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def customer_asset_path( + customer_id: str, + asset_id: str, + field_type: str, + ) -> str: + """Returns a fully-qualified customer_asset string.""" + return "customers/{customer_id}/customerAssets/{asset_id}~{field_type}".format( + customer_id=customer_id, + asset_id=asset_id, + field_type=field_type, + ) + + @staticmethod + def parse_customer_asset_path(path: str) -> Dict[str, str]: + """Parses a customer_asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerAssets/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_asset_set_path( + customer_id: str, + asset_set_id: str, + ) -> str: + """Returns a fully-qualified customer_asset_set string.""" + return ( + "customers/{customer_id}/customerAssetSets/{asset_set_id}".format( + customer_id=customer_id, + asset_set_id=asset_set_id, + ) + ) + + @staticmethod + def parse_customer_asset_set_path(path: str) -> Dict[str, str]: + """Parses a customer_asset_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerAssetSets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_client_path( + customer_id: str, + client_customer_id: str, + ) -> str: + """Returns a fully-qualified customer_client string.""" + return "customers/{customer_id}/customerClients/{client_customer_id}".format( + customer_id=customer_id, + client_customer_id=client_customer_id, + ) + + @staticmethod + def parse_customer_client_path(path: str) -> Dict[str, str]: + """Parses a customer_client path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerClients/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_client_link_path( + customer_id: str, + client_customer_id: str, + manager_link_id: str, + ) -> str: + """Returns a fully-qualified customer_client_link string.""" + return "customers/{customer_id}/customerClientLinks/{client_customer_id}~{manager_link_id}".format( + customer_id=customer_id, + client_customer_id=client_customer_id, + manager_link_id=manager_link_id, + ) + + @staticmethod + def parse_customer_client_link_path(path: str) -> Dict[str, str]: + """Parses a customer_client_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerClientLinks/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_conversion_goal_path( + customer_id: str, + category: str, + source: str, + ) -> str: + """Returns a fully-qualified customer_conversion_goal string.""" + return "customers/{customer_id}/customerConversionGoals/{category}~{source}".format( + customer_id=customer_id, + category=category, + source=source, + ) + + @staticmethod + def parse_customer_conversion_goal_path(path: str) -> Dict[str, str]: + """Parses a customer_conversion_goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerConversionGoals/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_customizer_path( + customer_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified customer_customizer string.""" + return "customers/{customer_id}/customerCustomizers/{customizer_attribute_id}".format( + customer_id=customer_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_customer_customizer_path(path: str) -> Dict[str, str]: + """Parses a customer_customizer path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerCustomizers/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_label_path( + customer_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified customer_label string.""" + return "customers/{customer_id}/customerLabels/{label_id}".format( + customer_id=customer_id, + label_id=label_id, + ) + + @staticmethod + def parse_customer_label_path(path: str) -> Dict[str, str]: + """Parses a customer_label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerLabels/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_lifecycle_goal_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer_lifecycle_goal string.""" + return "customers/{customer_id}/customerLifecycleGoals".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_lifecycle_goal_path(path: str) -> Dict[str, str]: + """Parses a customer_lifecycle_goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerLifecycleGoals$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_manager_link_path( + customer_id: str, + manager_customer_id: str, + manager_link_id: str, + ) -> str: + """Returns a fully-qualified customer_manager_link string.""" + return "customers/{customer_id}/customerManagerLinks/{manager_customer_id}~{manager_link_id}".format( + customer_id=customer_id, + manager_customer_id=manager_customer_id, + manager_link_id=manager_link_id, + ) + + @staticmethod + def parse_customer_manager_link_path(path: str) -> Dict[str, str]: + """Parses a customer_manager_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerManagerLinks/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_negative_criterion_path( + customer_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified customer_negative_criterion string.""" + return "customers/{customer_id}/customerNegativeCriteria/{criterion_id}".format( + customer_id=customer_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_customer_negative_criterion_path(path: str) -> Dict[str, str]: + """Parses a customer_negative_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerNegativeCriteria/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_search_term_insight_path( + customer_id: str, + cluster_id: str, + ) -> str: + """Returns a fully-qualified customer_search_term_insight string.""" + return "customers/{customer_id}/customerSearchTermInsights/{cluster_id}".format( + customer_id=customer_id, + cluster_id=cluster_id, + ) + + @staticmethod + def parse_customer_search_term_insight_path(path: str) -> Dict[str, str]: + """Parses a customer_search_term_insight path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerSearchTermInsights/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_user_access_path( + customer_id: str, + user_id: str, + ) -> str: + """Returns a fully-qualified customer_user_access string.""" + return "customers/{customer_id}/customerUserAccesses/{user_id}".format( + customer_id=customer_id, + user_id=user_id, + ) + + @staticmethod + def parse_customer_user_access_path(path: str) -> Dict[str, str]: + """Parses a customer_user_access path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerUserAccesses/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_user_access_invitation_path( + customer_id: str, + invitation_id: str, + ) -> str: + """Returns a fully-qualified customer_user_access_invitation string.""" + return "customers/{customer_id}/customerUserAccessInvitations/{invitation_id}".format( + customer_id=customer_id, + invitation_id=invitation_id, + ) + + @staticmethod + def parse_customer_user_access_invitation_path(path: str) -> Dict[str, str]: + """Parses a customer_user_access_invitation path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerUserAccessInvitations/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def custom_interest_path( + customer_id: str, + custom_interest_id: str, + ) -> str: + """Returns a fully-qualified custom_interest string.""" + return "customers/{customer_id}/customInterests/{custom_interest_id}".format( + customer_id=customer_id, + custom_interest_id=custom_interest_id, + ) + + @staticmethod + def parse_custom_interest_path(path: str) -> Dict[str, str]: + """Parses a custom_interest path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customInterests/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customizer_attribute_path( + customer_id: str, + customizer_attribute_id: str, + ) -> str: + """Returns a fully-qualified customizer_attribute string.""" + return "customers/{customer_id}/customizerAttributes/{customizer_attribute_id}".format( + customer_id=customer_id, + customizer_attribute_id=customizer_attribute_id, + ) + + @staticmethod + def parse_customizer_attribute_path(path: str) -> Dict[str, str]: + """Parses a customizer_attribute path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customizerAttributes/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def data_link_path( + customer_id: str, + product_link_id: str, + data_link_id: str, + ) -> str: + """Returns a fully-qualified data_link string.""" + return "customers/{customer_id}/dataLinks/{product_link_id}~{data_link_id}".format( + customer_id=customer_id, + product_link_id=product_link_id, + data_link_id=data_link_id, + ) + + @staticmethod + def parse_data_link_path(path: str) -> Dict[str, str]: + """Parses a data_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/dataLinks/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def detail_content_suitability_placement_view_path( + customer_id: str, + placement_fingerprint: str, + ) -> str: + """Returns a fully-qualified detail_content_suitability_placement_view string.""" + return "customers/{customer_id}/detailContentSuitabilityPlacementViews/{placement_fingerprint}".format( + customer_id=customer_id, + placement_fingerprint=placement_fingerprint, + ) + + @staticmethod + def parse_detail_content_suitability_placement_view_path( + path: str, + ) -> Dict[str, str]: + """Parses a detail_content_suitability_placement_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/detailContentSuitabilityPlacementViews/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def detailed_demographic_path( + customer_id: str, + detailed_demographic_id: str, + ) -> str: + """Returns a fully-qualified detailed_demographic string.""" + return "customers/{customer_id}/detailedDemographics/{detailed_demographic_id}".format( + customer_id=customer_id, + detailed_demographic_id=detailed_demographic_id, + ) + + @staticmethod + def parse_detailed_demographic_path(path: str) -> Dict[str, str]: + """Parses a detailed_demographic path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/detailedDemographics/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def detail_placement_view_path( + customer_id: str, + ad_group_id: str, + base64_placement: str, + ) -> str: + """Returns a fully-qualified detail_placement_view string.""" + return "customers/{customer_id}/detailPlacementViews/{ad_group_id}~{base64_placement}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + base64_placement=base64_placement, + ) + + @staticmethod + def parse_detail_placement_view_path(path: str) -> Dict[str, str]: + """Parses a detail_placement_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/detailPlacementViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def display_keyword_view_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified display_keyword_view string.""" + return "customers/{customer_id}/displayKeywordViews/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_display_keyword_view_path(path: str) -> Dict[str, str]: + """Parses a display_keyword_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/displayKeywordViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def distance_view_path( + customer_id: str, + placeholder_chain_id: str, + distance_bucket: str, + ) -> str: + """Returns a fully-qualified distance_view string.""" + return "customers/{customer_id}/distanceViews/{placeholder_chain_id}~{distance_bucket}".format( + customer_id=customer_id, + placeholder_chain_id=placeholder_chain_id, + distance_bucket=distance_bucket, + ) + + @staticmethod + def parse_distance_view_path(path: str) -> Dict[str, str]: + """Parses a distance_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/distanceViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def domain_category_path( + customer_id: str, + campaign_id: str, + base64_category: str, + language_code: str, + ) -> str: + """Returns a fully-qualified domain_category string.""" + return "customers/{customer_id}/domainCategories/{campaign_id}~{base64_category}~{language_code}".format( + customer_id=customer_id, + campaign_id=campaign_id, + base64_category=base64_category, + language_code=language_code, + ) + + @staticmethod + def parse_domain_category_path(path: str) -> Dict[str, str]: + """Parses a domain_category path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/domainCategories/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def dynamic_search_ads_search_term_view_path( + customer_id: str, + ad_group_id: str, + search_term_fingerprint: str, + headline_fingerprint: str, + landing_page_fingerprint: str, + page_url_fingerprint: str, + ) -> str: + """Returns a fully-qualified dynamic_search_ads_search_term_view string.""" + return "customers/{customer_id}/dynamicSearchAdsSearchTermViews/{ad_group_id}~{search_term_fingerprint}~{headline_fingerprint}~{landing_page_fingerprint}~{page_url_fingerprint}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + search_term_fingerprint=search_term_fingerprint, + headline_fingerprint=headline_fingerprint, + landing_page_fingerprint=landing_page_fingerprint, + page_url_fingerprint=page_url_fingerprint, + ) + + @staticmethod + def parse_dynamic_search_ads_search_term_view_path( + path: str, + ) -> Dict[str, str]: + """Parses a dynamic_search_ads_search_term_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/dynamicSearchAdsSearchTermViews/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def expanded_landing_page_view_path( + customer_id: str, + expanded_final_url_fingerprint: str, + ) -> str: + """Returns a fully-qualified expanded_landing_page_view string.""" + return "customers/{customer_id}/expandedLandingPageViews/{expanded_final_url_fingerprint}".format( + customer_id=customer_id, + expanded_final_url_fingerprint=expanded_final_url_fingerprint, + ) + + @staticmethod + def parse_expanded_landing_page_view_path(path: str) -> Dict[str, str]: + """Parses a expanded_landing_page_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/expandedLandingPageViews/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def experiment_path( + customer_id: str, + trial_id: str, + ) -> str: + """Returns a fully-qualified experiment string.""" + return "customers/{customer_id}/experiments/{trial_id}".format( + customer_id=customer_id, + trial_id=trial_id, + ) + + @staticmethod + def parse_experiment_path(path: str) -> Dict[str, str]: + """Parses a experiment path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/experiments/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def experiment_arm_path( + customer_id: str, + trial_id: str, + trial_arm_id: str, + ) -> str: + """Returns a fully-qualified experiment_arm string.""" + return "customers/{customer_id}/experimentArms/{trial_id}~{trial_arm_id}".format( + customer_id=customer_id, + trial_id=trial_id, + trial_arm_id=trial_arm_id, + ) + + @staticmethod + def parse_experiment_arm_path(path: str) -> Dict[str, str]: + """Parses a experiment_arm path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/experimentArms/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def final_url_expansion_asset_view_path( + customer_id: str, + campaign_id: str, + asset_id: str, + field_type: str, + url_fp: str, + ) -> str: + """Returns a fully-qualified final_url_expansion_asset_view string.""" + return "customers/{customer_id}/finalUrlExpansionAssetViews/{campaign_id}~{asset_id}~{field_type}~{url_fp}".format( + customer_id=customer_id, + campaign_id=campaign_id, + asset_id=asset_id, + field_type=field_type, + url_fp=url_fp, + ) + + @staticmethod + def parse_final_url_expansion_asset_view_path(path: str) -> Dict[str, str]: + """Parses a final_url_expansion_asset_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/finalUrlExpansionAssetViews/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def gender_view_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified gender_view string.""" + return "customers/{customer_id}/genderViews/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_gender_view_path(path: str) -> Dict[str, str]: + """Parses a gender_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/genderViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def geographic_view_path( + customer_id: str, + country_criterion_id: str, + location_type: str, + ) -> str: + """Returns a fully-qualified geographic_view string.""" + return "customers/{customer_id}/geographicViews/{country_criterion_id}~{location_type}".format( + customer_id=customer_id, + country_criterion_id=country_criterion_id, + location_type=location_type, + ) + + @staticmethod + def parse_geographic_view_path(path: str) -> Dict[str, str]: + """Parses a geographic_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/geographicViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def geo_target_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified geo_target_constant string.""" + return "geoTargetConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_geo_target_constant_path(path: str) -> Dict[str, str]: + """Parses a geo_target_constant path into its component segments.""" + m = re.match(r"^geoTargetConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def goal_path( + customer_id: str, + unified_goal_id: str, + ) -> str: + """Returns a fully-qualified goal string.""" + return "customers/{customer_id}/goals/{unified_goal_id}".format( + customer_id=customer_id, + unified_goal_id=unified_goal_id, + ) + + @staticmethod + def parse_goal_path(path: str) -> Dict[str, str]: + """Parses a goal path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/goals/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def group_content_suitability_placement_view_path( + customer_id: str, + placement_fingerprint: str, + ) -> str: + """Returns a fully-qualified group_content_suitability_placement_view string.""" + return "customers/{customer_id}/groupContentSuitabilityPlacementViews/{placement_fingerprint}".format( + customer_id=customer_id, + placement_fingerprint=placement_fingerprint, + ) + + @staticmethod + def parse_group_content_suitability_placement_view_path( + path: str, + ) -> Dict[str, str]: + """Parses a group_content_suitability_placement_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/groupContentSuitabilityPlacementViews/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def group_placement_view_path( + customer_id: str, + ad_group_id: str, + base64_placement: str, + ) -> str: + """Returns a fully-qualified group_placement_view string.""" + return "customers/{customer_id}/groupPlacementViews/{ad_group_id}~{base64_placement}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + base64_placement=base64_placement, + ) + + @staticmethod + def parse_group_placement_view_path(path: str) -> Dict[str, str]: + """Parses a group_placement_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/groupPlacementViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def hotel_group_view_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified hotel_group_view string.""" + return "customers/{customer_id}/hotelGroupViews/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_hotel_group_view_path(path: str) -> Dict[str, str]: + """Parses a hotel_group_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/hotelGroupViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def hotel_performance_view_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified hotel_performance_view string.""" + return "customers/{customer_id}/hotelPerformanceView".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_hotel_performance_view_path(path: str) -> Dict[str, str]: + """Parses a hotel_performance_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/hotelPerformanceView$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def hotel_reconciliation_path( + customer_id: str, + commission_id: str, + ) -> str: + """Returns a fully-qualified hotel_reconciliation string.""" + return "customers/{customer_id}/hotelReconciliations/{commission_id}".format( + customer_id=customer_id, + commission_id=commission_id, + ) + + @staticmethod + def parse_hotel_reconciliation_path(path: str) -> Dict[str, str]: + """Parses a hotel_reconciliation path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/hotelReconciliations/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def income_range_view_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified income_range_view string.""" + return "customers/{customer_id}/incomeRangeViews/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_income_range_view_path(path: str) -> Dict[str, str]: + """Parses a income_range_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/incomeRangeViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_path( + customer_id: str, + keyword_plan_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan string.""" + return "customers/{customer_id}/keywordPlans/{keyword_plan_id}".format( + customer_id=customer_id, + keyword_plan_id=keyword_plan_id, + ) + + @staticmethod + def parse_keyword_plan_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlans/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_ad_group_path( + customer_id: str, + keyword_plan_ad_group_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_ad_group string.""" + return "customers/{customer_id}/keywordPlanAdGroups/{keyword_plan_ad_group_id}".format( + customer_id=customer_id, + keyword_plan_ad_group_id=keyword_plan_ad_group_id, + ) + + @staticmethod + def parse_keyword_plan_ad_group_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanAdGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_ad_group_keyword_path( + customer_id: str, + keyword_plan_ad_group_keyword_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_ad_group_keyword string.""" + return "customers/{customer_id}/keywordPlanAdGroupKeywords/{keyword_plan_ad_group_keyword_id}".format( + customer_id=customer_id, + keyword_plan_ad_group_keyword_id=keyword_plan_ad_group_keyword_id, + ) + + @staticmethod + def parse_keyword_plan_ad_group_keyword_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_ad_group_keyword path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanAdGroupKeywords/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_campaign_path( + customer_id: str, + keyword_plan_campaign_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_campaign string.""" + return "customers/{customer_id}/keywordPlanCampaigns/{keyword_plan_campaign_id}".format( + customer_id=customer_id, + keyword_plan_campaign_id=keyword_plan_campaign_id, + ) + + @staticmethod + def parse_keyword_plan_campaign_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanCampaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_campaign_keyword_path( + customer_id: str, + keyword_plan_campaign_keyword_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_campaign_keyword string.""" + return "customers/{customer_id}/keywordPlanCampaignKeywords/{keyword_plan_campaign_keyword_id}".format( + customer_id=customer_id, + keyword_plan_campaign_keyword_id=keyword_plan_campaign_keyword_id, + ) + + @staticmethod + def parse_keyword_plan_campaign_keyword_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_campaign_keyword path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanCampaignKeywords/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_theme_constant_path( + express_category_id: str, + express_sub_category_id: str, + ) -> str: + """Returns a fully-qualified keyword_theme_constant string.""" + return "keywordThemeConstants/{express_category_id}~{express_sub_category_id}".format( + express_category_id=express_category_id, + express_sub_category_id=express_sub_category_id, + ) + + @staticmethod + def parse_keyword_theme_constant_path(path: str) -> Dict[str, str]: + """Parses a keyword_theme_constant path into its component segments.""" + m = re.match( + r"^keywordThemeConstants/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_view_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified keyword_view string.""" + return "customers/{customer_id}/keywordViews/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_keyword_view_path(path: str) -> Dict[str, str]: + """Parses a keyword_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def label_path( + customer_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified label string.""" + return "customers/{customer_id}/labels/{label_id}".format( + customer_id=customer_id, + label_id=label_id, + ) + + @staticmethod + def parse_label_path(path: str) -> Dict[str, str]: + """Parses a label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/labels/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def landing_page_view_path( + customer_id: str, + unexpanded_final_url_fingerprint: str, + ) -> str: + """Returns a fully-qualified landing_page_view string.""" + return "customers/{customer_id}/landingPageViews/{unexpanded_final_url_fingerprint}".format( + customer_id=customer_id, + unexpanded_final_url_fingerprint=unexpanded_final_url_fingerprint, + ) + + @staticmethod + def parse_landing_page_view_path(path: str) -> Dict[str, str]: + """Parses a landing_page_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/landingPageViews/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def language_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified language_constant string.""" + return "languageConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_language_constant_path(path: str) -> Dict[str, str]: + """Parses a language_constant path into its component segments.""" + m = re.match(r"^languageConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def lead_form_submission_data_path( + customer_id: str, + lead_form_user_submission_id: str, + ) -> str: + """Returns a fully-qualified lead_form_submission_data string.""" + return "customers/{customer_id}/leadFormSubmissionData/{lead_form_user_submission_id}".format( + customer_id=customer_id, + lead_form_user_submission_id=lead_form_user_submission_id, + ) + + @staticmethod + def parse_lead_form_submission_data_path(path: str) -> Dict[str, str]: + """Parses a lead_form_submission_data path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/leadFormSubmissionData/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def life_event_path( + customer_id: str, + life_event_id: str, + ) -> str: + """Returns a fully-qualified life_event string.""" + return "customers/{customer_id}/lifeEvents/{life_event_id}".format( + customer_id=customer_id, + life_event_id=life_event_id, + ) + + @staticmethod + def parse_life_event_path(path: str) -> Dict[str, str]: + """Parses a life_event path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/lifeEvents/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def local_services_employee_path( + customer_id: str, + gls_employee_id: str, + ) -> str: + """Returns a fully-qualified local_services_employee string.""" + return "customers/{customer_id}/localServicesEmployees/{gls_employee_id}".format( + customer_id=customer_id, + gls_employee_id=gls_employee_id, + ) + + @staticmethod + def parse_local_services_employee_path(path: str) -> Dict[str, str]: + """Parses a local_services_employee path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/localServicesEmployees/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def local_services_lead_path( + customer_id: str, + local_services_lead_id: str, + ) -> str: + """Returns a fully-qualified local_services_lead string.""" + return "customers/{customer_id}/localServicesLeads/{local_services_lead_id}".format( + customer_id=customer_id, + local_services_lead_id=local_services_lead_id, + ) + + @staticmethod + def parse_local_services_lead_path(path: str) -> Dict[str, str]: + """Parses a local_services_lead path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/localServicesLeads/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def local_services_lead_conversation_path( + customer_id: str, + local_services_lead_conversation_id: str, + ) -> str: + """Returns a fully-qualified local_services_lead_conversation string.""" + return "customers/{customer_id}/localServicesLeadConversations/{local_services_lead_conversation_id}".format( + customer_id=customer_id, + local_services_lead_conversation_id=local_services_lead_conversation_id, + ) + + @staticmethod + def parse_local_services_lead_conversation_path( + path: str, + ) -> Dict[str, str]: + """Parses a local_services_lead_conversation path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/localServicesLeadConversations/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def local_services_verification_artifact_path( + customer_id: str, + gls_verification_artifact_id: str, + ) -> str: + """Returns a fully-qualified local_services_verification_artifact string.""" + return "customers/{customer_id}/localServicesVerificationArtifacts/{gls_verification_artifact_id}".format( + customer_id=customer_id, + gls_verification_artifact_id=gls_verification_artifact_id, + ) + + @staticmethod + def parse_local_services_verification_artifact_path( + path: str, + ) -> Dict[str, str]: + """Parses a local_services_verification_artifact path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/localServicesVerificationArtifacts/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def location_interest_view_path( + customer_id: str, + campaign_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified location_interest_view string.""" + return "customers/{customer_id}/locationInterestViews/{campaign_id}~{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_location_interest_view_path(path: str) -> Dict[str, str]: + """Parses a location_interest_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/locationInterestViews/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def location_view_path( + customer_id: str, + campaign_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified location_view string.""" + return "customers/{customer_id}/locationViews/{campaign_id}~{criterion_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_location_view_path(path: str) -> Dict[str, str]: + """Parses a location_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/locationViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def managed_placement_view_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified managed_placement_view string.""" + return "customers/{customer_id}/managedPlacementViews/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_managed_placement_view_path(path: str) -> Dict[str, str]: + """Parses a managed_placement_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/managedPlacementViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def matched_location_interest_view_path( + customer_id: str, + country_criterion_id: str, + ) -> str: + """Returns a fully-qualified matched_location_interest_view string.""" + return "customers/{customer_id}/matchedLocationInterestViews/{country_criterion_id}".format( + customer_id=customer_id, + country_criterion_id=country_criterion_id, + ) + + @staticmethod + def parse_matched_location_interest_view_path(path: str) -> Dict[str, str]: + """Parses a matched_location_interest_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/matchedLocationInterestViews/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def media_file_path( + customer_id: str, + media_file_id: str, + ) -> str: + """Returns a fully-qualified media_file string.""" + return "customers/{customer_id}/mediaFiles/{media_file_id}".format( + customer_id=customer_id, + media_file_id=media_file_id, + ) + + @staticmethod + def parse_media_file_path(path: str) -> Dict[str, str]: + """Parses a media_file path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/mediaFiles/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def mobile_app_category_constant_path( + mobile_app_category_id: str, + ) -> str: + """Returns a fully-qualified mobile_app_category_constant string.""" + return "mobileAppCategoryConstants/{mobile_app_category_id}".format( + mobile_app_category_id=mobile_app_category_id, + ) + + @staticmethod + def parse_mobile_app_category_constant_path(path: str) -> Dict[str, str]: + """Parses a mobile_app_category_constant path into its component segments.""" + m = re.match( + r"^mobileAppCategoryConstants/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def mobile_device_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified mobile_device_constant string.""" + return "mobileDeviceConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_mobile_device_constant_path(path: str) -> Dict[str, str]: + """Parses a mobile_device_constant path into its component segments.""" + m = re.match(r"^mobileDeviceConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def offline_conversion_upload_client_summary_path( + customer_id: str, + client: str, + ) -> str: + """Returns a fully-qualified offline_conversion_upload_client_summary string.""" + return "customers/{customer_id}/offlineConversionUploadClientSummaries/{client}".format( + customer_id=customer_id, + client=client, + ) + + @staticmethod + def parse_offline_conversion_upload_client_summary_path( + path: str, + ) -> Dict[str, str]: + """Parses a offline_conversion_upload_client_summary path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/offlineConversionUploadClientSummaries/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def offline_conversion_upload_conversion_action_summary_path( + customer_id: str, + conversion_type_id: str, + client: str, + ) -> str: + """Returns a fully-qualified offline_conversion_upload_conversion_action_summary string.""" + return "customers/{customer_id}/offlineConversionUploadConversionActionSummaries/{conversion_type_id}~{client}".format( + customer_id=customer_id, + conversion_type_id=conversion_type_id, + client=client, + ) + + @staticmethod + def parse_offline_conversion_upload_conversion_action_summary_path( + path: str, + ) -> Dict[str, str]: + """Parses a offline_conversion_upload_conversion_action_summary path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/offlineConversionUploadConversionActionSummaries/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def offline_user_data_job_path( + customer_id: str, + offline_user_data_update_id: str, + ) -> str: + """Returns a fully-qualified offline_user_data_job string.""" + return "customers/{customer_id}/offlineUserDataJobs/{offline_user_data_update_id}".format( + customer_id=customer_id, + offline_user_data_update_id=offline_user_data_update_id, + ) + + @staticmethod + def parse_offline_user_data_job_path(path: str) -> Dict[str, str]: + """Parses a offline_user_data_job path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/offlineUserDataJobs/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def operating_system_version_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified operating_system_version_constant string.""" + return "operatingSystemVersionConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_operating_system_version_constant_path( + path: str, + ) -> Dict[str, str]: + """Parses a operating_system_version_constant path into its component segments.""" + m = re.match( + r"^operatingSystemVersionConstants/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def paid_organic_search_term_view_path( + customer_id: str, + campaign_id: str, + ad_group_id: str, + base64_search_term: str, + ) -> str: + """Returns a fully-qualified paid_organic_search_term_view string.""" + return "customers/{customer_id}/paidOrganicSearchTermViews/{campaign_id}~{ad_group_id}~{base64_search_term}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ad_group_id=ad_group_id, + base64_search_term=base64_search_term, + ) + + @staticmethod + def parse_paid_organic_search_term_view_path(path: str) -> Dict[str, str]: + """Parses a paid_organic_search_term_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/paidOrganicSearchTermViews/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def parental_status_view_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified parental_status_view string.""" + return "customers/{customer_id}/parentalStatusViews/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_parental_status_view_path(path: str) -> Dict[str, str]: + """Parses a parental_status_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/parentalStatusViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def payments_account_path( + customer_id: str, + payments_account_id: str, + ) -> str: + """Returns a fully-qualified payments_account string.""" + return "customers/{customer_id}/paymentsAccounts/{payments_account_id}".format( + customer_id=customer_id, + payments_account_id=payments_account_id, + ) + + @staticmethod + def parse_payments_account_path(path: str) -> Dict[str, str]: + """Parses a payments_account path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/paymentsAccounts/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def performance_max_placement_view_path( + customer_id: str, + base_64_placement: str, + ) -> str: + """Returns a fully-qualified performance_max_placement_view string.""" + return "customers/{customer_id}/performanceMaxPlacementViews/{base_64_placement}".format( + customer_id=customer_id, + base_64_placement=base_64_placement, + ) + + @staticmethod + def parse_performance_max_placement_view_path(path: str) -> Dict[str, str]: + """Parses a performance_max_placement_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/performanceMaxPlacementViews/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def per_store_view_path( + customer_id: str, + place_id: str, + ) -> str: + """Returns a fully-qualified per_store_view string.""" + return "customers/{customer_id}/perStoreViews/{place_id}".format( + customer_id=customer_id, + place_id=place_id, + ) + + @staticmethod + def parse_per_store_view_path(path: str) -> Dict[str, str]: + """Parses a per_store_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/perStoreViews/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def product_category_constant_path( + level: str, + category_id: str, + ) -> str: + """Returns a fully-qualified product_category_constant string.""" + return "productCategoryConstants/{level}~{category_id}".format( + level=level, + category_id=category_id, + ) + + @staticmethod + def parse_product_category_constant_path(path: str) -> Dict[str, str]: + """Parses a product_category_constant path into its component segments.""" + m = re.match( + r"^productCategoryConstants/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def product_group_view_path( + customer_id: str, + adgroup_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified product_group_view string.""" + return "customers/{customer_id}/productGroupViews/{adgroup_id}~{criterion_id}".format( + customer_id=customer_id, + adgroup_id=adgroup_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_product_group_view_path(path: str) -> Dict[str, str]: + """Parses a product_group_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/productGroupViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def product_link_path( + customer_id: str, + product_link_id: str, + ) -> str: + """Returns a fully-qualified product_link string.""" + return "customers/{customer_id}/productLinks/{product_link_id}".format( + customer_id=customer_id, + product_link_id=product_link_id, + ) + + @staticmethod + def parse_product_link_path(path: str) -> Dict[str, str]: + """Parses a product_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/productLinks/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def product_link_invitation_path( + customer_id: str, + customer_invitation_id: str, + ) -> str: + """Returns a fully-qualified product_link_invitation string.""" + return "customers/{customer_id}/productLinkInvitations/{customer_invitation_id}".format( + customer_id=customer_id, + customer_invitation_id=customer_invitation_id, + ) + + @staticmethod + def parse_product_link_invitation_path(path: str) -> Dict[str, str]: + """Parses a product_link_invitation path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/productLinkInvitations/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def qualifying_question_path( + qualifying_question_id: str, + ) -> str: + """Returns a fully-qualified qualifying_question string.""" + return "qualifyingQuestions/{qualifying_question_id}".format( + qualifying_question_id=qualifying_question_id, + ) + + @staticmethod + def parse_qualifying_question_path(path: str) -> Dict[str, str]: + """Parses a qualifying_question path into its component segments.""" + m = re.match( + r"^qualifyingQuestions/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def recommendation_path( + customer_id: str, + recommendation_id: str, + ) -> str: + """Returns a fully-qualified recommendation string.""" + return "customers/{customer_id}/recommendations/{recommendation_id}".format( + customer_id=customer_id, + recommendation_id=recommendation_id, + ) + + @staticmethod + def parse_recommendation_path(path: str) -> Dict[str, str]: + """Parses a recommendation path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/recommendations/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def recommendation_subscription_path( + customer_id: str, + recommendation_type: str, + ) -> str: + """Returns a fully-qualified recommendation_subscription string.""" + return "customers/{customer_id}/recommendationSubscriptions/{recommendation_type}".format( + customer_id=customer_id, + recommendation_type=recommendation_type, + ) + + @staticmethod + def parse_recommendation_subscription_path(path: str) -> Dict[str, str]: + """Parses a recommendation_subscription path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/recommendationSubscriptions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def remarketing_action_path( + customer_id: str, + remarketing_action_id: str, + ) -> str: + """Returns a fully-qualified remarketing_action string.""" + return "customers/{customer_id}/remarketingActions/{remarketing_action_id}".format( + customer_id=customer_id, + remarketing_action_id=remarketing_action_id, + ) + + @staticmethod + def parse_remarketing_action_path(path: str) -> Dict[str, str]: + """Parses a remarketing_action path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/remarketingActions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def search_term_view_path( + customer_id: str, + campaign_id: str, + ad_group_id: str, + query: str, + ) -> str: + """Returns a fully-qualified search_term_view string.""" + return "customers/{customer_id}/searchTermViews/{campaign_id}~{ad_group_id}~{query}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ad_group_id=ad_group_id, + query=query, + ) + + @staticmethod + def parse_search_term_view_path(path: str) -> Dict[str, str]: + """Parses a search_term_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/searchTermViews/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def shared_criterion_path( + customer_id: str, + shared_set_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified shared_criterion string.""" + return "customers/{customer_id}/sharedCriteria/{shared_set_id}~{criterion_id}".format( + customer_id=customer_id, + shared_set_id=shared_set_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_shared_criterion_path(path: str) -> Dict[str, str]: + """Parses a shared_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/sharedCriteria/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def shared_set_path( + customer_id: str, + shared_set_id: str, + ) -> str: + """Returns a fully-qualified shared_set string.""" + return "customers/{customer_id}/sharedSets/{shared_set_id}".format( + customer_id=customer_id, + shared_set_id=shared_set_id, + ) + + @staticmethod + def parse_shared_set_path(path: str) -> Dict[str, str]: + """Parses a shared_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/sharedSets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def shopping_performance_view_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified shopping_performance_view string.""" + return "customers/{customer_id}/shoppingPerformanceView".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_shopping_performance_view_path(path: str) -> Dict[str, str]: + """Parses a shopping_performance_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/shoppingPerformanceView$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def shopping_product_path( + customer_id: str, + merchant_center_id: str, + channel: str, + language_code: str, + feed_label: str, + item_id: str, + ) -> str: + """Returns a fully-qualified shopping_product string.""" + return "customers/{customer_id}/shoppingProducts/{merchant_center_id}~{channel}~{language_code}~{feed_label}~{item_id}".format( + customer_id=customer_id, + merchant_center_id=merchant_center_id, + channel=channel, + language_code=language_code, + feed_label=feed_label, + item_id=item_id, + ) + + @staticmethod + def parse_shopping_product_path(path: str) -> Dict[str, str]: + """Parses a shopping_product path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/shoppingProducts/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def smart_campaign_search_term_view_path( + customer_id: str, + campaign_id: str, + query: str, + ) -> str: + """Returns a fully-qualified smart_campaign_search_term_view string.""" + return "customers/{customer_id}/smartCampaignSearchTermViews/{campaign_id}~{query}".format( + customer_id=customer_id, + campaign_id=campaign_id, + query=query, + ) + + @staticmethod + def parse_smart_campaign_search_term_view_path(path: str) -> Dict[str, str]: + """Parses a smart_campaign_search_term_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/smartCampaignSearchTermViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def smart_campaign_setting_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified smart_campaign_setting string.""" + return "customers/{customer_id}/smartCampaignSettings/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_smart_campaign_setting_path(path: str) -> Dict[str, str]: + """Parses a smart_campaign_setting path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/smartCampaignSettings/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def targeting_expansion_view_path( + customer_id: str, + campaign_id: str, + targeting_expansion_type: str, + ) -> str: + """Returns a fully-qualified targeting_expansion_view string.""" + return "customers/{customer_id}/targetingExpansionViews/{campaign_id}~{targeting_expansion_type}".format( + customer_id=customer_id, + campaign_id=campaign_id, + targeting_expansion_type=targeting_expansion_type, + ) + + @staticmethod + def parse_targeting_expansion_view_path(path: str) -> Dict[str, str]: + """Parses a targeting_expansion_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/targetingExpansionViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def third_party_app_analytics_link_path( + customer_id: str, + customer_link_id: str, + ) -> str: + """Returns a fully-qualified third_party_app_analytics_link string.""" + return "customers/{customer_id}/thirdPartyAppAnalyticsLinks/{customer_link_id}".format( + customer_id=customer_id, + customer_link_id=customer_link_id, + ) + + @staticmethod + def parse_third_party_app_analytics_link_path(path: str) -> Dict[str, str]: + """Parses a third_party_app_analytics_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/thirdPartyAppAnalyticsLinks/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def topic_constant_path( + topic_id: str, + ) -> str: + """Returns a fully-qualified topic_constant string.""" + return "topicConstants/{topic_id}".format( + topic_id=topic_id, + ) + + @staticmethod + def parse_topic_constant_path(path: str) -> Dict[str, str]: + """Parses a topic_constant path into its component segments.""" + m = re.match(r"^topicConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def topic_view_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified topic_view string.""" + return "customers/{customer_id}/topicViews/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_topic_view_path(path: str) -> Dict[str, str]: + """Parses a topic_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/topicViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def travel_activity_group_view_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified travel_activity_group_view string.""" + return "customers/{customer_id}/travelActivityGroupViews/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_travel_activity_group_view_path(path: str) -> Dict[str, str]: + """Parses a travel_activity_group_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/travelActivityGroupViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def travel_activity_performance_view_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified travel_activity_performance_view string.""" + return "customers/{customer_id}/travelActivityPerformanceViews".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_travel_activity_performance_view_path( + path: str, + ) -> Dict[str, str]: + """Parses a travel_activity_performance_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/travelActivityPerformanceViews$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def user_interest_path( + customer_id: str, + user_interest_id: str, + ) -> str: + """Returns a fully-qualified user_interest string.""" + return ( + "customers/{customer_id}/userInterests/{user_interest_id}".format( + customer_id=customer_id, + user_interest_id=user_interest_id, + ) + ) + + @staticmethod + def parse_user_interest_path(path: str) -> Dict[str, str]: + """Parses a user_interest path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/userInterests/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def user_list_path( + customer_id: str, + user_list_id: str, + ) -> str: + """Returns a fully-qualified user_list string.""" + return "customers/{customer_id}/userLists/{user_list_id}".format( + customer_id=customer_id, + user_list_id=user_list_id, + ) + + @staticmethod + def parse_user_list_path(path: str) -> Dict[str, str]: + """Parses a user_list path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/userLists/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def user_list_customer_type_path( + customer_id: str, + user_list_id: str, + semantic_label: str, + ) -> str: + """Returns a fully-qualified user_list_customer_type string.""" + return "customers/{customer_id}/userListCustomerTypes/{user_list_id}~{semantic_label}".format( + customer_id=customer_id, + user_list_id=user_list_id, + semantic_label=semantic_label, + ) + + @staticmethod + def parse_user_list_customer_type_path(path: str) -> Dict[str, str]: + """Parses a user_list_customer_type path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/userListCustomerTypes/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def user_location_view_path( + customer_id: str, + country_criterion_id: str, + is_targeting_location: str, + ) -> str: + """Returns a fully-qualified user_location_view string.""" + return "customers/{customer_id}/userLocationViews/{country_criterion_id}~{is_targeting_location}".format( + customer_id=customer_id, + country_criterion_id=country_criterion_id, + is_targeting_location=is_targeting_location, + ) + + @staticmethod + def parse_user_location_view_path(path: str) -> Dict[str, str]: + """Parses a user_location_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/userLocationViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def video_path( + customer_id: str, + video_id: str, + ) -> str: + """Returns a fully-qualified video string.""" + return "customers/{customer_id}/videos/{video_id}".format( + customer_id=customer_id, + video_id=video_id, + ) + + @staticmethod + def parse_video_path(path: str) -> Dict[str, str]: + """Parses a video path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/videos/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def video_enhancement_path( + customer_id: str, + video_enhancement: str, + ) -> str: + """Returns a fully-qualified video_enhancement string.""" + return "customers/{customer_id}/videoEnhancements/{video_enhancement}".format( + customer_id=customer_id, + video_enhancement=video_enhancement, + ) + + @staticmethod + def parse_video_enhancement_path(path: str) -> Dict[str, str]: + """Parses a video_enhancement path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/videoEnhancements/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def webpage_view_path( + customer_id: str, + ad_group_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified webpage_view string.""" + return "customers/{customer_id}/webpageViews/{ad_group_id}~{criterion_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_webpage_view_path(path: str) -> Dict[str, str]: + """Parses a webpage_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/webpageViews/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def you_tube_video_upload_path( + customer_id: str, + video_upload_id: str, + ) -> str: + """Returns a fully-qualified you_tube_video_upload string.""" + return "customers/{customer_id}/youTubeVideoUploads/{video_upload_id}".format( + customer_id=customer_id, + video_upload_id=video_upload_id, + ) + + @staticmethod + def parse_you_tube_video_upload_path(path: str) -> Dict[str, str]: + """Parses a you_tube_video_upload path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/youTubeVideoUploads/(?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 = GoogleAdsServiceClient._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 = GoogleAdsServiceClient._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 + ): + """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 = GoogleAdsServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = GoogleAdsServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + GoogleAdsServiceClient._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 = GoogleAdsServiceClient._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): + """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, + GoogleAdsServiceTransport, + Callable[..., GoogleAdsServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the google ads 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,GoogleAdsServiceTransport,Callable[..., GoogleAdsServiceTransport]]]): + 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 GoogleAdsServiceTransport 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, + ) = GoogleAdsServiceClient._read_environment_variables() + self._client_cert_source = ( + GoogleAdsServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = GoogleAdsServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, GoogleAdsServiceTransport) + if transport_provided: + # transport is a GoogleAdsServiceTransport 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(GoogleAdsServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or GoogleAdsServiceClient._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[GoogleAdsServiceTransport], + Callable[..., GoogleAdsServiceTransport], + ] = ( + GoogleAdsServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., GoogleAdsServiceTransport], 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.ads.googleads.v24.services.GoogleAdsServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.GoogleAdsService", + "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.ads.googleads.v24.services.GoogleAdsService", + "credentialsType": None, + } + ), + ) + + def search( + self, + request: Optional[ + Union[google_ads_service.SearchGoogleAdsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + query: 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.SearchPager: + r"""Returns all rows that match the search query. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ChangeEventError <>`__ + `ChangeStatusError <>`__ `ClickViewError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QueryError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.SearchGoogleAdsRequest, dict]): + The request object. Request message for + [GoogleAdsService.Search][google.ads.googleads.v24.services.GoogleAdsService.Search]. + customer_id (str): + Required. The ID of the customer + being queried. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + query (str): + Required. The query string. + This corresponds to the ``query`` 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.ads.googleads.v24.services.services.google_ads_service.pagers.SearchPager: + Response message for + [GoogleAdsService.Search][google.ads.googleads.v24.services.GoogleAdsService.Search]. + + 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 = [customer_id, query] + 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, google_ads_service.SearchGoogleAdsRequest): + request = google_ads_service.SearchGoogleAdsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if query is not None: + request.query = query + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.search] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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.SearchPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def search_stream( + self, + request: Optional[ + Union[google_ads_service.SearchGoogleAdsStreamRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + query: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> Iterable[google_ads_service.SearchGoogleAdsStreamResponse]: + r"""Returns all rows that match the search stream query. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ChangeEventError <>`__ + `ChangeStatusError <>`__ `ClickViewError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QueryError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.SearchGoogleAdsStreamRequest, dict]): + The request object. Request message for + [GoogleAdsService.SearchStream][google.ads.googleads.v24.services.GoogleAdsService.SearchStream]. + customer_id (str): + Required. The ID of the customer + being queried. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + query (str): + Required. The query string. + This corresponds to the ``query`` 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: + Iterable[google.ads.googleads.v24.services.types.SearchGoogleAdsStreamResponse]: + Response message for + [GoogleAdsService.SearchStream][google.ads.googleads.v24.services.GoogleAdsService.SearchStream]. + + """ + # 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 = [customer_id, query] + 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, google_ads_service.SearchGoogleAdsStreamRequest + ): + request = google_ads_service.SearchGoogleAdsStreamRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if query is not None: + request.query = query + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.search_stream] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 mutate( + self, + request: Optional[ + Union[google_ads_service.MutateGoogleAdsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + mutate_operations: Optional[ + MutableSequence[google_ads_service.MutateOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> google_ads_service.MutateGoogleAdsResponse: + r"""Executes mutate and actions operations. Mutate operations + create, update, or remove resources. Actions perform custom + operations. This method supports atomic transactions with + multiple types of resources and actions. For example, you can + atomically create a campaign and a campaign budget, or perform + up to thousands of mutates atomically. + + This method is essentially a wrapper around a series of mutate + methods. The only features it offers over calling those methods + directly are: + + - Atomic transactions + - Temp resource names (described below) + - Somewhat reduced latency over making a series of mutate calls + + Note: Only resources that support atomic transactions are + included, so this method can't replace all calls to individual + services. + + Atomic Transaction Benefits + --------------------------- + + Atomicity makes error handling much easier. If you're making a + series of changes and one fails, it can leave your account in an + inconsistent state. With atomicity, you either reach the chosen + state directly, or the request fails and you can retry. + + Temp Resource Names + ------------------- + + Temp resource names are a special type of resource name used to + create a resource and reference that resource in the same + request. For example, if a campaign budget is created with + ``resource_name`` equal to ``customers/123/campaignBudgets/-1``, + that resource name can be reused in the ``Campaign.budget`` + field in the same request. That way, the two resources are + created and linked atomically. + + To create a temp resource name, put a negative number in the + part of the name that the server would normally allocate. + + Note: + + - Resources must be created with a temp name before the name can + be reused. For example, the previous CampaignBudget+Campaign + example would fail if the mutate order was reversed. + - Temp names are not remembered across requests. + - There's no limit to the number of temp names in a request. + - Each temp name must use a unique negative number, even if the + resource types differ. + + Latency + ------- + + It's important to group mutates by resource type or the request + may time out and fail. Latency is roughly equal to a series of + calls to individual mutate methods, where each change in + resource type is a new call. For example, mutating 10 campaigns + then 10 ad groups is like 2 calls, while mutating 1 campaign, 1 + ad group, 1 campaign, 1 ad group is like 4 calls. + + List of thrown errors: `AdCustomizerError <>`__ `AdError <>`__ + `AdGroupAdError <>`__ `AdGroupCriterionError <>`__ + `AdGroupError <>`__ `AssetError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ `BiddingError <>`__ + `CampaignBudgetError <>`__ `CampaignCriterionError <>`__ + `CampaignError <>`__ `CampaignExperimentError <>`__ + `CampaignSharedSetError <>`__ `CollectionSizeError <>`__ + `ContextError <>`__ `ConversionActionError <>`__ + `CriterionError <>`__ `CustomerFeedError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DateRangeError <>`__ + `DistinctError <>`__ `ExtensionFeedItemError <>`__ + `ExtensionSettingError <>`__ `FeedAttributeReferenceError <>`__ + `FeedError <>`__ `FeedItemError <>`__ `FeedItemSetError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `ImageError <>`__ + `InternalError <>`__ `KeywordPlanAdGroupKeywordError <>`__ + `KeywordPlanCampaignError <>`__ `KeywordPlanError <>`__ + `LabelError <>`__ `ListOperationError <>`__ + `MediaUploadError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `PolicyFindingError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SettingError <>`__ `SharedSetError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ `UserListError <>`__ + `YoutubeVideoRegistrationError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateGoogleAdsRequest, dict]): + The request object. Request message for + [GoogleAdsService.Mutate][google.ads.googleads.v24.services.GoogleAdsService.Mutate]. + customer_id (str): + Required. The ID of the customer + whose resources are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + mutate_operations (MutableSequence[google.ads.googleads.v24.services.types.MutateOperation]): + Required. The list of operations to + perform on individual resources. + + This corresponds to the ``mutate_operations`` 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.ads.googleads.v24.services.types.MutateGoogleAdsResponse: + Response message for + [GoogleAdsService.Mutate][google.ads.googleads.v24.services.GoogleAdsService.Mutate]. + + """ + # 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 = [customer_id, mutate_operations] + 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, google_ads_service.MutateGoogleAdsRequest): + request = google_ads_service.MutateGoogleAdsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if mutate_operations is not None: + request.mutate_operations = mutate_operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.mutate] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "GoogleAdsServiceClient": + 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() + + +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__ = ("GoogleAdsServiceClient",) diff --git a/google/ads/googleads/v24/services/services/google_ads_service/pagers.py b/google/ads/googleads/v24/services/services/google_ads_service/pagers.py new file mode 100644 index 000000000..fbc328825 --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_service/pagers.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import retry_async as retries_async +from typing import ( + Any, + AsyncIterator, + Awaitable, + Callable, + Sequence, + Tuple, + Iterator, + Union, +) + +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.ads.googleads.v24.services.types import google_ads_service + + +class SearchPager: + """A pager for iterating through ``search`` requests. + + This class thinly wraps an initial + :class:`google.ads.googleads.v24.services.types.SearchGoogleAdsResponse` object, and + provides an ``__iter__`` method to iterate through its + ``results`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``Search`` requests and continue to iterate + through the ``results`` field on the + corresponding responses. + + All the usual :class:`google.ads.googleads.v24.services.types.SearchGoogleAdsResponse` + 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[..., google_ads_service.SearchGoogleAdsResponse], + request: google_ads_service.SearchGoogleAdsRequest, + response: google_ads_service.SearchGoogleAdsResponse, + *, + 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.ads.googleads.v24.services.types.SearchGoogleAdsRequest): + The initial request object. + response (google.ads.googleads.v24.services.types.SearchGoogleAdsResponse): + 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 = google_ads_service.SearchGoogleAdsRequest(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[google_ads_service.SearchGoogleAdsResponse]: + 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[google_ads_service.GoogleAdsRow]: + for page in self.pages: + yield from page.results + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class SearchAsyncPager: + """A pager for iterating through ``search`` requests. + + This class thinly wraps an initial + :class:`google.ads.googleads.v24.services.types.SearchGoogleAdsResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``results`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``Search`` requests and continue to iterate + through the ``results`` field on the + corresponding responses. + + All the usual :class:`google.ads.googleads.v24.services.types.SearchGoogleAdsResponse` + 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[google_ads_service.SearchGoogleAdsResponse] + ], + request: google_ads_service.SearchGoogleAdsRequest, + response: google_ads_service.SearchGoogleAdsResponse, + *, + 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.ads.googleads.v24.services.types.SearchGoogleAdsRequest): + The initial request object. + response (google.ads.googleads.v24.services.types.SearchGoogleAdsResponse): + 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 = google_ads_service.SearchGoogleAdsRequest(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[google_ads_service.SearchGoogleAdsResponse]: + 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[google_ads_service.GoogleAdsRow]: + async def async_generator(): + async for page in self.pages: + for response in page.results: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/google/ads/googleads/v24/services/services/google_ads_service/transports/README.rst b/google/ads/googleads/v24/services/services/google_ads_service/transports/README.rst new file mode 100644 index 000000000..5545013dc --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`GoogleAdsServiceTransport` is the ABC for all transports. +- public child `GoogleAdsServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `GoogleAdsServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseGoogleAdsServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `GoogleAdsServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/google_ads_service/transports/__init__.py b/google/ads/googleads/v24/services/services/google_ads_service/transports/__init__.py new file mode 100644 index 000000000..f67200b50 --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import GoogleAdsServiceTransport +from .grpc import GoogleAdsServiceGrpcTransport +from .grpc_asyncio import GoogleAdsServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[GoogleAdsServiceTransport]] +_transport_registry["grpc"] = GoogleAdsServiceGrpcTransport +_transport_registry["grpc_asyncio"] = GoogleAdsServiceGrpcAsyncIOTransport + +__all__ = ( + "GoogleAdsServiceTransport", + "GoogleAdsServiceGrpcTransport", + "GoogleAdsServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/google_ads_service/transports/base.py b/google/ads/googleads/v24/services/services/google_ads_service/transports/base.py new file mode 100644 index 000000000..2d0e9d9de --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_service/transports/base.py @@ -0,0 +1,207 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import google_ads_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 GoogleAdsServiceTransport(abc.ABC): + """Abstract transport class for GoogleAdsService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.search: gapic_v1.method.wrap_method( + self.search, + default_timeout=None, + client_info=client_info, + ), + self.search_stream: gapic_v1.method.wrap_method( + self.search_stream, + default_timeout=None, + client_info=client_info, + ), + self.mutate: gapic_v1.method.wrap_method( + self.mutate, + 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 search( + self, + ) -> Callable[ + [google_ads_service.SearchGoogleAdsRequest], + Union[ + google_ads_service.SearchGoogleAdsResponse, + Awaitable[google_ads_service.SearchGoogleAdsResponse], + ], + ]: + raise NotImplementedError() + + @property + def search_stream( + self, + ) -> Callable[ + [google_ads_service.SearchGoogleAdsStreamRequest], + Union[ + google_ads_service.SearchGoogleAdsStreamResponse, + Awaitable[google_ads_service.SearchGoogleAdsStreamResponse], + ], + ]: + raise NotImplementedError() + + @property + def mutate( + self, + ) -> Callable[ + [google_ads_service.MutateGoogleAdsRequest], + Union[ + google_ads_service.MutateGoogleAdsResponse, + Awaitable[google_ads_service.MutateGoogleAdsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("GoogleAdsServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/google_ads_service/transports/grpc.py b/google/ads/googleads/v24/services/services/google_ads_service/transports/grpc.py new file mode 100644 index 000000000..7da837eff --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_service/transports/grpc.py @@ -0,0 +1,538 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import google_ads_service +from .base import GoogleAdsServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.GoogleAdsService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.GoogleAdsService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class GoogleAdsServiceGrpcTransport(GoogleAdsServiceTransport): + """gRPC backend transport for GoogleAdsService. + + Service to fetch data and metrics across resources. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 search( + self, + ) -> Callable[ + [google_ads_service.SearchGoogleAdsRequest], + google_ads_service.SearchGoogleAdsResponse, + ]: + r"""Return a callable for the search method over gRPC. + + Returns all rows that match the search query. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ChangeEventError <>`__ + `ChangeStatusError <>`__ `ClickViewError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QueryError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.SearchGoogleAdsRequest], + ~.SearchGoogleAdsResponse]: + 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 "search" not in self._stubs: + self._stubs["search"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.GoogleAdsService/Search", + request_serializer=google_ads_service.SearchGoogleAdsRequest.serialize, + response_deserializer=google_ads_service.SearchGoogleAdsResponse.deserialize, + ) + return self._stubs["search"] + + @property + def search_stream( + self, + ) -> Callable[ + [google_ads_service.SearchGoogleAdsStreamRequest], + google_ads_service.SearchGoogleAdsStreamResponse, + ]: + r"""Return a callable for the search stream method over gRPC. + + Returns all rows that match the search stream query. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ChangeEventError <>`__ + `ChangeStatusError <>`__ `ClickViewError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QueryError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.SearchGoogleAdsStreamRequest], + ~.SearchGoogleAdsStreamResponse]: + 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 "search_stream" not in self._stubs: + self._stubs["search_stream"] = self._logged_channel.unary_stream( + "/google.ads.googleads.v24.services.GoogleAdsService/SearchStream", + request_serializer=google_ads_service.SearchGoogleAdsStreamRequest.serialize, + response_deserializer=google_ads_service.SearchGoogleAdsStreamResponse.deserialize, + ) + return self._stubs["search_stream"] + + @property + def mutate( + self, + ) -> Callable[ + [google_ads_service.MutateGoogleAdsRequest], + google_ads_service.MutateGoogleAdsResponse, + ]: + r"""Return a callable for the mutate method over gRPC. + + Executes mutate and actions operations. Mutate operations + create, update, or remove resources. Actions perform custom + operations. This method supports atomic transactions with + multiple types of resources and actions. For example, you can + atomically create a campaign and a campaign budget, or perform + up to thousands of mutates atomically. + + This method is essentially a wrapper around a series of mutate + methods. The only features it offers over calling those methods + directly are: + + - Atomic transactions + - Temp resource names (described below) + - Somewhat reduced latency over making a series of mutate calls + + Note: Only resources that support atomic transactions are + included, so this method can't replace all calls to individual + services. + + Atomic Transaction Benefits + --------------------------- + + Atomicity makes error handling much easier. If you're making a + series of changes and one fails, it can leave your account in an + inconsistent state. With atomicity, you either reach the chosen + state directly, or the request fails and you can retry. + + Temp Resource Names + ------------------- + + Temp resource names are a special type of resource name used to + create a resource and reference that resource in the same + request. For example, if a campaign budget is created with + ``resource_name`` equal to ``customers/123/campaignBudgets/-1``, + that resource name can be reused in the ``Campaign.budget`` + field in the same request. That way, the two resources are + created and linked atomically. + + To create a temp resource name, put a negative number in the + part of the name that the server would normally allocate. + + Note: + + - Resources must be created with a temp name before the name can + be reused. For example, the previous CampaignBudget+Campaign + example would fail if the mutate order was reversed. + - Temp names are not remembered across requests. + - There's no limit to the number of temp names in a request. + - Each temp name must use a unique negative number, even if the + resource types differ. + + Latency + ------- + + It's important to group mutates by resource type or the request + may time out and fail. Latency is roughly equal to a series of + calls to individual mutate methods, where each change in + resource type is a new call. For example, mutating 10 campaigns + then 10 ad groups is like 2 calls, while mutating 1 campaign, 1 + ad group, 1 campaign, 1 ad group is like 4 calls. + + List of thrown errors: `AdCustomizerError <>`__ `AdError <>`__ + `AdGroupAdError <>`__ `AdGroupCriterionError <>`__ + `AdGroupError <>`__ `AssetError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ `BiddingError <>`__ + `CampaignBudgetError <>`__ `CampaignCriterionError <>`__ + `CampaignError <>`__ `CampaignExperimentError <>`__ + `CampaignSharedSetError <>`__ `CollectionSizeError <>`__ + `ContextError <>`__ `ConversionActionError <>`__ + `CriterionError <>`__ `CustomerFeedError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DateRangeError <>`__ + `DistinctError <>`__ `ExtensionFeedItemError <>`__ + `ExtensionSettingError <>`__ `FeedAttributeReferenceError <>`__ + `FeedError <>`__ `FeedItemError <>`__ `FeedItemSetError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `ImageError <>`__ + `InternalError <>`__ `KeywordPlanAdGroupKeywordError <>`__ + `KeywordPlanCampaignError <>`__ `KeywordPlanError <>`__ + `LabelError <>`__ `ListOperationError <>`__ + `MediaUploadError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `PolicyFindingError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SettingError <>`__ `SharedSetError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ `UserListError <>`__ + `YoutubeVideoRegistrationError <>`__ + + Returns: + Callable[[~.MutateGoogleAdsRequest], + ~.MutateGoogleAdsResponse]: + 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 "mutate" not in self._stubs: + self._stubs["mutate"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.GoogleAdsService/Mutate", + request_serializer=google_ads_service.MutateGoogleAdsRequest.serialize, + response_deserializer=google_ads_service.MutateGoogleAdsResponse.deserialize, + ) + return self._stubs["mutate"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("GoogleAdsServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/google_ads_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/google_ads_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..56c9b7631 --- /dev/null +++ b/google/ads/googleads/v24/services/services/google_ads_service/transports/grpc_asyncio.py @@ -0,0 +1,569 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import google_ads_service +from .base import GoogleAdsServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.GoogleAdsService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.GoogleAdsService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class GoogleAdsServiceGrpcAsyncIOTransport(GoogleAdsServiceTransport): + """gRPC AsyncIO backend transport for GoogleAdsService. + + Service to fetch data and metrics across resources. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 search( + self, + ) -> Callable[ + [google_ads_service.SearchGoogleAdsRequest], + Awaitable[google_ads_service.SearchGoogleAdsResponse], + ]: + r"""Return a callable for the search method over gRPC. + + Returns all rows that match the search query. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ChangeEventError <>`__ + `ChangeStatusError <>`__ `ClickViewError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QueryError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.SearchGoogleAdsRequest], + Awaitable[~.SearchGoogleAdsResponse]]: + 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 "search" not in self._stubs: + self._stubs["search"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.GoogleAdsService/Search", + request_serializer=google_ads_service.SearchGoogleAdsRequest.serialize, + response_deserializer=google_ads_service.SearchGoogleAdsResponse.deserialize, + ) + return self._stubs["search"] + + @property + def search_stream( + self, + ) -> Callable[ + [google_ads_service.SearchGoogleAdsStreamRequest], + Awaitable[google_ads_service.SearchGoogleAdsStreamResponse], + ]: + r"""Return a callable for the search stream method over gRPC. + + Returns all rows that match the search stream query. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ChangeEventError <>`__ + `ChangeStatusError <>`__ `ClickViewError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QueryError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.SearchGoogleAdsStreamRequest], + Awaitable[~.SearchGoogleAdsStreamResponse]]: + 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 "search_stream" not in self._stubs: + self._stubs["search_stream"] = self._logged_channel.unary_stream( + "/google.ads.googleads.v24.services.GoogleAdsService/SearchStream", + request_serializer=google_ads_service.SearchGoogleAdsStreamRequest.serialize, + response_deserializer=google_ads_service.SearchGoogleAdsStreamResponse.deserialize, + ) + return self._stubs["search_stream"] + + @property + def mutate( + self, + ) -> Callable[ + [google_ads_service.MutateGoogleAdsRequest], + Awaitable[google_ads_service.MutateGoogleAdsResponse], + ]: + r"""Return a callable for the mutate method over gRPC. + + Executes mutate and actions operations. Mutate operations + create, update, or remove resources. Actions perform custom + operations. This method supports atomic transactions with + multiple types of resources and actions. For example, you can + atomically create a campaign and a campaign budget, or perform + up to thousands of mutates atomically. + + This method is essentially a wrapper around a series of mutate + methods. The only features it offers over calling those methods + directly are: + + - Atomic transactions + - Temp resource names (described below) + - Somewhat reduced latency over making a series of mutate calls + + Note: Only resources that support atomic transactions are + included, so this method can't replace all calls to individual + services. + + Atomic Transaction Benefits + --------------------------- + + Atomicity makes error handling much easier. If you're making a + series of changes and one fails, it can leave your account in an + inconsistent state. With atomicity, you either reach the chosen + state directly, or the request fails and you can retry. + + Temp Resource Names + ------------------- + + Temp resource names are a special type of resource name used to + create a resource and reference that resource in the same + request. For example, if a campaign budget is created with + ``resource_name`` equal to ``customers/123/campaignBudgets/-1``, + that resource name can be reused in the ``Campaign.budget`` + field in the same request. That way, the two resources are + created and linked atomically. + + To create a temp resource name, put a negative number in the + part of the name that the server would normally allocate. + + Note: + + - Resources must be created with a temp name before the name can + be reused. For example, the previous CampaignBudget+Campaign + example would fail if the mutate order was reversed. + - Temp names are not remembered across requests. + - There's no limit to the number of temp names in a request. + - Each temp name must use a unique negative number, even if the + resource types differ. + + Latency + ------- + + It's important to group mutates by resource type or the request + may time out and fail. Latency is roughly equal to a series of + calls to individual mutate methods, where each change in + resource type is a new call. For example, mutating 10 campaigns + then 10 ad groups is like 2 calls, while mutating 1 campaign, 1 + ad group, 1 campaign, 1 ad group is like 4 calls. + + List of thrown errors: `AdCustomizerError <>`__ `AdError <>`__ + `AdGroupAdError <>`__ `AdGroupCriterionError <>`__ + `AdGroupError <>`__ `AssetError <>`__ `AuthenticationError <>`__ + `AuthorizationError <>`__ `BiddingError <>`__ + `CampaignBudgetError <>`__ `CampaignCriterionError <>`__ + `CampaignError <>`__ `CampaignExperimentError <>`__ + `CampaignSharedSetError <>`__ `CollectionSizeError <>`__ + `ContextError <>`__ `ConversionActionError <>`__ + `CriterionError <>`__ `CustomerFeedError <>`__ + `DatabaseError <>`__ `DateError <>`__ `DateRangeError <>`__ + `DistinctError <>`__ `ExtensionFeedItemError <>`__ + `ExtensionSettingError <>`__ `FeedAttributeReferenceError <>`__ + `FeedError <>`__ `FeedItemError <>`__ `FeedItemSetError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `ImageError <>`__ + `InternalError <>`__ `KeywordPlanAdGroupKeywordError <>`__ + `KeywordPlanCampaignError <>`__ `KeywordPlanError <>`__ + `LabelError <>`__ `ListOperationError <>`__ + `MediaUploadError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `PolicyFindingError <>`__ + `PolicyViolationError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SettingError <>`__ `SharedSetError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ `UserListError <>`__ + `YoutubeVideoRegistrationError <>`__ + + Returns: + Callable[[~.MutateGoogleAdsRequest], + Awaitable[~.MutateGoogleAdsResponse]]: + 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 "mutate" not in self._stubs: + self._stubs["mutate"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.GoogleAdsService/Mutate", + request_serializer=google_ads_service.MutateGoogleAdsRequest.serialize, + response_deserializer=google_ads_service.MutateGoogleAdsResponse.deserialize, + ) + return self._stubs["mutate"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.search: self._wrap_method( + self.search, + default_timeout=None, + client_info=client_info, + ), + self.search_stream: self._wrap_method( + self.search_stream, + default_timeout=None, + client_info=client_info, + ), + self.mutate: self._wrap_method( + self.mutate, + 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" + + +__all__ = ("GoogleAdsServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/identity_verification_service/__init__.py b/google/ads/googleads/v24/services/services/identity_verification_service/__init__.py new file mode 100644 index 000000000..36c6b8a2e --- /dev/null +++ b/google/ads/googleads/v24/services/services/identity_verification_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import IdentityVerificationServiceClient +from .async_client import IdentityVerificationServiceAsyncClient + +__all__ = ( + "IdentityVerificationServiceClient", + "IdentityVerificationServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/identity_verification_service/async_client.py b/google/ads/googleads/v24/services/services/identity_verification_service/async_client.py new file mode 100644 index 000000000..9b37f7472 --- /dev/null +++ b/google/ads/googleads/v24/services/services/identity_verification_service/async_client.py @@ -0,0 +1,527 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.enums.types import identity_verification_program +from google.ads.googleads.v24.services.types import ( + identity_verification_service, +) +from .transports.base import ( + IdentityVerificationServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import IdentityVerificationServiceClient + +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 IdentityVerificationServiceAsyncClient: + """A service for managing Identity Verification Service.""" + + _client: IdentityVerificationServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = IdentityVerificationServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + IdentityVerificationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + IdentityVerificationServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = IdentityVerificationServiceClient._DEFAULT_UNIVERSE + + common_billing_account_path = staticmethod( + IdentityVerificationServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + IdentityVerificationServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + IdentityVerificationServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + IdentityVerificationServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + IdentityVerificationServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + IdentityVerificationServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + IdentityVerificationServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + IdentityVerificationServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + IdentityVerificationServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + IdentityVerificationServiceClient.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: + IdentityVerificationServiceAsyncClient: The constructed client. + """ + return IdentityVerificationServiceClient.from_service_account_info.__func__(IdentityVerificationServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + IdentityVerificationServiceAsyncClient: The constructed client. + """ + return IdentityVerificationServiceClient.from_service_account_file.__func__(IdentityVerificationServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return IdentityVerificationServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> IdentityVerificationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + IdentityVerificationServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = IdentityVerificationServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + IdentityVerificationServiceTransport, + Callable[..., IdentityVerificationServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the identity verification 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,IdentityVerificationServiceTransport,Callable[..., IdentityVerificationServiceTransport]]]): + 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 IdentityVerificationServiceTransport 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 = IdentityVerificationServiceClient( + 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.ads.googleads.v24.services.IdentityVerificationServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.IdentityVerificationService", + "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.ads.googleads.v24.services.IdentityVerificationService", + "credentialsType": None, + } + ), + ) + + async def start_identity_verification( + self, + request: Optional[ + Union[ + identity_verification_service.StartIdentityVerificationRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + verification_program: Optional[ + identity_verification_program.IdentityVerificationProgramEnum.IdentityVerificationProgram + ] = 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 Identity Verification for a given verification program + type. Statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.StartIdentityVerificationRequest, dict]]): + The request object. Request message for + [StartIdentityVerification][google.ads.googleads.v24.services.IdentityVerificationService.StartIdentityVerification]. + customer_id (:class:`str`): + Required. The Id of the customer for + whom we are creating this verification. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + verification_program (:class:`google.ads.googleads.v24.enums.types.IdentityVerificationProgramEnum.IdentityVerificationProgram`): + Required. The verification program + type for which we want to start the + verification. + + This corresponds to the ``verification_program`` 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 = [customer_id, verification_program] + 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, + identity_verification_service.StartIdentityVerificationRequest, + ): + request = ( + identity_verification_service.StartIdentityVerificationRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if verification_program is not None: + request.verification_program = verification_program + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.start_identity_verification + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + async def get_identity_verification( + self, + request: Optional[ + Union[ + identity_verification_service.GetIdentityVerificationRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> identity_verification_service.GetIdentityVerificationResponse: + r"""Returns Identity Verification information. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GetIdentityVerificationRequest, dict]]): + The request object. Request message for + [GetIdentityVerification][google.ads.googleads.v24.services.IdentityVerificationService.GetIdentityVerification]. + customer_id (:class:`str`): + Required. The ID of the customer for + whom we are requesting verification + information. + + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.GetIdentityVerificationResponse: + Response message for + [GetIdentityVerification][google.ads.googleads.v24.services.IdentityVerificationService.GetIdentityVerification]. + + """ + # 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 = [customer_id] + 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, + identity_verification_service.GetIdentityVerificationRequest, + ): + request = ( + identity_verification_service.GetIdentityVerificationRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_identity_verification + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "IdentityVerificationServiceAsyncClient": + 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__ = ("IdentityVerificationServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/identity_verification_service/client.py b/google/ads/googleads/v24/services/services/identity_verification_service/client.py new file mode 100644 index 000000000..9ab7620cb --- /dev/null +++ b/google/ads/googleads/v24/services/services/identity_verification_service/client.py @@ -0,0 +1,985 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.enums.types import identity_verification_program +from google.ads.googleads.v24.services.types import ( + identity_verification_service, +) +from .transports.base import ( + IdentityVerificationServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import IdentityVerificationServiceGrpcTransport +from .transports.grpc_asyncio import ( + IdentityVerificationServiceGrpcAsyncIOTransport, +) + + +class IdentityVerificationServiceClientMeta(type): + """Metaclass for the IdentityVerificationService 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[IdentityVerificationServiceTransport]] + _transport_registry["grpc"] = IdentityVerificationServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + IdentityVerificationServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[IdentityVerificationServiceTransport]: + """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 IdentityVerificationServiceClient( + metaclass=IdentityVerificationServiceClientMeta +): + """A service for managing Identity Verification Service.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + IdentityVerificationServiceClient: 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: + IdentityVerificationServiceClient: 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) -> IdentityVerificationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + IdentityVerificationServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @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 = ( + IdentityVerificationServiceClient._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 = ( + IdentityVerificationServiceClient._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 + ): + """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 = ( + IdentityVerificationServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + IdentityVerificationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = IdentityVerificationServiceClient._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 = IdentityVerificationServiceClient._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): + """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, + IdentityVerificationServiceTransport, + Callable[..., IdentityVerificationServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the identity verification 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,IdentityVerificationServiceTransport,Callable[..., IdentityVerificationServiceTransport]]]): + 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 IdentityVerificationServiceTransport 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, + ) = IdentityVerificationServiceClient._read_environment_variables() + self._client_cert_source = ( + IdentityVerificationServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + IdentityVerificationServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, IdentityVerificationServiceTransport + ) + if transport_provided: + # transport is a IdentityVerificationServiceTransport 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( + IdentityVerificationServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or IdentityVerificationServiceClient._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[IdentityVerificationServiceTransport], + Callable[..., IdentityVerificationServiceTransport], + ] = ( + IdentityVerificationServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., IdentityVerificationServiceTransport], + 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.ads.googleads.v24.services.IdentityVerificationServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.IdentityVerificationService", + "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.ads.googleads.v24.services.IdentityVerificationService", + "credentialsType": None, + } + ), + ) + + def start_identity_verification( + self, + request: Optional[ + Union[ + identity_verification_service.StartIdentityVerificationRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + verification_program: Optional[ + identity_verification_program.IdentityVerificationProgramEnum.IdentityVerificationProgram + ] = 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 Identity Verification for a given verification program + type. Statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.StartIdentityVerificationRequest, dict]): + The request object. Request message for + [StartIdentityVerification][google.ads.googleads.v24.services.IdentityVerificationService.StartIdentityVerification]. + customer_id (str): + Required. The Id of the customer for + whom we are creating this verification. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + verification_program (google.ads.googleads.v24.enums.types.IdentityVerificationProgramEnum.IdentityVerificationProgram): + Required. The verification program + type for which we want to start the + verification. + + This corresponds to the ``verification_program`` 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`. + """ + # 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 = [customer_id, verification_program] + 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, + identity_verification_service.StartIdentityVerificationRequest, + ): + request = ( + identity_verification_service.StartIdentityVerificationRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if verification_program is not None: + request.verification_program = verification_program + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.start_identity_verification + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + def get_identity_verification( + self, + request: Optional[ + Union[ + identity_verification_service.GetIdentityVerificationRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> identity_verification_service.GetIdentityVerificationResponse: + r"""Returns Identity Verification information. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GetIdentityVerificationRequest, dict]): + The request object. Request message for + [GetIdentityVerification][google.ads.googleads.v24.services.IdentityVerificationService.GetIdentityVerification]. + customer_id (str): + Required. The ID of the customer for + whom we are requesting verification + information. + + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.GetIdentityVerificationResponse: + Response message for + [GetIdentityVerification][google.ads.googleads.v24.services.IdentityVerificationService.GetIdentityVerification]. + + """ + # 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 = [customer_id] + 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, + identity_verification_service.GetIdentityVerificationRequest, + ): + request = ( + identity_verification_service.GetIdentityVerificationRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.get_identity_verification + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "IdentityVerificationServiceClient": + 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() + + +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__ = ("IdentityVerificationServiceClient",) diff --git a/google/ads/googleads/v24/services/services/identity_verification_service/transports/README.rst b/google/ads/googleads/v24/services/services/identity_verification_service/transports/README.rst new file mode 100644 index 000000000..62a06b1a2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/identity_verification_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`IdentityVerificationServiceTransport` is the ABC for all transports. +- public child `IdentityVerificationServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `IdentityVerificationServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseIdentityVerificationServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `IdentityVerificationServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/identity_verification_service/transports/__init__.py b/google/ads/googleads/v24/services/services/identity_verification_service/transports/__init__.py new file mode 100644 index 000000000..be088b912 --- /dev/null +++ b/google/ads/googleads/v24/services/services/identity_verification_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import IdentityVerificationServiceTransport +from .grpc import IdentityVerificationServiceGrpcTransport +from .grpc_asyncio import IdentityVerificationServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[IdentityVerificationServiceTransport]] +_transport_registry["grpc"] = IdentityVerificationServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + IdentityVerificationServiceGrpcAsyncIOTransport +) + +__all__ = ( + "IdentityVerificationServiceTransport", + "IdentityVerificationServiceGrpcTransport", + "IdentityVerificationServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/identity_verification_service/transports/base.py b/google/ads/googleads/v24/services/services/identity_verification_service/transports/base.py new file mode 100644 index 000000000..b1e1738a7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/identity_verification_service/transports/base.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + identity_verification_service, +) +from google.protobuf import empty_pb2 # type: ignore + +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 IdentityVerificationServiceTransport(abc.ABC): + """Abstract transport class for IdentityVerificationService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.start_identity_verification: gapic_v1.method.wrap_method( + self.start_identity_verification, + default_timeout=None, + client_info=client_info, + ), + self.get_identity_verification: gapic_v1.method.wrap_method( + self.get_identity_verification, + 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 start_identity_verification( + self, + ) -> Callable[ + [identity_verification_service.StartIdentityVerificationRequest], + Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]], + ]: + raise NotImplementedError() + + @property + def get_identity_verification( + self, + ) -> Callable[ + [identity_verification_service.GetIdentityVerificationRequest], + Union[ + identity_verification_service.GetIdentityVerificationResponse, + Awaitable[ + identity_verification_service.GetIdentityVerificationResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("IdentityVerificationServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/identity_verification_service/transports/grpc.py b/google/ads/googleads/v24/services/services/identity_verification_service/transports/grpc.py new file mode 100644 index 000000000..256f3b45c --- /dev/null +++ b/google/ads/googleads/v24/services/services/identity_verification_service/transports/grpc.py @@ -0,0 +1,428 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + identity_verification_service, +) +from google.protobuf import empty_pb2 # type: ignore +from .base import IdentityVerificationServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.IdentityVerificationService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.IdentityVerificationService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class IdentityVerificationServiceGrpcTransport( + IdentityVerificationServiceTransport +): + """gRPC backend transport for IdentityVerificationService. + + A service for managing Identity Verification Service. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 start_identity_verification( + self, + ) -> Callable[ + [identity_verification_service.StartIdentityVerificationRequest], + empty_pb2.Empty, + ]: + r"""Return a callable for the start identity verification method over gRPC. + + Starts Identity Verification for a given verification program + type. Statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.StartIdentityVerificationRequest], + ~.Empty]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "start_identity_verification" not in self._stubs: + self._stubs["start_identity_verification"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.IdentityVerificationService/StartIdentityVerification", + request_serializer=identity_verification_service.StartIdentityVerificationRequest.serialize, + response_deserializer=empty_pb2.Empty.FromString, + ) + ) + return self._stubs["start_identity_verification"] + + @property + def get_identity_verification( + self, + ) -> Callable[ + [identity_verification_service.GetIdentityVerificationRequest], + identity_verification_service.GetIdentityVerificationResponse, + ]: + r"""Return a callable for the get identity verification method over gRPC. + + Returns Identity Verification information. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GetIdentityVerificationRequest], + ~.GetIdentityVerificationResponse]: + 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_identity_verification" not in self._stubs: + self._stubs["get_identity_verification"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.IdentityVerificationService/GetIdentityVerification", + request_serializer=identity_verification_service.GetIdentityVerificationRequest.serialize, + response_deserializer=identity_verification_service.GetIdentityVerificationResponse.deserialize, + ) + ) + return self._stubs["get_identity_verification"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("IdentityVerificationServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/identity_verification_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/identity_verification_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..ccb2efabf --- /dev/null +++ b/google/ads/googleads/v24/services/services/identity_verification_service/transports/grpc_asyncio.py @@ -0,0 +1,456 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + identity_verification_service, +) +from google.protobuf import empty_pb2 # type: ignore +from .base import IdentityVerificationServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.IdentityVerificationService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.IdentityVerificationService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class IdentityVerificationServiceGrpcAsyncIOTransport( + IdentityVerificationServiceTransport +): + """gRPC AsyncIO backend transport for IdentityVerificationService. + + A service for managing Identity Verification Service. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 start_identity_verification( + self, + ) -> Callable[ + [identity_verification_service.StartIdentityVerificationRequest], + Awaitable[empty_pb2.Empty], + ]: + r"""Return a callable for the start identity verification method over gRPC. + + Starts Identity Verification for a given verification program + type. Statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.StartIdentityVerificationRequest], + Awaitable[~.Empty]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "start_identity_verification" not in self._stubs: + self._stubs["start_identity_verification"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.IdentityVerificationService/StartIdentityVerification", + request_serializer=identity_verification_service.StartIdentityVerificationRequest.serialize, + response_deserializer=empty_pb2.Empty.FromString, + ) + ) + return self._stubs["start_identity_verification"] + + @property + def get_identity_verification( + self, + ) -> Callable[ + [identity_verification_service.GetIdentityVerificationRequest], + Awaitable[ + identity_verification_service.GetIdentityVerificationResponse + ], + ]: + r"""Return a callable for the get identity verification method over gRPC. + + Returns Identity Verification information. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GetIdentityVerificationRequest], + Awaitable[~.GetIdentityVerificationResponse]]: + 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_identity_verification" not in self._stubs: + self._stubs["get_identity_verification"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.IdentityVerificationService/GetIdentityVerification", + request_serializer=identity_verification_service.GetIdentityVerificationRequest.serialize, + response_deserializer=identity_verification_service.GetIdentityVerificationResponse.deserialize, + ) + ) + return self._stubs["get_identity_verification"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.start_identity_verification: self._wrap_method( + self.start_identity_verification, + default_timeout=None, + client_info=client_info, + ), + self.get_identity_verification: self._wrap_method( + self.get_identity_verification, + 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" + + +__all__ = ("IdentityVerificationServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/incentive_service/__init__.py b/google/ads/googleads/v24/services/services/incentive_service/__init__.py new file mode 100644 index 000000000..e7bd10e9b --- /dev/null +++ b/google/ads/googleads/v24/services/services/incentive_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import IncentiveServiceClient +from .async_client import IncentiveServiceAsyncClient + +__all__ = ( + "IncentiveServiceClient", + "IncentiveServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/incentive_service/async_client.py b/google/ads/googleads/v24/services/services/incentive_service/async_client.py new file mode 100644 index 000000000..a6b98cde1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/incentive_service/async_client.py @@ -0,0 +1,457 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import incentive_service +from .transports.base import IncentiveServiceTransport, DEFAULT_CLIENT_INFO +from .client import IncentiveServiceClient + +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 IncentiveServiceAsyncClient: + """Service to support incentive related operations.""" + + _client: IncentiveServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = IncentiveServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = IncentiveServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + IncentiveServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = IncentiveServiceClient._DEFAULT_UNIVERSE + + common_billing_account_path = staticmethod( + IncentiveServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + IncentiveServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(IncentiveServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + IncentiveServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + IncentiveServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + IncentiveServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + IncentiveServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + IncentiveServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + IncentiveServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + IncentiveServiceClient.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: + IncentiveServiceAsyncClient: The constructed client. + """ + return IncentiveServiceClient.from_service_account_info.__func__(IncentiveServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + IncentiveServiceAsyncClient: The constructed client. + """ + return IncentiveServiceClient.from_service_account_file.__func__(IncentiveServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return IncentiveServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> IncentiveServiceTransport: + """Returns the transport used by the client instance. + + Returns: + IncentiveServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = IncentiveServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + IncentiveServiceTransport, + Callable[..., IncentiveServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the incentive 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,IncentiveServiceTransport,Callable[..., IncentiveServiceTransport]]]): + 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 IncentiveServiceTransport 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 = IncentiveServiceClient( + 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.ads.googleads.v24.services.IncentiveServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.IncentiveService", + "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.ads.googleads.v24.services.IncentiveService", + "credentialsType": None, + } + ), + ) + + async def fetch_incentive( + self, + request: Optional[ + Union[incentive_service.FetchIncentiveRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> incentive_service.FetchIncentiveResponse: + r"""Returns incentives for a given user. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.FetchIncentiveRequest, dict]]): + The request object. Request for getting the acquisition + incentive for a user. + 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.googleads.v24.services.types.FetchIncentiveResponse: + Response from getting the acquisition + incentive for a user when they visit a + specific marketing page. + + """ + # 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, incentive_service.FetchIncentiveRequest): + request = incentive_service.FetchIncentiveRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.fetch_incentive + ] + + # 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 apply_incentive( + self, + request: Optional[ + Union[incentive_service.ApplyIncentiveRequest, dict] + ] = None, + *, + country_code: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> incentive_service.ApplyIncentiveResponse: + r"""Applies the incentive for the ads customer. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ApplyIncentiveRequest, dict]]): + The request object. Request message for applying an + incentive. + country_code (:class:`str`): + Required. User's country code. Required. This field must + be equal to the Google Ads account's billing country. + Incentive eligibility, terms of service, and reward + values are often country-specific. This country code is + used to ensure the selected incentive is applicable to + the user. Possible country codes: + https://developers.google.com/google-ads/api/data/codes-formats#country_codes + + This corresponds to the ``country_code`` 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.ads.googleads.v24.services.types.ApplyIncentiveResponse: + Response for applying an incentive. + """ + # 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 = [country_code] + 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, incentive_service.ApplyIncentiveRequest): + request = incentive_service.ApplyIncentiveRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if country_code is not None: + request.country_code = country_code + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.apply_incentive + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ("customer_id", request.customer_id), + ("selected_incentive_id", request.selected_incentive_id), + ) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "IncentiveServiceAsyncClient": + 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__ = ("IncentiveServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/incentive_service/client.py b/google/ads/googleads/v24/services/services/incentive_service/client.py new file mode 100644 index 000000000..e2e194371 --- /dev/null +++ b/google/ads/googleads/v24/services/services/incentive_service/client.py @@ -0,0 +1,895 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import incentive_service +from .transports.base import IncentiveServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import IncentiveServiceGrpcTransport +from .transports.grpc_asyncio import IncentiveServiceGrpcAsyncIOTransport + + +class IncentiveServiceClientMeta(type): + """Metaclass for the IncentiveService 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[IncentiveServiceTransport]] + _transport_registry["grpc"] = IncentiveServiceGrpcTransport + _transport_registry["grpc_asyncio"] = IncentiveServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[IncentiveServiceTransport]: + """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 IncentiveServiceClient(metaclass=IncentiveServiceClientMeta): + """Service to support incentive related operations.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + IncentiveServiceClient: 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: + IncentiveServiceClient: 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) -> IncentiveServiceTransport: + """Returns the transport used by the client instance. + + Returns: + IncentiveServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @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 = IncentiveServiceClient._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 = IncentiveServiceClient._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 + ): + """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 = IncentiveServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = IncentiveServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + IncentiveServiceClient._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 = IncentiveServiceClient._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): + """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, + IncentiveServiceTransport, + Callable[..., IncentiveServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the incentive 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,IncentiveServiceTransport,Callable[..., IncentiveServiceTransport]]]): + 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 IncentiveServiceTransport 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, + ) = IncentiveServiceClient._read_environment_variables() + self._client_cert_source = ( + IncentiveServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = IncentiveServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, IncentiveServiceTransport) + if transport_provided: + # transport is a IncentiveServiceTransport 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(IncentiveServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or IncentiveServiceClient._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[IncentiveServiceTransport], + Callable[..., IncentiveServiceTransport], + ] = ( + IncentiveServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., IncentiveServiceTransport], 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.ads.googleads.v24.services.IncentiveServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.IncentiveService", + "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.ads.googleads.v24.services.IncentiveService", + "credentialsType": None, + } + ), + ) + + def fetch_incentive( + self, + request: Optional[ + Union[incentive_service.FetchIncentiveRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> incentive_service.FetchIncentiveResponse: + r"""Returns incentives for a given user. + + Args: + request (Union[google.ads.googleads.v24.services.types.FetchIncentiveRequest, dict]): + The request object. Request for getting the acquisition + incentive for a user. + 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.googleads.v24.services.types.FetchIncentiveResponse: + Response from getting the acquisition + incentive for a user when they visit a + specific marketing page. + + """ + # 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, incentive_service.FetchIncentiveRequest): + request = incentive_service.FetchIncentiveRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.fetch_incentive] + + # 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 apply_incentive( + self, + request: Optional[ + Union[incentive_service.ApplyIncentiveRequest, dict] + ] = None, + *, + country_code: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> incentive_service.ApplyIncentiveResponse: + r"""Applies the incentive for the ads customer. + + Args: + request (Union[google.ads.googleads.v24.services.types.ApplyIncentiveRequest, dict]): + The request object. Request message for applying an + incentive. + country_code (str): + Required. User's country code. Required. This field must + be equal to the Google Ads account's billing country. + Incentive eligibility, terms of service, and reward + values are often country-specific. This country code is + used to ensure the selected incentive is applicable to + the user. Possible country codes: + https://developers.google.com/google-ads/api/data/codes-formats#country_codes + + This corresponds to the ``country_code`` 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.ads.googleads.v24.services.types.ApplyIncentiveResponse: + Response for applying an incentive. + """ + # 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 = [country_code] + 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, incentive_service.ApplyIncentiveRequest): + request = incentive_service.ApplyIncentiveRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if country_code is not None: + request.country_code = country_code + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.apply_incentive] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ("customer_id", request.customer_id), + ("selected_incentive_id", request.selected_incentive_id), + ) + ), + ) + + # 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) -> "IncentiveServiceClient": + 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() + + +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__ = ("IncentiveServiceClient",) diff --git a/google/ads/googleads/v24/services/services/incentive_service/transports/README.rst b/google/ads/googleads/v24/services/services/incentive_service/transports/README.rst new file mode 100644 index 000000000..59e39e8df --- /dev/null +++ b/google/ads/googleads/v24/services/services/incentive_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`IncentiveServiceTransport` is the ABC for all transports. +- public child `IncentiveServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `IncentiveServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseIncentiveServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `IncentiveServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/incentive_service/transports/__init__.py b/google/ads/googleads/v24/services/services/incentive_service/transports/__init__.py new file mode 100644 index 000000000..0855ce0e6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/incentive_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import IncentiveServiceTransport +from .grpc import IncentiveServiceGrpcTransport +from .grpc_asyncio import IncentiveServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[IncentiveServiceTransport]] +_transport_registry["grpc"] = IncentiveServiceGrpcTransport +_transport_registry["grpc_asyncio"] = IncentiveServiceGrpcAsyncIOTransport + +__all__ = ( + "IncentiveServiceTransport", + "IncentiveServiceGrpcTransport", + "IncentiveServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/incentive_service/transports/base.py b/google/ads/googleads/v24/services/services/incentive_service/transports/base.py new file mode 100644 index 000000000..47bc0fac7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/incentive_service/transports/base.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import incentive_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 IncentiveServiceTransport(abc.ABC): + """Abstract transport class for IncentiveService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.fetch_incentive: gapic_v1.method.wrap_method( + self.fetch_incentive, + default_timeout=None, + client_info=client_info, + ), + self.apply_incentive: gapic_v1.method.wrap_method( + self.apply_incentive, + 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 fetch_incentive( + self, + ) -> Callable[ + [incentive_service.FetchIncentiveRequest], + Union[ + incentive_service.FetchIncentiveResponse, + Awaitable[incentive_service.FetchIncentiveResponse], + ], + ]: + raise NotImplementedError() + + @property + def apply_incentive( + self, + ) -> Callable[ + [incentive_service.ApplyIncentiveRequest], + Union[ + incentive_service.ApplyIncentiveResponse, + Awaitable[incentive_service.ApplyIncentiveResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("IncentiveServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/incentive_service/transports/grpc.py b/google/ads/googleads/v24/services/services/incentive_service/transports/grpc.py new file mode 100644 index 000000000..e28889a45 --- /dev/null +++ b/google/ads/googleads/v24/services/services/incentive_service/transports/grpc.py @@ -0,0 +1,410 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import incentive_service +from .base import IncentiveServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.IncentiveService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.IncentiveService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class IncentiveServiceGrpcTransport(IncentiveServiceTransport): + """gRPC backend transport for IncentiveService. + + Service to support incentive related operations. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 fetch_incentive( + self, + ) -> Callable[ + [incentive_service.FetchIncentiveRequest], + incentive_service.FetchIncentiveResponse, + ]: + r"""Return a callable for the fetch incentive method over gRPC. + + Returns incentives for a given user. + + Returns: + Callable[[~.FetchIncentiveRequest], + ~.FetchIncentiveResponse]: + 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 "fetch_incentive" not in self._stubs: + self._stubs["fetch_incentive"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.IncentiveService/FetchIncentive", + request_serializer=incentive_service.FetchIncentiveRequest.serialize, + response_deserializer=incentive_service.FetchIncentiveResponse.deserialize, + ) + return self._stubs["fetch_incentive"] + + @property + def apply_incentive( + self, + ) -> Callable[ + [incentive_service.ApplyIncentiveRequest], + incentive_service.ApplyIncentiveResponse, + ]: + r"""Return a callable for the apply incentive method over gRPC. + + Applies the incentive for the ads customer. + + Returns: + Callable[[~.ApplyIncentiveRequest], + ~.ApplyIncentiveResponse]: + 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 "apply_incentive" not in self._stubs: + self._stubs["apply_incentive"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.IncentiveService/ApplyIncentive", + request_serializer=incentive_service.ApplyIncentiveRequest.serialize, + response_deserializer=incentive_service.ApplyIncentiveResponse.deserialize, + ) + return self._stubs["apply_incentive"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("IncentiveServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/incentive_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/incentive_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..e2bb10fa7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/incentive_service/transports/grpc_asyncio.py @@ -0,0 +1,436 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import incentive_service +from .base import IncentiveServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.IncentiveService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.IncentiveService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class IncentiveServiceGrpcAsyncIOTransport(IncentiveServiceTransport): + """gRPC AsyncIO backend transport for IncentiveService. + + Service to support incentive related operations. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 fetch_incentive( + self, + ) -> Callable[ + [incentive_service.FetchIncentiveRequest], + Awaitable[incentive_service.FetchIncentiveResponse], + ]: + r"""Return a callable for the fetch incentive method over gRPC. + + Returns incentives for a given user. + + Returns: + Callable[[~.FetchIncentiveRequest], + Awaitable[~.FetchIncentiveResponse]]: + 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 "fetch_incentive" not in self._stubs: + self._stubs["fetch_incentive"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.IncentiveService/FetchIncentive", + request_serializer=incentive_service.FetchIncentiveRequest.serialize, + response_deserializer=incentive_service.FetchIncentiveResponse.deserialize, + ) + return self._stubs["fetch_incentive"] + + @property + def apply_incentive( + self, + ) -> Callable[ + [incentive_service.ApplyIncentiveRequest], + Awaitable[incentive_service.ApplyIncentiveResponse], + ]: + r"""Return a callable for the apply incentive method over gRPC. + + Applies the incentive for the ads customer. + + Returns: + Callable[[~.ApplyIncentiveRequest], + Awaitable[~.ApplyIncentiveResponse]]: + 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 "apply_incentive" not in self._stubs: + self._stubs["apply_incentive"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.IncentiveService/ApplyIncentive", + request_serializer=incentive_service.ApplyIncentiveRequest.serialize, + response_deserializer=incentive_service.ApplyIncentiveResponse.deserialize, + ) + return self._stubs["apply_incentive"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.fetch_incentive: self._wrap_method( + self.fetch_incentive, + default_timeout=None, + client_info=client_info, + ), + self.apply_incentive: self._wrap_method( + self.apply_incentive, + 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" + + +__all__ = ("IncentiveServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/invoice_service/__init__.py b/google/ads/googleads/v24/services/services/invoice_service/__init__.py new file mode 100644 index 000000000..574705400 --- /dev/null +++ b/google/ads/googleads/v24/services/services/invoice_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import InvoiceServiceClient +from .async_client import InvoiceServiceAsyncClient + +__all__ = ( + "InvoiceServiceClient", + "InvoiceServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/invoice_service/async_client.py b/google/ads/googleads/v24/services/services/invoice_service/async_client.py new file mode 100644 index 000000000..e39f2d7cf --- /dev/null +++ b/google/ads/googleads/v24/services/services/invoice_service/async_client.py @@ -0,0 +1,436 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.enums.types import month_of_year +from google.ads.googleads.v24.services.types import invoice_service +from .transports.base import InvoiceServiceTransport, DEFAULT_CLIENT_INFO +from .client import InvoiceServiceClient + +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 InvoiceServiceAsyncClient: + """A service to fetch invoices issued for a billing setup during + a given month. + """ + + _client: InvoiceServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = InvoiceServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = InvoiceServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = InvoiceServiceClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = InvoiceServiceClient._DEFAULT_UNIVERSE + + invoice_path = staticmethod(InvoiceServiceClient.invoice_path) + parse_invoice_path = staticmethod(InvoiceServiceClient.parse_invoice_path) + common_billing_account_path = staticmethod( + InvoiceServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + InvoiceServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(InvoiceServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + InvoiceServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + InvoiceServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + InvoiceServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod(InvoiceServiceClient.common_project_path) + parse_common_project_path = staticmethod( + InvoiceServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + InvoiceServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + InvoiceServiceClient.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: + InvoiceServiceAsyncClient: The constructed client. + """ + return InvoiceServiceClient.from_service_account_info.__func__(InvoiceServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + InvoiceServiceAsyncClient: The constructed client. + """ + return InvoiceServiceClient.from_service_account_file.__func__(InvoiceServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return InvoiceServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> InvoiceServiceTransport: + """Returns the transport used by the client instance. + + Returns: + InvoiceServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = InvoiceServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + InvoiceServiceTransport, + Callable[..., InvoiceServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the invoice 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,InvoiceServiceTransport,Callable[..., InvoiceServiceTransport]]]): + 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 InvoiceServiceTransport 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 = InvoiceServiceClient( + 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.ads.googleads.v24.services.InvoiceServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.InvoiceService", + "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.ads.googleads.v24.services.InvoiceService", + "credentialsType": None, + } + ), + ) + + async def list_invoices( + self, + request: Optional[ + Union[invoice_service.ListInvoicesRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + billing_setup: Optional[str] = None, + issue_year: Optional[str] = None, + issue_month: Optional[month_of_year.MonthOfYearEnum.MonthOfYear] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> invoice_service.ListInvoicesResponse: + r"""Returns all invoices associated with a billing setup, for a + given month. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `InvoiceError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListInvoicesRequest, dict]]): + The request object. Request message for fetching the + invoices of a given billing setup that + were issued during a given month. + customer_id (:class:`str`): + Required. The ID of the customer to + fetch invoices for. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + billing_setup (:class:`str`): + Required. The billing setup resource name of the + requested invoices. + + ``customers/{customer_id}/billingSetups/{billing_setup_id}`` + + This corresponds to the ``billing_setup`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + issue_year (:class:`str`): + Required. The issue year to retrieve + invoices, in yyyy format. Only invoices + issued in 2019 or later can be + retrieved. + + This corresponds to the ``issue_year`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + issue_month (:class:`google.ads.googleads.v24.enums.types.MonthOfYearEnum.MonthOfYear`): + Required. The issue month to retrieve + invoices. + + This corresponds to the ``issue_month`` 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.ads.googleads.v24.services.types.ListInvoicesResponse: + Response message for + [InvoiceService.ListInvoices][google.ads.googleads.v24.services.InvoiceService.ListInvoices]. + + """ + # 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 = [customer_id, billing_setup, issue_year, issue_month] + 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, invoice_service.ListInvoicesRequest): + request = invoice_service.ListInvoicesRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if billing_setup is not None: + request.billing_setup = billing_setup + if issue_year is not None: + request.issue_year = issue_year + if issue_month is not None: + request.issue_month = issue_month + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_invoices + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "InvoiceServiceAsyncClient": + 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__ = ("InvoiceServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/invoice_service/client.py b/google/ads/googleads/v24/services/services/invoice_service/client.py new file mode 100644 index 000000000..335a736ae --- /dev/null +++ b/google/ads/googleads/v24/services/services/invoice_service/client.py @@ -0,0 +1,896 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.enums.types import month_of_year +from google.ads.googleads.v24.services.types import invoice_service +from .transports.base import InvoiceServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import InvoiceServiceGrpcTransport +from .transports.grpc_asyncio import InvoiceServiceGrpcAsyncIOTransport + + +class InvoiceServiceClientMeta(type): + """Metaclass for the InvoiceService 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[InvoiceServiceTransport]] + _transport_registry["grpc"] = InvoiceServiceGrpcTransport + _transport_registry["grpc_asyncio"] = InvoiceServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[InvoiceServiceTransport]: + """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 InvoiceServiceClient(metaclass=InvoiceServiceClientMeta): + """A service to fetch invoices issued for a billing setup during + a given month. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + InvoiceServiceClient: 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: + InvoiceServiceClient: 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) -> InvoiceServiceTransport: + """Returns the transport used by the client instance. + + Returns: + InvoiceServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def invoice_path( + customer_id: str, + invoice_id: str, + ) -> str: + """Returns a fully-qualified invoice string.""" + return "customers/{customer_id}/invoices/{invoice_id}".format( + customer_id=customer_id, + invoice_id=invoice_id, + ) + + @staticmethod + def parse_invoice_path(path: str) -> Dict[str, str]: + """Parses a invoice path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/invoices/(?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 = InvoiceServiceClient._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 = InvoiceServiceClient._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 + ): + """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 = InvoiceServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = InvoiceServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + InvoiceServiceClient._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 = InvoiceServiceClient._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): + """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, + InvoiceServiceTransport, + Callable[..., InvoiceServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the invoice 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,InvoiceServiceTransport,Callable[..., InvoiceServiceTransport]]]): + 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 InvoiceServiceTransport 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, + ) = InvoiceServiceClient._read_environment_variables() + self._client_cert_source = InvoiceServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = InvoiceServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, InvoiceServiceTransport) + if transport_provided: + # transport is a InvoiceServiceTransport 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(InvoiceServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or InvoiceServiceClient._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[InvoiceServiceTransport], + Callable[..., InvoiceServiceTransport], + ] = ( + InvoiceServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., InvoiceServiceTransport], 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.ads.googleads.v24.services.InvoiceServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.InvoiceService", + "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.ads.googleads.v24.services.InvoiceService", + "credentialsType": None, + } + ), + ) + + def list_invoices( + self, + request: Optional[ + Union[invoice_service.ListInvoicesRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + billing_setup: Optional[str] = None, + issue_year: Optional[str] = None, + issue_month: Optional[month_of_year.MonthOfYearEnum.MonthOfYear] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> invoice_service.ListInvoicesResponse: + r"""Returns all invoices associated with a billing setup, for a + given month. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `InvoiceError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListInvoicesRequest, dict]): + The request object. Request message for fetching the + invoices of a given billing setup that + were issued during a given month. + customer_id (str): + Required. The ID of the customer to + fetch invoices for. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + billing_setup (str): + Required. The billing setup resource name of the + requested invoices. + + ``customers/{customer_id}/billingSetups/{billing_setup_id}`` + + This corresponds to the ``billing_setup`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + issue_year (str): + Required. The issue year to retrieve + invoices, in yyyy format. Only invoices + issued in 2019 or later can be + retrieved. + + This corresponds to the ``issue_year`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + issue_month (google.ads.googleads.v24.enums.types.MonthOfYearEnum.MonthOfYear): + Required. The issue month to retrieve + invoices. + + This corresponds to the ``issue_month`` 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.ads.googleads.v24.services.types.ListInvoicesResponse: + Response message for + [InvoiceService.ListInvoices][google.ads.googleads.v24.services.InvoiceService.ListInvoices]. + + """ + # 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 = [customer_id, billing_setup, issue_year, issue_month] + 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, invoice_service.ListInvoicesRequest): + request = invoice_service.ListInvoicesRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if billing_setup is not None: + request.billing_setup = billing_setup + if issue_year is not None: + request.issue_year = issue_year + if issue_month is not None: + request.issue_month = issue_month + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.list_invoices] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "InvoiceServiceClient": + 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() + + +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__ = ("InvoiceServiceClient",) diff --git a/google/ads/googleads/v24/services/services/invoice_service/transports/README.rst b/google/ads/googleads/v24/services/services/invoice_service/transports/README.rst new file mode 100644 index 000000000..b3f353b9d --- /dev/null +++ b/google/ads/googleads/v24/services/services/invoice_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`InvoiceServiceTransport` is the ABC for all transports. +- public child `InvoiceServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `InvoiceServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseInvoiceServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `InvoiceServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/invoice_service/transports/__init__.py b/google/ads/googleads/v24/services/services/invoice_service/transports/__init__.py new file mode 100644 index 000000000..828dd740a --- /dev/null +++ b/google/ads/googleads/v24/services/services/invoice_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import InvoiceServiceTransport +from .grpc import InvoiceServiceGrpcTransport +from .grpc_asyncio import InvoiceServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[InvoiceServiceTransport]] +_transport_registry["grpc"] = InvoiceServiceGrpcTransport +_transport_registry["grpc_asyncio"] = InvoiceServiceGrpcAsyncIOTransport + +__all__ = ( + "InvoiceServiceTransport", + "InvoiceServiceGrpcTransport", + "InvoiceServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/invoice_service/transports/base.py b/google/ads/googleads/v24/services/services/invoice_service/transports/base.py new file mode 100644 index 000000000..bedf04e40 --- /dev/null +++ b/google/ads/googleads/v24/services/services/invoice_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import invoice_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 InvoiceServiceTransport(abc.ABC): + """Abstract transport class for InvoiceService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.list_invoices: gapic_v1.method.wrap_method( + self.list_invoices, + 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_invoices( + self, + ) -> Callable[ + [invoice_service.ListInvoicesRequest], + Union[ + invoice_service.ListInvoicesResponse, + Awaitable[invoice_service.ListInvoicesResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("InvoiceServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/invoice_service/transports/grpc.py b/google/ads/googleads/v24/services/services/invoice_service/transports/grpc.py new file mode 100644 index 000000000..e34f29dbc --- /dev/null +++ b/google/ads/googleads/v24/services/services/invoice_service/transports/grpc.py @@ -0,0 +1,388 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import invoice_service +from .base import InvoiceServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.InvoiceService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.InvoiceService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class InvoiceServiceGrpcTransport(InvoiceServiceTransport): + """gRPC backend transport for InvoiceService. + + A service to fetch invoices issued for a billing setup during + a given month. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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_invoices( + self, + ) -> Callable[ + [invoice_service.ListInvoicesRequest], + invoice_service.ListInvoicesResponse, + ]: + r"""Return a callable for the list invoices method over gRPC. + + Returns all invoices associated with a billing setup, for a + given month. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `InvoiceError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.ListInvoicesRequest], + ~.ListInvoicesResponse]: + 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_invoices" not in self._stubs: + self._stubs["list_invoices"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.InvoiceService/ListInvoices", + request_serializer=invoice_service.ListInvoicesRequest.serialize, + response_deserializer=invoice_service.ListInvoicesResponse.deserialize, + ) + return self._stubs["list_invoices"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("InvoiceServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/invoice_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/invoice_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..9c07699a0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/invoice_service/transports/grpc_asyncio.py @@ -0,0 +1,409 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import invoice_service +from .base import InvoiceServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.InvoiceService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.InvoiceService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class InvoiceServiceGrpcAsyncIOTransport(InvoiceServiceTransport): + """gRPC AsyncIO backend transport for InvoiceService. + + A service to fetch invoices issued for a billing setup during + a given month. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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_invoices( + self, + ) -> Callable[ + [invoice_service.ListInvoicesRequest], + Awaitable[invoice_service.ListInvoicesResponse], + ]: + r"""Return a callable for the list invoices method over gRPC. + + Returns all invoices associated with a billing setup, for a + given month. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `InvoiceError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.ListInvoicesRequest], + Awaitable[~.ListInvoicesResponse]]: + 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_invoices" not in self._stubs: + self._stubs["list_invoices"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.InvoiceService/ListInvoices", + request_serializer=invoice_service.ListInvoicesRequest.serialize, + response_deserializer=invoice_service.ListInvoicesResponse.deserialize, + ) + return self._stubs["list_invoices"] + + 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_invoices: self._wrap_method( + self.list_invoices, + 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" + + +__all__ = ("InvoiceServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/__init__.py b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/__init__.py new file mode 100644 index 000000000..b9384ea3a --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import KeywordPlanAdGroupKeywordServiceClient +from .async_client import KeywordPlanAdGroupKeywordServiceAsyncClient + +__all__ = ( + "KeywordPlanAdGroupKeywordServiceClient", + "KeywordPlanAdGroupKeywordServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/async_client.py b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/async_client.py new file mode 100644 index 000000000..b6bf3bd87 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/async_client.py @@ -0,0 +1,459 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + keyword_plan_ad_group_keyword_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + KeywordPlanAdGroupKeywordServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import KeywordPlanAdGroupKeywordServiceClient + +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 KeywordPlanAdGroupKeywordServiceAsyncClient: + """Service to manage Keyword Plan ad group keywords. + KeywordPlanAdGroup is required to add ad group keywords. + Positive and negative keywords are supported. A maximum of + 10,000 positive keywords are allowed per keyword plan. A maximum + of 1,000 negative keywords are allower per keyword plan. This + includes campaign negative keywords and ad group negative + keywords. + """ + + _client: KeywordPlanAdGroupKeywordServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = KeywordPlanAdGroupKeywordServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + KeywordPlanAdGroupKeywordServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + KeywordPlanAdGroupKeywordServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = KeywordPlanAdGroupKeywordServiceClient._DEFAULT_UNIVERSE + + keyword_plan_ad_group_path = staticmethod( + KeywordPlanAdGroupKeywordServiceClient.keyword_plan_ad_group_path + ) + parse_keyword_plan_ad_group_path = staticmethod( + KeywordPlanAdGroupKeywordServiceClient.parse_keyword_plan_ad_group_path + ) + keyword_plan_ad_group_keyword_path = staticmethod( + KeywordPlanAdGroupKeywordServiceClient.keyword_plan_ad_group_keyword_path + ) + parse_keyword_plan_ad_group_keyword_path = staticmethod( + KeywordPlanAdGroupKeywordServiceClient.parse_keyword_plan_ad_group_keyword_path + ) + common_billing_account_path = staticmethod( + KeywordPlanAdGroupKeywordServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + KeywordPlanAdGroupKeywordServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + KeywordPlanAdGroupKeywordServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + KeywordPlanAdGroupKeywordServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + KeywordPlanAdGroupKeywordServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + KeywordPlanAdGroupKeywordServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + KeywordPlanAdGroupKeywordServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + KeywordPlanAdGroupKeywordServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + KeywordPlanAdGroupKeywordServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + KeywordPlanAdGroupKeywordServiceClient.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: + KeywordPlanAdGroupKeywordServiceAsyncClient: The constructed client. + """ + return KeywordPlanAdGroupKeywordServiceClient.from_service_account_info.__func__(KeywordPlanAdGroupKeywordServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + KeywordPlanAdGroupKeywordServiceAsyncClient: The constructed client. + """ + return KeywordPlanAdGroupKeywordServiceClient.from_service_account_file.__func__(KeywordPlanAdGroupKeywordServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return KeywordPlanAdGroupKeywordServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> KeywordPlanAdGroupKeywordServiceTransport: + """Returns the transport used by the client instance. + + Returns: + KeywordPlanAdGroupKeywordServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + KeywordPlanAdGroupKeywordServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + KeywordPlanAdGroupKeywordServiceTransport, + Callable[..., KeywordPlanAdGroupKeywordServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the keyword plan ad group keyword 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,KeywordPlanAdGroupKeywordServiceTransport,Callable[..., KeywordPlanAdGroupKeywordServiceTransport]]]): + 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 KeywordPlanAdGroupKeywordServiceTransport 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 = KeywordPlanAdGroupKeywordServiceClient( + 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.ads.googleads.v24.services.KeywordPlanAdGroupKeywordServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.KeywordPlanAdGroupKeywordService", + "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.ads.googleads.v24.services.KeywordPlanAdGroupKeywordService", + "credentialsType": None, + } + ), + ) + + async def mutate_keyword_plan_ad_group_keywords( + self, + request: Optional[ + Union[ + keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + keyword_plan_ad_group_keyword_service.KeywordPlanAdGroupKeywordOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsResponse + ): + r"""Creates, updates, or removes Keyword Plan ad group keywords. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanAdGroupKeywordError <>`__ `KeywordPlanError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateKeywordPlanAdGroupKeywordsRequest, dict]]): + The request object. Request message for + [KeywordPlanAdGroupKeywordService.MutateKeywordPlanAdGroupKeywords][google.ads.googleads.v24.services.KeywordPlanAdGroupKeywordService.MutateKeywordPlanAdGroupKeywords]. + customer_id (:class:`str`): + Required. The ID of the customer + whose Keyword Plan ad group keywords are + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanAdGroupKeywordOperation]`): + Required. The list of operations to + perform on individual Keyword Plan ad + group keywords. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateKeywordPlanAdGroupKeywordsResponse: + Response message for a Keyword Plan + ad group keyword mutate. + + """ + # 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 = [customer_id, operations] + 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, + keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsRequest, + ): + request = keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_keyword_plan_ad_group_keywords + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "KeywordPlanAdGroupKeywordServiceAsyncClient": + 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__ = ("KeywordPlanAdGroupKeywordServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/client.py b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/client.py new file mode 100644 index 000000000..97e6a762c --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/client.py @@ -0,0 +1,958 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + keyword_plan_ad_group_keyword_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + KeywordPlanAdGroupKeywordServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import KeywordPlanAdGroupKeywordServiceGrpcTransport +from .transports.grpc_asyncio import ( + KeywordPlanAdGroupKeywordServiceGrpcAsyncIOTransport, +) + + +class KeywordPlanAdGroupKeywordServiceClientMeta(type): + """Metaclass for the KeywordPlanAdGroupKeywordService 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[KeywordPlanAdGroupKeywordServiceTransport]] + _transport_registry["grpc"] = KeywordPlanAdGroupKeywordServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + KeywordPlanAdGroupKeywordServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[KeywordPlanAdGroupKeywordServiceTransport]: + """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 KeywordPlanAdGroupKeywordServiceClient( + metaclass=KeywordPlanAdGroupKeywordServiceClientMeta +): + """Service to manage Keyword Plan ad group keywords. + KeywordPlanAdGroup is required to add ad group keywords. + Positive and negative keywords are supported. A maximum of + 10,000 positive keywords are allowed per keyword plan. A maximum + of 1,000 negative keywords are allower per keyword plan. This + includes campaign negative keywords and ad group negative + keywords. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + KeywordPlanAdGroupKeywordServiceClient: 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: + KeywordPlanAdGroupKeywordServiceClient: 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) -> KeywordPlanAdGroupKeywordServiceTransport: + """Returns the transport used by the client instance. + + Returns: + KeywordPlanAdGroupKeywordServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def keyword_plan_ad_group_path( + customer_id: str, + keyword_plan_ad_group_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_ad_group string.""" + return "customers/{customer_id}/keywordPlanAdGroups/{keyword_plan_ad_group_id}".format( + customer_id=customer_id, + keyword_plan_ad_group_id=keyword_plan_ad_group_id, + ) + + @staticmethod + def parse_keyword_plan_ad_group_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanAdGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_ad_group_keyword_path( + customer_id: str, + keyword_plan_ad_group_keyword_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_ad_group_keyword string.""" + return "customers/{customer_id}/keywordPlanAdGroupKeywords/{keyword_plan_ad_group_keyword_id}".format( + customer_id=customer_id, + keyword_plan_ad_group_keyword_id=keyword_plan_ad_group_keyword_id, + ) + + @staticmethod + def parse_keyword_plan_ad_group_keyword_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_ad_group_keyword path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanAdGroupKeywords/(?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 = ( + KeywordPlanAdGroupKeywordServiceClient._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 = ( + KeywordPlanAdGroupKeywordServiceClient._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 + ): + """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 = ( + KeywordPlanAdGroupKeywordServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + KeywordPlanAdGroupKeywordServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = KeywordPlanAdGroupKeywordServiceClient._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 = ( + KeywordPlanAdGroupKeywordServiceClient._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): + """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, + KeywordPlanAdGroupKeywordServiceTransport, + Callable[..., KeywordPlanAdGroupKeywordServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the keyword plan ad group keyword 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,KeywordPlanAdGroupKeywordServiceTransport,Callable[..., KeywordPlanAdGroupKeywordServiceTransport]]]): + 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 KeywordPlanAdGroupKeywordServiceTransport 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, + ) = KeywordPlanAdGroupKeywordServiceClient._read_environment_variables() + self._client_cert_source = ( + KeywordPlanAdGroupKeywordServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + KeywordPlanAdGroupKeywordServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, KeywordPlanAdGroupKeywordServiceTransport + ) + if transport_provided: + # transport is a KeywordPlanAdGroupKeywordServiceTransport 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( + KeywordPlanAdGroupKeywordServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or KeywordPlanAdGroupKeywordServiceClient._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[KeywordPlanAdGroupKeywordServiceTransport], + Callable[..., KeywordPlanAdGroupKeywordServiceTransport], + ] = ( + KeywordPlanAdGroupKeywordServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., KeywordPlanAdGroupKeywordServiceTransport], + 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.ads.googleads.v24.services.KeywordPlanAdGroupKeywordServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.KeywordPlanAdGroupKeywordService", + "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.ads.googleads.v24.services.KeywordPlanAdGroupKeywordService", + "credentialsType": None, + } + ), + ) + + def mutate_keyword_plan_ad_group_keywords( + self, + request: Optional[ + Union[ + keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + keyword_plan_ad_group_keyword_service.KeywordPlanAdGroupKeywordOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsResponse + ): + r"""Creates, updates, or removes Keyword Plan ad group keywords. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanAdGroupKeywordError <>`__ `KeywordPlanError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateKeywordPlanAdGroupKeywordsRequest, dict]): + The request object. Request message for + [KeywordPlanAdGroupKeywordService.MutateKeywordPlanAdGroupKeywords][google.ads.googleads.v24.services.KeywordPlanAdGroupKeywordService.MutateKeywordPlanAdGroupKeywords]. + customer_id (str): + Required. The ID of the customer + whose Keyword Plan ad group keywords are + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanAdGroupKeywordOperation]): + Required. The list of operations to + perform on individual Keyword Plan ad + group keywords. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateKeywordPlanAdGroupKeywordsResponse: + Response message for a Keyword Plan + ad group keyword mutate. + + """ + # 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 = [customer_id, operations] + 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, + keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsRequest, + ): + request = keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_keyword_plan_ad_group_keywords + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "KeywordPlanAdGroupKeywordServiceClient": + 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() + + +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__ = ("KeywordPlanAdGroupKeywordServiceClient",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/README.rst b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/README.rst new file mode 100644 index 000000000..258c2efab --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`KeywordPlanAdGroupKeywordServiceTransport` is the ABC for all transports. +- public child `KeywordPlanAdGroupKeywordServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `KeywordPlanAdGroupKeywordServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseKeywordPlanAdGroupKeywordServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `KeywordPlanAdGroupKeywordServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/__init__.py b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/__init__.py new file mode 100644 index 000000000..04bd37d8c --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import KeywordPlanAdGroupKeywordServiceTransport +from .grpc import KeywordPlanAdGroupKeywordServiceGrpcTransport +from .grpc_asyncio import KeywordPlanAdGroupKeywordServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[KeywordPlanAdGroupKeywordServiceTransport]] +_transport_registry["grpc"] = KeywordPlanAdGroupKeywordServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + KeywordPlanAdGroupKeywordServiceGrpcAsyncIOTransport +) + +__all__ = ( + "KeywordPlanAdGroupKeywordServiceTransport", + "KeywordPlanAdGroupKeywordServiceGrpcTransport", + "KeywordPlanAdGroupKeywordServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/base.py b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/base.py new file mode 100644 index 000000000..e424d1a44 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + keyword_plan_ad_group_keyword_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 KeywordPlanAdGroupKeywordServiceTransport(abc.ABC): + """Abstract transport class for KeywordPlanAdGroupKeywordService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_keyword_plan_ad_group_keywords: gapic_v1.method.wrap_method( + self.mutate_keyword_plan_ad_group_keywords, + 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 mutate_keyword_plan_ad_group_keywords( + self, + ) -> Callable[ + [ + keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsRequest + ], + Union[ + keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsResponse, + Awaitable[ + keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("KeywordPlanAdGroupKeywordServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/grpc.py b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/grpc.py new file mode 100644 index 000000000..8748b89ab --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/grpc.py @@ -0,0 +1,404 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + keyword_plan_ad_group_keyword_service, +) +from .base import KeywordPlanAdGroupKeywordServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.KeywordPlanAdGroupKeywordService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.KeywordPlanAdGroupKeywordService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class KeywordPlanAdGroupKeywordServiceGrpcTransport( + KeywordPlanAdGroupKeywordServiceTransport +): + """gRPC backend transport for KeywordPlanAdGroupKeywordService. + + Service to manage Keyword Plan ad group keywords. + KeywordPlanAdGroup is required to add ad group keywords. + Positive and negative keywords are supported. A maximum of + 10,000 positive keywords are allowed per keyword plan. A maximum + of 1,000 negative keywords are allower per keyword plan. This + includes campaign negative keywords and ad group negative + keywords. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_keyword_plan_ad_group_keywords( + self, + ) -> Callable[ + [ + keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsRequest + ], + keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsResponse, + ]: + r"""Return a callable for the mutate keyword plan ad group + keywords method over gRPC. + + Creates, updates, or removes Keyword Plan ad group keywords. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanAdGroupKeywordError <>`__ `KeywordPlanError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Returns: + Callable[[~.MutateKeywordPlanAdGroupKeywordsRequest], + ~.MutateKeywordPlanAdGroupKeywordsResponse]: + 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 "mutate_keyword_plan_ad_group_keywords" not in self._stubs: + self._stubs["mutate_keyword_plan_ad_group_keywords"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanAdGroupKeywordService/MutateKeywordPlanAdGroupKeywords", + request_serializer=keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsRequest.serialize, + response_deserializer=keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsResponse.deserialize, + ) + ) + return self._stubs["mutate_keyword_plan_ad_group_keywords"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("KeywordPlanAdGroupKeywordServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..5d80b1e06 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_keyword_service/transports/grpc_asyncio.py @@ -0,0 +1,427 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + keyword_plan_ad_group_keyword_service, +) +from .base import KeywordPlanAdGroupKeywordServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.KeywordPlanAdGroupKeywordService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.KeywordPlanAdGroupKeywordService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class KeywordPlanAdGroupKeywordServiceGrpcAsyncIOTransport( + KeywordPlanAdGroupKeywordServiceTransport +): + """gRPC AsyncIO backend transport for KeywordPlanAdGroupKeywordService. + + Service to manage Keyword Plan ad group keywords. + KeywordPlanAdGroup is required to add ad group keywords. + Positive and negative keywords are supported. A maximum of + 10,000 positive keywords are allowed per keyword plan. A maximum + of 1,000 negative keywords are allower per keyword plan. This + includes campaign negative keywords and ad group negative + keywords. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_keyword_plan_ad_group_keywords( + self, + ) -> Callable[ + [ + keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsRequest + ], + Awaitable[ + keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsResponse + ], + ]: + r"""Return a callable for the mutate keyword plan ad group + keywords method over gRPC. + + Creates, updates, or removes Keyword Plan ad group keywords. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanAdGroupKeywordError <>`__ `KeywordPlanError <>`__ + `MutateError <>`__ `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Returns: + Callable[[~.MutateKeywordPlanAdGroupKeywordsRequest], + Awaitable[~.MutateKeywordPlanAdGroupKeywordsResponse]]: + 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 "mutate_keyword_plan_ad_group_keywords" not in self._stubs: + self._stubs["mutate_keyword_plan_ad_group_keywords"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanAdGroupKeywordService/MutateKeywordPlanAdGroupKeywords", + request_serializer=keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsRequest.serialize, + response_deserializer=keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsResponse.deserialize, + ) + ) + return self._stubs["mutate_keyword_plan_ad_group_keywords"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_keyword_plan_ad_group_keywords: self._wrap_method( + self.mutate_keyword_plan_ad_group_keywords, + 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" + + +__all__ = ("KeywordPlanAdGroupKeywordServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/__init__.py b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/__init__.py new file mode 100644 index 000000000..fbdc8c222 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import KeywordPlanAdGroupServiceClient +from .async_client import KeywordPlanAdGroupServiceAsyncClient + +__all__ = ( + "KeywordPlanAdGroupServiceClient", + "KeywordPlanAdGroupServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/async_client.py b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/async_client.py new file mode 100644 index 000000000..c67ae1e00 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/async_client.py @@ -0,0 +1,451 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + keyword_plan_ad_group_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + KeywordPlanAdGroupServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import KeywordPlanAdGroupServiceClient + +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 KeywordPlanAdGroupServiceAsyncClient: + """Service to manage Keyword Plan ad groups.""" + + _client: KeywordPlanAdGroupServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = KeywordPlanAdGroupServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + KeywordPlanAdGroupServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + KeywordPlanAdGroupServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = KeywordPlanAdGroupServiceClient._DEFAULT_UNIVERSE + + keyword_plan_ad_group_path = staticmethod( + KeywordPlanAdGroupServiceClient.keyword_plan_ad_group_path + ) + parse_keyword_plan_ad_group_path = staticmethod( + KeywordPlanAdGroupServiceClient.parse_keyword_plan_ad_group_path + ) + keyword_plan_campaign_path = staticmethod( + KeywordPlanAdGroupServiceClient.keyword_plan_campaign_path + ) + parse_keyword_plan_campaign_path = staticmethod( + KeywordPlanAdGroupServiceClient.parse_keyword_plan_campaign_path + ) + common_billing_account_path = staticmethod( + KeywordPlanAdGroupServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + KeywordPlanAdGroupServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + KeywordPlanAdGroupServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + KeywordPlanAdGroupServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + KeywordPlanAdGroupServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + KeywordPlanAdGroupServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + KeywordPlanAdGroupServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + KeywordPlanAdGroupServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + KeywordPlanAdGroupServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + KeywordPlanAdGroupServiceClient.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: + KeywordPlanAdGroupServiceAsyncClient: The constructed client. + """ + return KeywordPlanAdGroupServiceClient.from_service_account_info.__func__(KeywordPlanAdGroupServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + KeywordPlanAdGroupServiceAsyncClient: The constructed client. + """ + return KeywordPlanAdGroupServiceClient.from_service_account_file.__func__(KeywordPlanAdGroupServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return KeywordPlanAdGroupServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> KeywordPlanAdGroupServiceTransport: + """Returns the transport used by the client instance. + + Returns: + KeywordPlanAdGroupServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = KeywordPlanAdGroupServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + KeywordPlanAdGroupServiceTransport, + Callable[..., KeywordPlanAdGroupServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the keyword plan ad group 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,KeywordPlanAdGroupServiceTransport,Callable[..., KeywordPlanAdGroupServiceTransport]]]): + 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 KeywordPlanAdGroupServiceTransport 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 = KeywordPlanAdGroupServiceClient( + 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.ads.googleads.v24.services.KeywordPlanAdGroupServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.KeywordPlanAdGroupService", + "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.ads.googleads.v24.services.KeywordPlanAdGroupService", + "credentialsType": None, + } + ), + ) + + async def mutate_keyword_plan_ad_groups( + self, + request: Optional[ + Union[ + keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + keyword_plan_ad_group_service.KeywordPlanAdGroupOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsResponse: + r"""Creates, updates, or removes Keyword Plan ad groups. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanAdGroupError <>`__ `KeywordPlanError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateKeywordPlanAdGroupsRequest, dict]]): + The request object. Request message for + [KeywordPlanAdGroupService.MutateKeywordPlanAdGroups][google.ads.googleads.v24.services.KeywordPlanAdGroupService.MutateKeywordPlanAdGroups]. + customer_id (:class:`str`): + Required. The ID of the customer + whose Keyword Plan ad groups are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanAdGroupOperation]`): + Required. The list of operations to + perform on individual Keyword Plan ad + groups. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateKeywordPlanAdGroupsResponse: + Response message for a Keyword Plan + ad group mutate. + + """ + # 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 = [customer_id, operations] + 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, + keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsRequest, + ): + request = ( + keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_keyword_plan_ad_groups + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "KeywordPlanAdGroupServiceAsyncClient": + 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__ = ("KeywordPlanAdGroupServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/client.py b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/client.py new file mode 100644 index 000000000..450085795 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/client.py @@ -0,0 +1,945 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + keyword_plan_ad_group_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + KeywordPlanAdGroupServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import KeywordPlanAdGroupServiceGrpcTransport +from .transports.grpc_asyncio import ( + KeywordPlanAdGroupServiceGrpcAsyncIOTransport, +) + + +class KeywordPlanAdGroupServiceClientMeta(type): + """Metaclass for the KeywordPlanAdGroupService 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[KeywordPlanAdGroupServiceTransport]] + _transport_registry["grpc"] = KeywordPlanAdGroupServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + KeywordPlanAdGroupServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[KeywordPlanAdGroupServiceTransport]: + """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 KeywordPlanAdGroupServiceClient( + metaclass=KeywordPlanAdGroupServiceClientMeta +): + """Service to manage Keyword Plan ad groups.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + KeywordPlanAdGroupServiceClient: 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: + KeywordPlanAdGroupServiceClient: 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) -> KeywordPlanAdGroupServiceTransport: + """Returns the transport used by the client instance. + + Returns: + KeywordPlanAdGroupServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def keyword_plan_ad_group_path( + customer_id: str, + keyword_plan_ad_group_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_ad_group string.""" + return "customers/{customer_id}/keywordPlanAdGroups/{keyword_plan_ad_group_id}".format( + customer_id=customer_id, + keyword_plan_ad_group_id=keyword_plan_ad_group_id, + ) + + @staticmethod + def parse_keyword_plan_ad_group_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanAdGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_campaign_path( + customer_id: str, + keyword_plan_campaign_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_campaign string.""" + return "customers/{customer_id}/keywordPlanCampaigns/{keyword_plan_campaign_id}".format( + customer_id=customer_id, + keyword_plan_campaign_id=keyword_plan_campaign_id, + ) + + @staticmethod + def parse_keyword_plan_campaign_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanCampaigns/(?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 = ( + KeywordPlanAdGroupServiceClient._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 = ( + KeywordPlanAdGroupServiceClient._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 + ): + """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 = ( + KeywordPlanAdGroupServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = KeywordPlanAdGroupServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = KeywordPlanAdGroupServiceClient._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 = KeywordPlanAdGroupServiceClient._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): + """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, + KeywordPlanAdGroupServiceTransport, + Callable[..., KeywordPlanAdGroupServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the keyword plan ad group 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,KeywordPlanAdGroupServiceTransport,Callable[..., KeywordPlanAdGroupServiceTransport]]]): + 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 KeywordPlanAdGroupServiceTransport 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, + ) = KeywordPlanAdGroupServiceClient._read_environment_variables() + self._client_cert_source = ( + KeywordPlanAdGroupServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + KeywordPlanAdGroupServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, KeywordPlanAdGroupServiceTransport + ) + if transport_provided: + # transport is a KeywordPlanAdGroupServiceTransport 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( + KeywordPlanAdGroupServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or KeywordPlanAdGroupServiceClient._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[KeywordPlanAdGroupServiceTransport], + Callable[..., KeywordPlanAdGroupServiceTransport], + ] = ( + KeywordPlanAdGroupServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., KeywordPlanAdGroupServiceTransport], 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.ads.googleads.v24.services.KeywordPlanAdGroupServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.KeywordPlanAdGroupService", + "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.ads.googleads.v24.services.KeywordPlanAdGroupService", + "credentialsType": None, + } + ), + ) + + def mutate_keyword_plan_ad_groups( + self, + request: Optional[ + Union[ + keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + keyword_plan_ad_group_service.KeywordPlanAdGroupOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsResponse: + r"""Creates, updates, or removes Keyword Plan ad groups. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanAdGroupError <>`__ `KeywordPlanError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateKeywordPlanAdGroupsRequest, dict]): + The request object. Request message for + [KeywordPlanAdGroupService.MutateKeywordPlanAdGroups][google.ads.googleads.v24.services.KeywordPlanAdGroupService.MutateKeywordPlanAdGroups]. + customer_id (str): + Required. The ID of the customer + whose Keyword Plan ad groups are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanAdGroupOperation]): + Required. The list of operations to + perform on individual Keyword Plan ad + groups. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateKeywordPlanAdGroupsResponse: + Response message for a Keyword Plan + ad group mutate. + + """ + # 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 = [customer_id, operations] + 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, + keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsRequest, + ): + request = ( + keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_keyword_plan_ad_groups + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "KeywordPlanAdGroupServiceClient": + 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() + + +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__ = ("KeywordPlanAdGroupServiceClient",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/README.rst b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/README.rst new file mode 100644 index 000000000..2d8e4bf46 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`KeywordPlanAdGroupServiceTransport` is the ABC for all transports. +- public child `KeywordPlanAdGroupServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `KeywordPlanAdGroupServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseKeywordPlanAdGroupServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `KeywordPlanAdGroupServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/__init__.py b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/__init__.py new file mode 100644 index 000000000..3de4ea345 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import KeywordPlanAdGroupServiceTransport +from .grpc import KeywordPlanAdGroupServiceGrpcTransport +from .grpc_asyncio import KeywordPlanAdGroupServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[KeywordPlanAdGroupServiceTransport]] +_transport_registry["grpc"] = KeywordPlanAdGroupServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + KeywordPlanAdGroupServiceGrpcAsyncIOTransport +) + +__all__ = ( + "KeywordPlanAdGroupServiceTransport", + "KeywordPlanAdGroupServiceGrpcTransport", + "KeywordPlanAdGroupServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/base.py b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/base.py new file mode 100644 index 000000000..089ff4a79 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + keyword_plan_ad_group_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 KeywordPlanAdGroupServiceTransport(abc.ABC): + """Abstract transport class for KeywordPlanAdGroupService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_keyword_plan_ad_groups: gapic_v1.method.wrap_method( + self.mutate_keyword_plan_ad_groups, + 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 mutate_keyword_plan_ad_groups( + self, + ) -> Callable[ + [keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsRequest], + Union[ + keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsResponse, + Awaitable[ + keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("KeywordPlanAdGroupServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/grpc.py b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/grpc.py new file mode 100644 index 000000000..23aab922c --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/grpc.py @@ -0,0 +1,396 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + keyword_plan_ad_group_service, +) +from .base import KeywordPlanAdGroupServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.KeywordPlanAdGroupService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.KeywordPlanAdGroupService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class KeywordPlanAdGroupServiceGrpcTransport( + KeywordPlanAdGroupServiceTransport +): + """gRPC backend transport for KeywordPlanAdGroupService. + + Service to manage Keyword Plan ad groups. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_keyword_plan_ad_groups( + self, + ) -> Callable[ + [keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsRequest], + keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsResponse, + ]: + r"""Return a callable for the mutate keyword plan ad groups method over gRPC. + + Creates, updates, or removes Keyword Plan ad groups. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanAdGroupError <>`__ `KeywordPlanError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Returns: + Callable[[~.MutateKeywordPlanAdGroupsRequest], + ~.MutateKeywordPlanAdGroupsResponse]: + 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 "mutate_keyword_plan_ad_groups" not in self._stubs: + self._stubs["mutate_keyword_plan_ad_groups"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanAdGroupService/MutateKeywordPlanAdGroups", + request_serializer=keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsRequest.serialize, + response_deserializer=keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsResponse.deserialize, + ) + ) + return self._stubs["mutate_keyword_plan_ad_groups"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("KeywordPlanAdGroupServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..178cceb38 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_ad_group_service/transports/grpc_asyncio.py @@ -0,0 +1,419 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + keyword_plan_ad_group_service, +) +from .base import KeywordPlanAdGroupServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.KeywordPlanAdGroupService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.KeywordPlanAdGroupService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class KeywordPlanAdGroupServiceGrpcAsyncIOTransport( + KeywordPlanAdGroupServiceTransport +): + """gRPC AsyncIO backend transport for KeywordPlanAdGroupService. + + Service to manage Keyword Plan ad groups. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_keyword_plan_ad_groups( + self, + ) -> Callable[ + [keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsRequest], + Awaitable[ + keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsResponse + ], + ]: + r"""Return a callable for the mutate keyword plan ad groups method over gRPC. + + Creates, updates, or removes Keyword Plan ad groups. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanAdGroupError <>`__ `KeywordPlanError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Returns: + Callable[[~.MutateKeywordPlanAdGroupsRequest], + Awaitable[~.MutateKeywordPlanAdGroupsResponse]]: + 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 "mutate_keyword_plan_ad_groups" not in self._stubs: + self._stubs["mutate_keyword_plan_ad_groups"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanAdGroupService/MutateKeywordPlanAdGroups", + request_serializer=keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsRequest.serialize, + response_deserializer=keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsResponse.deserialize, + ) + ) + return self._stubs["mutate_keyword_plan_ad_groups"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_keyword_plan_ad_groups: self._wrap_method( + self.mutate_keyword_plan_ad_groups, + 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" + + +__all__ = ("KeywordPlanAdGroupServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/__init__.py b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/__init__.py new file mode 100644 index 000000000..55dd28473 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import KeywordPlanCampaignKeywordServiceClient +from .async_client import KeywordPlanCampaignKeywordServiceAsyncClient + +__all__ = ( + "KeywordPlanCampaignKeywordServiceClient", + "KeywordPlanCampaignKeywordServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/async_client.py b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/async_client.py new file mode 100644 index 000000000..02add7492 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/async_client.py @@ -0,0 +1,461 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + keyword_plan_campaign_keyword_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + KeywordPlanCampaignKeywordServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import KeywordPlanCampaignKeywordServiceClient + +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 KeywordPlanCampaignKeywordServiceAsyncClient: + """Service to manage Keyword Plan campaign keywords. + KeywordPlanCampaign is required to add the campaign keywords. + Only negative keywords are supported. A maximum of 1000 negative + keywords are allowed per plan. This includes both campaign + negative keywords and ad group negative keywords. + """ + + _client: KeywordPlanCampaignKeywordServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = KeywordPlanCampaignKeywordServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + KeywordPlanCampaignKeywordServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + KeywordPlanCampaignKeywordServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ( + KeywordPlanCampaignKeywordServiceClient._DEFAULT_UNIVERSE + ) + + keyword_plan_campaign_path = staticmethod( + KeywordPlanCampaignKeywordServiceClient.keyword_plan_campaign_path + ) + parse_keyword_plan_campaign_path = staticmethod( + KeywordPlanCampaignKeywordServiceClient.parse_keyword_plan_campaign_path + ) + keyword_plan_campaign_keyword_path = staticmethod( + KeywordPlanCampaignKeywordServiceClient.keyword_plan_campaign_keyword_path + ) + parse_keyword_plan_campaign_keyword_path = staticmethod( + KeywordPlanCampaignKeywordServiceClient.parse_keyword_plan_campaign_keyword_path + ) + common_billing_account_path = staticmethod( + KeywordPlanCampaignKeywordServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + KeywordPlanCampaignKeywordServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + KeywordPlanCampaignKeywordServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + KeywordPlanCampaignKeywordServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + KeywordPlanCampaignKeywordServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + KeywordPlanCampaignKeywordServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + KeywordPlanCampaignKeywordServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + KeywordPlanCampaignKeywordServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + KeywordPlanCampaignKeywordServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + KeywordPlanCampaignKeywordServiceClient.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: + KeywordPlanCampaignKeywordServiceAsyncClient: The constructed client. + """ + return KeywordPlanCampaignKeywordServiceClient.from_service_account_info.__func__(KeywordPlanCampaignKeywordServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + KeywordPlanCampaignKeywordServiceAsyncClient: The constructed client. + """ + return KeywordPlanCampaignKeywordServiceClient.from_service_account_file.__func__(KeywordPlanCampaignKeywordServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return KeywordPlanCampaignKeywordServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> KeywordPlanCampaignKeywordServiceTransport: + """Returns the transport used by the client instance. + + Returns: + KeywordPlanCampaignKeywordServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + KeywordPlanCampaignKeywordServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + KeywordPlanCampaignKeywordServiceTransport, + Callable[..., KeywordPlanCampaignKeywordServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the keyword plan campaign keyword 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,KeywordPlanCampaignKeywordServiceTransport,Callable[..., KeywordPlanCampaignKeywordServiceTransport]]]): + 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 KeywordPlanCampaignKeywordServiceTransport 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 = KeywordPlanCampaignKeywordServiceClient( + 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.ads.googleads.v24.services.KeywordPlanCampaignKeywordServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.KeywordPlanCampaignKeywordService", + "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.ads.googleads.v24.services.KeywordPlanCampaignKeywordService", + "credentialsType": None, + } + ), + ) + + async def mutate_keyword_plan_campaign_keywords( + self, + request: Optional[ + Union[ + keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + keyword_plan_campaign_keyword_service.KeywordPlanCampaignKeywordOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsResponse + ): + r"""Creates, updates, or removes Keyword Plan campaign keywords. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanAdGroupKeywordError <>`__ + `KeywordPlanCampaignKeywordError <>`__ `QuotaError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateKeywordPlanCampaignKeywordsRequest, dict]]): + The request object. Request message for + [KeywordPlanCampaignKeywordService.MutateKeywordPlanCampaignKeywords][google.ads.googleads.v24.services.KeywordPlanCampaignKeywordService.MutateKeywordPlanCampaignKeywords]. + customer_id (:class:`str`): + Required. The ID of the customer + whose campaign keywords are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanCampaignKeywordOperation]`): + Required. The list of operations to + perform on individual Keyword Plan + campaign keywords. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateKeywordPlanCampaignKeywordsResponse: + Response message for a Keyword Plan + campaign keyword mutate. + + """ + # 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 = [customer_id, operations] + 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, + keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsRequest, + ): + request = keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_keyword_plan_campaign_keywords + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__( + self, + ) -> "KeywordPlanCampaignKeywordServiceAsyncClient": + 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__ = ("KeywordPlanCampaignKeywordServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/client.py b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/client.py new file mode 100644 index 000000000..d3906879f --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/client.py @@ -0,0 +1,958 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + keyword_plan_campaign_keyword_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + KeywordPlanCampaignKeywordServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import KeywordPlanCampaignKeywordServiceGrpcTransport +from .transports.grpc_asyncio import ( + KeywordPlanCampaignKeywordServiceGrpcAsyncIOTransport, +) + + +class KeywordPlanCampaignKeywordServiceClientMeta(type): + """Metaclass for the KeywordPlanCampaignKeywordService 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[KeywordPlanCampaignKeywordServiceTransport]] + _transport_registry["grpc"] = KeywordPlanCampaignKeywordServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + KeywordPlanCampaignKeywordServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[KeywordPlanCampaignKeywordServiceTransport]: + """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 KeywordPlanCampaignKeywordServiceClient( + metaclass=KeywordPlanCampaignKeywordServiceClientMeta +): + """Service to manage Keyword Plan campaign keywords. + KeywordPlanCampaign is required to add the campaign keywords. + Only negative keywords are supported. A maximum of 1000 negative + keywords are allowed per plan. This includes both campaign + negative keywords and ad group negative keywords. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + KeywordPlanCampaignKeywordServiceClient: 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: + KeywordPlanCampaignKeywordServiceClient: 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) -> KeywordPlanCampaignKeywordServiceTransport: + """Returns the transport used by the client instance. + + Returns: + KeywordPlanCampaignKeywordServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def keyword_plan_campaign_path( + customer_id: str, + keyword_plan_campaign_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_campaign string.""" + return "customers/{customer_id}/keywordPlanCampaigns/{keyword_plan_campaign_id}".format( + customer_id=customer_id, + keyword_plan_campaign_id=keyword_plan_campaign_id, + ) + + @staticmethod + def parse_keyword_plan_campaign_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanCampaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_campaign_keyword_path( + customer_id: str, + keyword_plan_campaign_keyword_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_campaign_keyword string.""" + return "customers/{customer_id}/keywordPlanCampaignKeywords/{keyword_plan_campaign_keyword_id}".format( + customer_id=customer_id, + keyword_plan_campaign_keyword_id=keyword_plan_campaign_keyword_id, + ) + + @staticmethod + def parse_keyword_plan_campaign_keyword_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_campaign_keyword path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanCampaignKeywords/(?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 = ( + KeywordPlanCampaignKeywordServiceClient._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 = ( + KeywordPlanCampaignKeywordServiceClient._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 + ): + """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 = ( + KeywordPlanCampaignKeywordServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + KeywordPlanCampaignKeywordServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = KeywordPlanCampaignKeywordServiceClient._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 = ( + KeywordPlanCampaignKeywordServiceClient._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): + """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, + KeywordPlanCampaignKeywordServiceTransport, + Callable[..., KeywordPlanCampaignKeywordServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the keyword plan campaign keyword 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,KeywordPlanCampaignKeywordServiceTransport,Callable[..., KeywordPlanCampaignKeywordServiceTransport]]]): + 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 KeywordPlanCampaignKeywordServiceTransport 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, + ) = ( + KeywordPlanCampaignKeywordServiceClient._read_environment_variables() + ) + self._client_cert_source = ( + KeywordPlanCampaignKeywordServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + KeywordPlanCampaignKeywordServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, KeywordPlanCampaignKeywordServiceTransport + ) + if transport_provided: + # transport is a KeywordPlanCampaignKeywordServiceTransport 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( + KeywordPlanCampaignKeywordServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or KeywordPlanCampaignKeywordServiceClient._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[KeywordPlanCampaignKeywordServiceTransport], + Callable[..., KeywordPlanCampaignKeywordServiceTransport], + ] = ( + KeywordPlanCampaignKeywordServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., KeywordPlanCampaignKeywordServiceTransport], + 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.ads.googleads.v24.services.KeywordPlanCampaignKeywordServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.KeywordPlanCampaignKeywordService", + "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.ads.googleads.v24.services.KeywordPlanCampaignKeywordService", + "credentialsType": None, + } + ), + ) + + def mutate_keyword_plan_campaign_keywords( + self, + request: Optional[ + Union[ + keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + keyword_plan_campaign_keyword_service.KeywordPlanCampaignKeywordOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsResponse + ): + r"""Creates, updates, or removes Keyword Plan campaign keywords. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanAdGroupKeywordError <>`__ + `KeywordPlanCampaignKeywordError <>`__ `QuotaError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateKeywordPlanCampaignKeywordsRequest, dict]): + The request object. Request message for + [KeywordPlanCampaignKeywordService.MutateKeywordPlanCampaignKeywords][google.ads.googleads.v24.services.KeywordPlanCampaignKeywordService.MutateKeywordPlanCampaignKeywords]. + customer_id (str): + Required. The ID of the customer + whose campaign keywords are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanCampaignKeywordOperation]): + Required. The list of operations to + perform on individual Keyword Plan + campaign keywords. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateKeywordPlanCampaignKeywordsResponse: + Response message for a Keyword Plan + campaign keyword mutate. + + """ + # 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 = [customer_id, operations] + 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, + keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsRequest, + ): + request = keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_keyword_plan_campaign_keywords + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "KeywordPlanCampaignKeywordServiceClient": + 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() + + +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__ = ("KeywordPlanCampaignKeywordServiceClient",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/README.rst b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/README.rst new file mode 100644 index 000000000..701b3825a --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`KeywordPlanCampaignKeywordServiceTransport` is the ABC for all transports. +- public child `KeywordPlanCampaignKeywordServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `KeywordPlanCampaignKeywordServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseKeywordPlanCampaignKeywordServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `KeywordPlanCampaignKeywordServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/__init__.py b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/__init__.py new file mode 100644 index 000000000..1d0894be9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import KeywordPlanCampaignKeywordServiceTransport +from .grpc import KeywordPlanCampaignKeywordServiceGrpcTransport +from .grpc_asyncio import KeywordPlanCampaignKeywordServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[KeywordPlanCampaignKeywordServiceTransport]] +_transport_registry["grpc"] = KeywordPlanCampaignKeywordServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + KeywordPlanCampaignKeywordServiceGrpcAsyncIOTransport +) + +__all__ = ( + "KeywordPlanCampaignKeywordServiceTransport", + "KeywordPlanCampaignKeywordServiceGrpcTransport", + "KeywordPlanCampaignKeywordServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/base.py b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/base.py new file mode 100644 index 000000000..ed1b7634d --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + keyword_plan_campaign_keyword_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 KeywordPlanCampaignKeywordServiceTransport(abc.ABC): + """Abstract transport class for KeywordPlanCampaignKeywordService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_keyword_plan_campaign_keywords: gapic_v1.method.wrap_method( + self.mutate_keyword_plan_campaign_keywords, + 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 mutate_keyword_plan_campaign_keywords( + self, + ) -> Callable[ + [ + keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsRequest + ], + Union[ + keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsResponse, + Awaitable[ + keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("KeywordPlanCampaignKeywordServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/grpc.py b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/grpc.py new file mode 100644 index 000000000..f22114ce0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/grpc.py @@ -0,0 +1,405 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + keyword_plan_campaign_keyword_service, +) +from .base import ( + KeywordPlanCampaignKeywordServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.KeywordPlanCampaignKeywordService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.KeywordPlanCampaignKeywordService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class KeywordPlanCampaignKeywordServiceGrpcTransport( + KeywordPlanCampaignKeywordServiceTransport +): + """gRPC backend transport for KeywordPlanCampaignKeywordService. + + Service to manage Keyword Plan campaign keywords. + KeywordPlanCampaign is required to add the campaign keywords. + Only negative keywords are supported. A maximum of 1000 negative + keywords are allowed per plan. This includes both campaign + negative keywords and ad group negative keywords. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_keyword_plan_campaign_keywords( + self, + ) -> Callable[ + [ + keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsRequest + ], + keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsResponse, + ]: + r"""Return a callable for the mutate keyword plan campaign + keywords method over gRPC. + + Creates, updates, or removes Keyword Plan campaign keywords. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanAdGroupKeywordError <>`__ + `KeywordPlanCampaignKeywordError <>`__ `QuotaError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + + Returns: + Callable[[~.MutateKeywordPlanCampaignKeywordsRequest], + ~.MutateKeywordPlanCampaignKeywordsResponse]: + 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 "mutate_keyword_plan_campaign_keywords" not in self._stubs: + self._stubs["mutate_keyword_plan_campaign_keywords"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanCampaignKeywordService/MutateKeywordPlanCampaignKeywords", + request_serializer=keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsRequest.serialize, + response_deserializer=keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsResponse.deserialize, + ) + ) + return self._stubs["mutate_keyword_plan_campaign_keywords"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("KeywordPlanCampaignKeywordServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..fdec21afd --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_keyword_service/transports/grpc_asyncio.py @@ -0,0 +1,428 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + keyword_plan_campaign_keyword_service, +) +from .base import ( + KeywordPlanCampaignKeywordServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.KeywordPlanCampaignKeywordService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.KeywordPlanCampaignKeywordService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class KeywordPlanCampaignKeywordServiceGrpcAsyncIOTransport( + KeywordPlanCampaignKeywordServiceTransport +): + """gRPC AsyncIO backend transport for KeywordPlanCampaignKeywordService. + + Service to manage Keyword Plan campaign keywords. + KeywordPlanCampaign is required to add the campaign keywords. + Only negative keywords are supported. A maximum of 1000 negative + keywords are allowed per plan. This includes both campaign + negative keywords and ad group negative keywords. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_keyword_plan_campaign_keywords( + self, + ) -> Callable[ + [ + keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsRequest + ], + Awaitable[ + keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsResponse + ], + ]: + r"""Return a callable for the mutate keyword plan campaign + keywords method over gRPC. + + Creates, updates, or removes Keyword Plan campaign keywords. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanAdGroupKeywordError <>`__ + `KeywordPlanCampaignKeywordError <>`__ `QuotaError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + + Returns: + Callable[[~.MutateKeywordPlanCampaignKeywordsRequest], + Awaitable[~.MutateKeywordPlanCampaignKeywordsResponse]]: + 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 "mutate_keyword_plan_campaign_keywords" not in self._stubs: + self._stubs["mutate_keyword_plan_campaign_keywords"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanCampaignKeywordService/MutateKeywordPlanCampaignKeywords", + request_serializer=keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsRequest.serialize, + response_deserializer=keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsResponse.deserialize, + ) + ) + return self._stubs["mutate_keyword_plan_campaign_keywords"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_keyword_plan_campaign_keywords: self._wrap_method( + self.mutate_keyword_plan_campaign_keywords, + 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" + + +__all__ = ("KeywordPlanCampaignKeywordServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/__init__.py b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/__init__.py new file mode 100644 index 000000000..cdf523d7d --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import KeywordPlanCampaignServiceClient +from .async_client import KeywordPlanCampaignServiceAsyncClient + +__all__ = ( + "KeywordPlanCampaignServiceClient", + "KeywordPlanCampaignServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/async_client.py b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/async_client.py new file mode 100644 index 000000000..02088d6cd --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/async_client.py @@ -0,0 +1,463 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + keyword_plan_campaign_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + KeywordPlanCampaignServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import KeywordPlanCampaignServiceClient + +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 KeywordPlanCampaignServiceAsyncClient: + """Service to manage Keyword Plan campaigns.""" + + _client: KeywordPlanCampaignServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = KeywordPlanCampaignServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + KeywordPlanCampaignServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + KeywordPlanCampaignServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = KeywordPlanCampaignServiceClient._DEFAULT_UNIVERSE + + geo_target_constant_path = staticmethod( + KeywordPlanCampaignServiceClient.geo_target_constant_path + ) + parse_geo_target_constant_path = staticmethod( + KeywordPlanCampaignServiceClient.parse_geo_target_constant_path + ) + keyword_plan_path = staticmethod( + KeywordPlanCampaignServiceClient.keyword_plan_path + ) + parse_keyword_plan_path = staticmethod( + KeywordPlanCampaignServiceClient.parse_keyword_plan_path + ) + keyword_plan_campaign_path = staticmethod( + KeywordPlanCampaignServiceClient.keyword_plan_campaign_path + ) + parse_keyword_plan_campaign_path = staticmethod( + KeywordPlanCampaignServiceClient.parse_keyword_plan_campaign_path + ) + language_constant_path = staticmethod( + KeywordPlanCampaignServiceClient.language_constant_path + ) + parse_language_constant_path = staticmethod( + KeywordPlanCampaignServiceClient.parse_language_constant_path + ) + common_billing_account_path = staticmethod( + KeywordPlanCampaignServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + KeywordPlanCampaignServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + KeywordPlanCampaignServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + KeywordPlanCampaignServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + KeywordPlanCampaignServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + KeywordPlanCampaignServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + KeywordPlanCampaignServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + KeywordPlanCampaignServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + KeywordPlanCampaignServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + KeywordPlanCampaignServiceClient.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: + KeywordPlanCampaignServiceAsyncClient: The constructed client. + """ + return KeywordPlanCampaignServiceClient.from_service_account_info.__func__(KeywordPlanCampaignServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + KeywordPlanCampaignServiceAsyncClient: The constructed client. + """ + return KeywordPlanCampaignServiceClient.from_service_account_file.__func__(KeywordPlanCampaignServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return KeywordPlanCampaignServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> KeywordPlanCampaignServiceTransport: + """Returns the transport used by the client instance. + + Returns: + KeywordPlanCampaignServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = KeywordPlanCampaignServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + KeywordPlanCampaignServiceTransport, + Callable[..., KeywordPlanCampaignServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the keyword plan campaign 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,KeywordPlanCampaignServiceTransport,Callable[..., KeywordPlanCampaignServiceTransport]]]): + 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 KeywordPlanCampaignServiceTransport 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 = KeywordPlanCampaignServiceClient( + 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.ads.googleads.v24.services.KeywordPlanCampaignServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.KeywordPlanCampaignService", + "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.ads.googleads.v24.services.KeywordPlanCampaignService", + "credentialsType": None, + } + ), + ) + + async def mutate_keyword_plan_campaigns( + self, + request: Optional[ + Union[ + keyword_plan_campaign_service.MutateKeywordPlanCampaignsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + keyword_plan_campaign_service.KeywordPlanCampaignOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> keyword_plan_campaign_service.MutateKeywordPlanCampaignsResponse: + r"""Creates, updates, or removes Keyword Plan campaigns. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanCampaignError <>`__ `KeywordPlanError <>`__ + `ListOperationError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateKeywordPlanCampaignsRequest, dict]]): + The request object. Request message for + [KeywordPlanCampaignService.MutateKeywordPlanCampaigns][google.ads.googleads.v24.services.KeywordPlanCampaignService.MutateKeywordPlanCampaigns]. + customer_id (:class:`str`): + Required. The ID of the customer + whose Keyword Plan campaigns are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanCampaignOperation]`): + Required. The list of operations to + perform on individual Keyword Plan + campaigns. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateKeywordPlanCampaignsResponse: + Response message for a Keyword Plan + campaign mutate. + + """ + # 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 = [customer_id, operations] + 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, + keyword_plan_campaign_service.MutateKeywordPlanCampaignsRequest, + ): + request = ( + keyword_plan_campaign_service.MutateKeywordPlanCampaignsRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_keyword_plan_campaigns + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "KeywordPlanCampaignServiceAsyncClient": + 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__ = ("KeywordPlanCampaignServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/client.py b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/client.py new file mode 100644 index 000000000..a712707eb --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/client.py @@ -0,0 +1,978 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + keyword_plan_campaign_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + KeywordPlanCampaignServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import KeywordPlanCampaignServiceGrpcTransport +from .transports.grpc_asyncio import ( + KeywordPlanCampaignServiceGrpcAsyncIOTransport, +) + + +class KeywordPlanCampaignServiceClientMeta(type): + """Metaclass for the KeywordPlanCampaignService 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[KeywordPlanCampaignServiceTransport]] + _transport_registry["grpc"] = KeywordPlanCampaignServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + KeywordPlanCampaignServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[KeywordPlanCampaignServiceTransport]: + """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 KeywordPlanCampaignServiceClient( + metaclass=KeywordPlanCampaignServiceClientMeta +): + """Service to manage Keyword Plan campaigns.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + KeywordPlanCampaignServiceClient: 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: + KeywordPlanCampaignServiceClient: 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) -> KeywordPlanCampaignServiceTransport: + """Returns the transport used by the client instance. + + Returns: + KeywordPlanCampaignServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def geo_target_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified geo_target_constant string.""" + return "geoTargetConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_geo_target_constant_path(path: str) -> Dict[str, str]: + """Parses a geo_target_constant path into its component segments.""" + m = re.match(r"^geoTargetConstants/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_path( + customer_id: str, + keyword_plan_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan string.""" + return "customers/{customer_id}/keywordPlans/{keyword_plan_id}".format( + customer_id=customer_id, + keyword_plan_id=keyword_plan_id, + ) + + @staticmethod + def parse_keyword_plan_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlans/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_plan_campaign_path( + customer_id: str, + keyword_plan_campaign_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan_campaign string.""" + return "customers/{customer_id}/keywordPlanCampaigns/{keyword_plan_campaign_id}".format( + customer_id=customer_id, + keyword_plan_campaign_id=keyword_plan_campaign_id, + ) + + @staticmethod + def parse_keyword_plan_campaign_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan_campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlanCampaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def language_constant_path( + criterion_id: str, + ) -> str: + """Returns a fully-qualified language_constant string.""" + return "languageConstants/{criterion_id}".format( + criterion_id=criterion_id, + ) + + @staticmethod + def parse_language_constant_path(path: str) -> Dict[str, str]: + """Parses a language_constant path into its component segments.""" + m = re.match(r"^languageConstants/(?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 = ( + KeywordPlanCampaignServiceClient._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 = ( + KeywordPlanCampaignServiceClient._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 + ): + """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 = ( + KeywordPlanCampaignServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + KeywordPlanCampaignServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = KeywordPlanCampaignServiceClient._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 = KeywordPlanCampaignServiceClient._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): + """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, + KeywordPlanCampaignServiceTransport, + Callable[..., KeywordPlanCampaignServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the keyword plan campaign 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,KeywordPlanCampaignServiceTransport,Callable[..., KeywordPlanCampaignServiceTransport]]]): + 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 KeywordPlanCampaignServiceTransport 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, + ) = KeywordPlanCampaignServiceClient._read_environment_variables() + self._client_cert_source = ( + KeywordPlanCampaignServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + KeywordPlanCampaignServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, KeywordPlanCampaignServiceTransport + ) + if transport_provided: + # transport is a KeywordPlanCampaignServiceTransport 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( + KeywordPlanCampaignServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or KeywordPlanCampaignServiceClient._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[KeywordPlanCampaignServiceTransport], + Callable[..., KeywordPlanCampaignServiceTransport], + ] = ( + KeywordPlanCampaignServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., KeywordPlanCampaignServiceTransport], + 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.ads.googleads.v24.services.KeywordPlanCampaignServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.KeywordPlanCampaignService", + "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.ads.googleads.v24.services.KeywordPlanCampaignService", + "credentialsType": None, + } + ), + ) + + def mutate_keyword_plan_campaigns( + self, + request: Optional[ + Union[ + keyword_plan_campaign_service.MutateKeywordPlanCampaignsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + keyword_plan_campaign_service.KeywordPlanCampaignOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> keyword_plan_campaign_service.MutateKeywordPlanCampaignsResponse: + r"""Creates, updates, or removes Keyword Plan campaigns. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanCampaignError <>`__ `KeywordPlanError <>`__ + `ListOperationError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateKeywordPlanCampaignsRequest, dict]): + The request object. Request message for + [KeywordPlanCampaignService.MutateKeywordPlanCampaigns][google.ads.googleads.v24.services.KeywordPlanCampaignService.MutateKeywordPlanCampaigns]. + customer_id (str): + Required. The ID of the customer + whose Keyword Plan campaigns are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanCampaignOperation]): + Required. The list of operations to + perform on individual Keyword Plan + campaigns. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateKeywordPlanCampaignsResponse: + Response message for a Keyword Plan + campaign mutate. + + """ + # 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 = [customer_id, operations] + 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, + keyword_plan_campaign_service.MutateKeywordPlanCampaignsRequest, + ): + request = ( + keyword_plan_campaign_service.MutateKeywordPlanCampaignsRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_keyword_plan_campaigns + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "KeywordPlanCampaignServiceClient": + 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() + + +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__ = ("KeywordPlanCampaignServiceClient",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/README.rst b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/README.rst new file mode 100644 index 000000000..21e920bb5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`KeywordPlanCampaignServiceTransport` is the ABC for all transports. +- public child `KeywordPlanCampaignServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `KeywordPlanCampaignServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseKeywordPlanCampaignServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `KeywordPlanCampaignServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/__init__.py b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/__init__.py new file mode 100644 index 000000000..c831cdde7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import KeywordPlanCampaignServiceTransport +from .grpc import KeywordPlanCampaignServiceGrpcTransport +from .grpc_asyncio import KeywordPlanCampaignServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[KeywordPlanCampaignServiceTransport]] +_transport_registry["grpc"] = KeywordPlanCampaignServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + KeywordPlanCampaignServiceGrpcAsyncIOTransport +) + +__all__ = ( + "KeywordPlanCampaignServiceTransport", + "KeywordPlanCampaignServiceGrpcTransport", + "KeywordPlanCampaignServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/base.py b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/base.py new file mode 100644 index 000000000..d19ef51ff --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + keyword_plan_campaign_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 KeywordPlanCampaignServiceTransport(abc.ABC): + """Abstract transport class for KeywordPlanCampaignService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_keyword_plan_campaigns: gapic_v1.method.wrap_method( + self.mutate_keyword_plan_campaigns, + 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 mutate_keyword_plan_campaigns( + self, + ) -> Callable[ + [keyword_plan_campaign_service.MutateKeywordPlanCampaignsRequest], + Union[ + keyword_plan_campaign_service.MutateKeywordPlanCampaignsResponse, + Awaitable[ + keyword_plan_campaign_service.MutateKeywordPlanCampaignsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("KeywordPlanCampaignServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/grpc.py b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/grpc.py new file mode 100644 index 000000000..9d9aa2eeb --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/grpc.py @@ -0,0 +1,396 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + keyword_plan_campaign_service, +) +from .base import KeywordPlanCampaignServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.KeywordPlanCampaignService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.KeywordPlanCampaignService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class KeywordPlanCampaignServiceGrpcTransport( + KeywordPlanCampaignServiceTransport +): + """gRPC backend transport for KeywordPlanCampaignService. + + Service to manage Keyword Plan campaigns. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_keyword_plan_campaigns( + self, + ) -> Callable[ + [keyword_plan_campaign_service.MutateKeywordPlanCampaignsRequest], + keyword_plan_campaign_service.MutateKeywordPlanCampaignsResponse, + ]: + r"""Return a callable for the mutate keyword plan campaigns method over gRPC. + + Creates, updates, or removes Keyword Plan campaigns. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanCampaignError <>`__ `KeywordPlanError <>`__ + `ListOperationError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Returns: + Callable[[~.MutateKeywordPlanCampaignsRequest], + ~.MutateKeywordPlanCampaignsResponse]: + 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 "mutate_keyword_plan_campaigns" not in self._stubs: + self._stubs["mutate_keyword_plan_campaigns"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanCampaignService/MutateKeywordPlanCampaigns", + request_serializer=keyword_plan_campaign_service.MutateKeywordPlanCampaignsRequest.serialize, + response_deserializer=keyword_plan_campaign_service.MutateKeywordPlanCampaignsResponse.deserialize, + ) + ) + return self._stubs["mutate_keyword_plan_campaigns"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("KeywordPlanCampaignServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..cfa9711b6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_campaign_service/transports/grpc_asyncio.py @@ -0,0 +1,419 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + keyword_plan_campaign_service, +) +from .base import KeywordPlanCampaignServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.KeywordPlanCampaignService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.KeywordPlanCampaignService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class KeywordPlanCampaignServiceGrpcAsyncIOTransport( + KeywordPlanCampaignServiceTransport +): + """gRPC AsyncIO backend transport for KeywordPlanCampaignService. + + Service to manage Keyword Plan campaigns. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_keyword_plan_campaigns( + self, + ) -> Callable[ + [keyword_plan_campaign_service.MutateKeywordPlanCampaignsRequest], + Awaitable[ + keyword_plan_campaign_service.MutateKeywordPlanCampaignsResponse + ], + ]: + r"""Return a callable for the mutate keyword plan campaigns method over gRPC. + + Creates, updates, or removes Keyword Plan campaigns. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanCampaignError <>`__ `KeywordPlanError <>`__ + `ListOperationError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ + + Returns: + Callable[[~.MutateKeywordPlanCampaignsRequest], + Awaitable[~.MutateKeywordPlanCampaignsResponse]]: + 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 "mutate_keyword_plan_campaigns" not in self._stubs: + self._stubs["mutate_keyword_plan_campaigns"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanCampaignService/MutateKeywordPlanCampaigns", + request_serializer=keyword_plan_campaign_service.MutateKeywordPlanCampaignsRequest.serialize, + response_deserializer=keyword_plan_campaign_service.MutateKeywordPlanCampaignsResponse.deserialize, + ) + ) + return self._stubs["mutate_keyword_plan_campaigns"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_keyword_plan_campaigns: self._wrap_method( + self.mutate_keyword_plan_campaigns, + 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" + + +__all__ = ("KeywordPlanCampaignServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_idea_service/__init__.py b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/__init__.py new file mode 100644 index 000000000..466f4fd08 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import KeywordPlanIdeaServiceClient +from .async_client import KeywordPlanIdeaServiceAsyncClient + +__all__ = ( + "KeywordPlanIdeaServiceClient", + "KeywordPlanIdeaServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_idea_service/async_client.py b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/async_client.py new file mode 100644 index 000000000..199321f11 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/async_client.py @@ -0,0 +1,701 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.services.keyword_plan_idea_service import ( + pagers, +) +from google.ads.googleads.v24.services.types import keyword_plan_idea_service +from .transports.base import ( + KeywordPlanIdeaServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import KeywordPlanIdeaServiceClient + +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 KeywordPlanIdeaServiceAsyncClient: + """Service to generate keyword ideas.""" + + _client: KeywordPlanIdeaServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = KeywordPlanIdeaServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = KeywordPlanIdeaServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + KeywordPlanIdeaServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = KeywordPlanIdeaServiceClient._DEFAULT_UNIVERSE + + common_billing_account_path = staticmethod( + KeywordPlanIdeaServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + KeywordPlanIdeaServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + KeywordPlanIdeaServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + KeywordPlanIdeaServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + KeywordPlanIdeaServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + KeywordPlanIdeaServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + KeywordPlanIdeaServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + KeywordPlanIdeaServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + KeywordPlanIdeaServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + KeywordPlanIdeaServiceClient.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: + KeywordPlanIdeaServiceAsyncClient: The constructed client. + """ + return KeywordPlanIdeaServiceClient.from_service_account_info.__func__(KeywordPlanIdeaServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + KeywordPlanIdeaServiceAsyncClient: The constructed client. + """ + return KeywordPlanIdeaServiceClient.from_service_account_file.__func__(KeywordPlanIdeaServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return KeywordPlanIdeaServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> KeywordPlanIdeaServiceTransport: + """Returns the transport used by the client instance. + + Returns: + KeywordPlanIdeaServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = KeywordPlanIdeaServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + KeywordPlanIdeaServiceTransport, + Callable[..., KeywordPlanIdeaServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the keyword plan idea 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,KeywordPlanIdeaServiceTransport,Callable[..., KeywordPlanIdeaServiceTransport]]]): + 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 KeywordPlanIdeaServiceTransport 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 = KeywordPlanIdeaServiceClient( + 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.ads.googleads.v24.services.KeywordPlanIdeaServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.KeywordPlanIdeaService", + "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.ads.googleads.v24.services.KeywordPlanIdeaService", + "credentialsType": None, + } + ), + ) + + async def generate_keyword_ideas( + self, + request: Optional[ + Union[keyword_plan_idea_service.GenerateKeywordIdeasRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> pagers.GenerateKeywordIdeasAsyncPager: + r"""Returns a list of keyword ideas. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanIdeaError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateKeywordIdeasRequest, dict]]): + The request object. Request message for + [KeywordPlanIdeaService.GenerateKeywordIdeas][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordIdeas]. + 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.googleads.v24.services.services.keyword_plan_idea_service.pagers.GenerateKeywordIdeasAsyncPager: + Response message for + [KeywordPlanIdeaService.GenerateKeywordIdeas][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordIdeas]. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # 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, keyword_plan_idea_service.GenerateKeywordIdeasRequest + ): + request = keyword_plan_idea_service.GenerateKeywordIdeasRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_keyword_ideas + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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.GenerateKeywordIdeasAsyncPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def generate_keyword_historical_metrics( + self, + request: Optional[ + Union[ + keyword_plan_idea_service.GenerateKeywordHistoricalMetricsRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> keyword_plan_idea_service.GenerateKeywordHistoricalMetricsResponse: + r"""Returns a list of keyword historical metrics. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateKeywordHistoricalMetricsRequest, dict]]): + The request object. Request message for + [KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics]. + 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.googleads.v24.services.types.GenerateKeywordHistoricalMetricsResponse: + Response message for + [KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics]. + + """ + # 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, + keyword_plan_idea_service.GenerateKeywordHistoricalMetricsRequest, + ): + request = keyword_plan_idea_service.GenerateKeywordHistoricalMetricsRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_keyword_historical_metrics + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_ad_group_themes( + self, + request: Optional[ + Union[keyword_plan_idea_service.GenerateAdGroupThemesRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + keywords: Optional[MutableSequence[str]] = None, + ad_groups: Optional[MutableSequence[str]] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> keyword_plan_idea_service.GenerateAdGroupThemesResponse: + r"""Returns a list of suggested AdGroups and suggested modifications + (text, match type) for the given keywords. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateAdGroupThemesRequest, dict]]): + The request object. Request message for + [KeywordPlanIdeaService.GenerateAdGroupThemes][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateAdGroupThemes]. + customer_id (:class:`str`): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + keywords (:class:`MutableSequence[str]`): + Required. A list of keywords to group + into the provided AdGroups. + + This corresponds to the ``keywords`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + ad_groups (:class:`MutableSequence[str]`): + Required. A list of resource names of AdGroups to group + keywords into. Resource name format: + ``customers/{customer_id}/adGroups/{ad_group_id}`` + + This corresponds to the ``ad_groups`` 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.ads.googleads.v24.services.types.GenerateAdGroupThemesResponse: + Response message for + [KeywordPlanIdeaService.GenerateAdGroupThemes][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateAdGroupThemes]. + + """ + # 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 = [customer_id, keywords, ad_groups] + 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, keyword_plan_idea_service.GenerateAdGroupThemesRequest + ): + request = keyword_plan_idea_service.GenerateAdGroupThemesRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if keywords: + request.keywords.extend(keywords) + if ad_groups: + request.ad_groups.extend(ad_groups) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_ad_group_themes + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_keyword_forecast_metrics( + self, + request: Optional[ + Union[ + keyword_plan_idea_service.GenerateKeywordForecastMetricsRequest, + dict, + ] + ] = None, + *, + campaign: Optional[keyword_plan_idea_service.CampaignToForecast] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> keyword_plan_idea_service.GenerateKeywordForecastMetricsResponse: + r"""Returns metrics (such as impressions, clicks, total cost) of a + keyword forecast for the given campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateKeywordForecastMetricsRequest, dict]]): + The request object. Request message for + [KeywordPlanIdeaService.GenerateKeywordForecastMetrics][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordForecastMetrics]. + campaign (:class:`google.ads.googleads.v24.services.types.CampaignToForecast`): + Required. The campaign used in the + forecast. + + This corresponds to the ``campaign`` 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.ads.googleads.v24.services.types.GenerateKeywordForecastMetricsResponse: + Response message for + [KeywordPlanIdeaService.GenerateKeywordForecastMetrics][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordForecastMetrics]. + + """ + # 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 = [campaign] + 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, + keyword_plan_idea_service.GenerateKeywordForecastMetricsRequest, + ): + request = ( + keyword_plan_idea_service.GenerateKeywordForecastMetricsRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if campaign is not None: + request.campaign = campaign + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_keyword_forecast_metrics + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "KeywordPlanIdeaServiceAsyncClient": + 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__ = ("KeywordPlanIdeaServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_idea_service/client.py b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/client.py new file mode 100644 index 000000000..8226907b6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/client.py @@ -0,0 +1,1162 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.services.keyword_plan_idea_service import ( + pagers, +) +from google.ads.googleads.v24.services.types import keyword_plan_idea_service +from .transports.base import ( + KeywordPlanIdeaServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import KeywordPlanIdeaServiceGrpcTransport +from .transports.grpc_asyncio import KeywordPlanIdeaServiceGrpcAsyncIOTransport + + +class KeywordPlanIdeaServiceClientMeta(type): + """Metaclass for the KeywordPlanIdeaService 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[KeywordPlanIdeaServiceTransport]] + _transport_registry["grpc"] = KeywordPlanIdeaServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + KeywordPlanIdeaServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[KeywordPlanIdeaServiceTransport]: + """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 KeywordPlanIdeaServiceClient(metaclass=KeywordPlanIdeaServiceClientMeta): + """Service to generate keyword ideas.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + KeywordPlanIdeaServiceClient: 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: + KeywordPlanIdeaServiceClient: 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) -> KeywordPlanIdeaServiceTransport: + """Returns the transport used by the client instance. + + Returns: + KeywordPlanIdeaServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @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 = ( + KeywordPlanIdeaServiceClient._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 = ( + KeywordPlanIdeaServiceClient._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 + ): + """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 = KeywordPlanIdeaServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = KeywordPlanIdeaServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + KeywordPlanIdeaServiceClient._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 = KeywordPlanIdeaServiceClient._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): + """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, + KeywordPlanIdeaServiceTransport, + Callable[..., KeywordPlanIdeaServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the keyword plan idea 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,KeywordPlanIdeaServiceTransport,Callable[..., KeywordPlanIdeaServiceTransport]]]): + 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 KeywordPlanIdeaServiceTransport 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, + ) = KeywordPlanIdeaServiceClient._read_environment_variables() + self._client_cert_source = ( + KeywordPlanIdeaServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + KeywordPlanIdeaServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, KeywordPlanIdeaServiceTransport + ) + if transport_provided: + # transport is a KeywordPlanIdeaServiceTransport 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(KeywordPlanIdeaServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or KeywordPlanIdeaServiceClient._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[KeywordPlanIdeaServiceTransport], + Callable[..., KeywordPlanIdeaServiceTransport], + ] = ( + KeywordPlanIdeaServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., KeywordPlanIdeaServiceTransport], 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.ads.googleads.v24.services.KeywordPlanIdeaServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.KeywordPlanIdeaService", + "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.ads.googleads.v24.services.KeywordPlanIdeaService", + "credentialsType": None, + } + ), + ) + + def generate_keyword_ideas( + self, + request: Optional[ + Union[keyword_plan_idea_service.GenerateKeywordIdeasRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> pagers.GenerateKeywordIdeasPager: + r"""Returns a list of keyword ideas. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanIdeaError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateKeywordIdeasRequest, dict]): + The request object. Request message for + [KeywordPlanIdeaService.GenerateKeywordIdeas][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordIdeas]. + 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.googleads.v24.services.services.keyword_plan_idea_service.pagers.GenerateKeywordIdeasPager: + Response message for + [KeywordPlanIdeaService.GenerateKeywordIdeas][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordIdeas]. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # 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, keyword_plan_idea_service.GenerateKeywordIdeasRequest + ): + request = keyword_plan_idea_service.GenerateKeywordIdeasRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_keyword_ideas + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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.GenerateKeywordIdeasPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def generate_keyword_historical_metrics( + self, + request: Optional[ + Union[ + keyword_plan_idea_service.GenerateKeywordHistoricalMetricsRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> keyword_plan_idea_service.GenerateKeywordHistoricalMetricsResponse: + r"""Returns a list of keyword historical metrics. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateKeywordHistoricalMetricsRequest, dict]): + The request object. Request message for + [KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics]. + 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.googleads.v24.services.types.GenerateKeywordHistoricalMetricsResponse: + Response message for + [KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics]. + + """ + # 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, + keyword_plan_idea_service.GenerateKeywordHistoricalMetricsRequest, + ): + request = keyword_plan_idea_service.GenerateKeywordHistoricalMetricsRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_keyword_historical_metrics + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_ad_group_themes( + self, + request: Optional[ + Union[keyword_plan_idea_service.GenerateAdGroupThemesRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + keywords: Optional[MutableSequence[str]] = None, + ad_groups: Optional[MutableSequence[str]] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> keyword_plan_idea_service.GenerateAdGroupThemesResponse: + r"""Returns a list of suggested AdGroups and suggested modifications + (text, match type) for the given keywords. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateAdGroupThemesRequest, dict]): + The request object. Request message for + [KeywordPlanIdeaService.GenerateAdGroupThemes][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateAdGroupThemes]. + customer_id (str): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + keywords (MutableSequence[str]): + Required. A list of keywords to group + into the provided AdGroups. + + This corresponds to the ``keywords`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + ad_groups (MutableSequence[str]): + Required. A list of resource names of AdGroups to group + keywords into. Resource name format: + ``customers/{customer_id}/adGroups/{ad_group_id}`` + + This corresponds to the ``ad_groups`` 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.ads.googleads.v24.services.types.GenerateAdGroupThemesResponse: + Response message for + [KeywordPlanIdeaService.GenerateAdGroupThemes][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateAdGroupThemes]. + + """ + # 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 = [customer_id, keywords, ad_groups] + 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, keyword_plan_idea_service.GenerateAdGroupThemesRequest + ): + request = keyword_plan_idea_service.GenerateAdGroupThemesRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if keywords is not None: + request.keywords = keywords + if ad_groups is not None: + request.ad_groups = ad_groups + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_ad_group_themes + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_keyword_forecast_metrics( + self, + request: Optional[ + Union[ + keyword_plan_idea_service.GenerateKeywordForecastMetricsRequest, + dict, + ] + ] = None, + *, + campaign: Optional[keyword_plan_idea_service.CampaignToForecast] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> keyword_plan_idea_service.GenerateKeywordForecastMetricsResponse: + r"""Returns metrics (such as impressions, clicks, total cost) of a + keyword forecast for the given campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateKeywordForecastMetricsRequest, dict]): + The request object. Request message for + [KeywordPlanIdeaService.GenerateKeywordForecastMetrics][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordForecastMetrics]. + campaign (google.ads.googleads.v24.services.types.CampaignToForecast): + Required. The campaign used in the + forecast. + + This corresponds to the ``campaign`` 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.ads.googleads.v24.services.types.GenerateKeywordForecastMetricsResponse: + Response message for + [KeywordPlanIdeaService.GenerateKeywordForecastMetrics][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordForecastMetrics]. + + """ + # 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 = [campaign] + 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, + keyword_plan_idea_service.GenerateKeywordForecastMetricsRequest, + ): + request = ( + keyword_plan_idea_service.GenerateKeywordForecastMetricsRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if campaign is not None: + request.campaign = campaign + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_keyword_forecast_metrics + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "KeywordPlanIdeaServiceClient": + 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() + + +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__ = ("KeywordPlanIdeaServiceClient",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_idea_service/pagers.py b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/pagers.py new file mode 100644 index 000000000..a1dcc2755 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/pagers.py @@ -0,0 +1,212 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import retry_async as retries_async +from typing import ( + Any, + AsyncIterator, + Awaitable, + Callable, + Sequence, + Tuple, + Iterator, + Union, +) + +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.ads.googleads.v24.services.types import keyword_plan_idea_service + + +class GenerateKeywordIdeasPager: + """A pager for iterating through ``generate_keyword_ideas`` requests. + + This class thinly wraps an initial + :class:`google.ads.googleads.v24.services.types.GenerateKeywordIdeaResponse` object, and + provides an ``__iter__`` method to iterate through its + ``results`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``GenerateKeywordIdeas`` requests and continue to iterate + through the ``results`` field on the + corresponding responses. + + All the usual :class:`google.ads.googleads.v24.services.types.GenerateKeywordIdeaResponse` + 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[ + ..., keyword_plan_idea_service.GenerateKeywordIdeaResponse + ], + request: keyword_plan_idea_service.GenerateKeywordIdeasRequest, + response: keyword_plan_idea_service.GenerateKeywordIdeaResponse, + *, + 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.ads.googleads.v24.services.types.GenerateKeywordIdeasRequest): + The initial request object. + response (google.ads.googleads.v24.services.types.GenerateKeywordIdeaResponse): + 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 = keyword_plan_idea_service.GenerateKeywordIdeasRequest( + 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[keyword_plan_idea_service.GenerateKeywordIdeaResponse]: + 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[keyword_plan_idea_service.GenerateKeywordIdeaResult]: + for page in self.pages: + yield from page.results + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class GenerateKeywordIdeasAsyncPager: + """A pager for iterating through ``generate_keyword_ideas`` requests. + + This class thinly wraps an initial + :class:`google.ads.googleads.v24.services.types.GenerateKeywordIdeaResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``results`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``GenerateKeywordIdeas`` requests and continue to iterate + through the ``results`` field on the + corresponding responses. + + All the usual :class:`google.ads.googleads.v24.services.types.GenerateKeywordIdeaResponse` + 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[keyword_plan_idea_service.GenerateKeywordIdeaResponse], + ], + request: keyword_plan_idea_service.GenerateKeywordIdeasRequest, + response: keyword_plan_idea_service.GenerateKeywordIdeaResponse, + *, + 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.ads.googleads.v24.services.types.GenerateKeywordIdeasRequest): + The initial request object. + response (google.ads.googleads.v24.services.types.GenerateKeywordIdeaResponse): + 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 = keyword_plan_idea_service.GenerateKeywordIdeasRequest( + 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[keyword_plan_idea_service.GenerateKeywordIdeaResponse]: + 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[keyword_plan_idea_service.GenerateKeywordIdeaResult]: + async def async_generator(): + async for page in self.pages: + for response in page.results: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/README.rst b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/README.rst new file mode 100644 index 000000000..2f67d0dc3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`KeywordPlanIdeaServiceTransport` is the ABC for all transports. +- public child `KeywordPlanIdeaServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `KeywordPlanIdeaServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseKeywordPlanIdeaServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `KeywordPlanIdeaServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/__init__.py b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/__init__.py new file mode 100644 index 000000000..9d33ff763 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import KeywordPlanIdeaServiceTransport +from .grpc import KeywordPlanIdeaServiceGrpcTransport +from .grpc_asyncio import KeywordPlanIdeaServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[KeywordPlanIdeaServiceTransport]] +_transport_registry["grpc"] = KeywordPlanIdeaServiceGrpcTransport +_transport_registry["grpc_asyncio"] = KeywordPlanIdeaServiceGrpcAsyncIOTransport + +__all__ = ( + "KeywordPlanIdeaServiceTransport", + "KeywordPlanIdeaServiceGrpcTransport", + "KeywordPlanIdeaServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/base.py b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/base.py new file mode 100644 index 000000000..26588a82e --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/base.py @@ -0,0 +1,228 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import keyword_plan_idea_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 KeywordPlanIdeaServiceTransport(abc.ABC): + """Abstract transport class for KeywordPlanIdeaService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.generate_keyword_ideas: gapic_v1.method.wrap_method( + self.generate_keyword_ideas, + default_timeout=None, + client_info=client_info, + ), + self.generate_keyword_historical_metrics: gapic_v1.method.wrap_method( + self.generate_keyword_historical_metrics, + default_timeout=None, + client_info=client_info, + ), + self.generate_ad_group_themes: gapic_v1.method.wrap_method( + self.generate_ad_group_themes, + default_timeout=None, + client_info=client_info, + ), + self.generate_keyword_forecast_metrics: gapic_v1.method.wrap_method( + self.generate_keyword_forecast_metrics, + 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 generate_keyword_ideas( + self, + ) -> Callable[ + [keyword_plan_idea_service.GenerateKeywordIdeasRequest], + Union[ + keyword_plan_idea_service.GenerateKeywordIdeaResponse, + Awaitable[keyword_plan_idea_service.GenerateKeywordIdeaResponse], + ], + ]: + raise NotImplementedError() + + @property + def generate_keyword_historical_metrics( + self, + ) -> Callable[ + [keyword_plan_idea_service.GenerateKeywordHistoricalMetricsRequest], + Union[ + keyword_plan_idea_service.GenerateKeywordHistoricalMetricsResponse, + Awaitable[ + keyword_plan_idea_service.GenerateKeywordHistoricalMetricsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def generate_ad_group_themes( + self, + ) -> Callable[ + [keyword_plan_idea_service.GenerateAdGroupThemesRequest], + Union[ + keyword_plan_idea_service.GenerateAdGroupThemesResponse, + Awaitable[keyword_plan_idea_service.GenerateAdGroupThemesResponse], + ], + ]: + raise NotImplementedError() + + @property + def generate_keyword_forecast_metrics( + self, + ) -> Callable[ + [keyword_plan_idea_service.GenerateKeywordForecastMetricsRequest], + Union[ + keyword_plan_idea_service.GenerateKeywordForecastMetricsResponse, + Awaitable[ + keyword_plan_idea_service.GenerateKeywordForecastMetricsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("KeywordPlanIdeaServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/grpc.py b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/grpc.py new file mode 100644 index 000000000..2843b4c31 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/grpc.py @@ -0,0 +1,501 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import keyword_plan_idea_service +from .base import KeywordPlanIdeaServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.KeywordPlanIdeaService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.KeywordPlanIdeaService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class KeywordPlanIdeaServiceGrpcTransport(KeywordPlanIdeaServiceTransport): + """gRPC backend transport for KeywordPlanIdeaService. + + Service to generate keyword ideas. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 generate_keyword_ideas( + self, + ) -> Callable[ + [keyword_plan_idea_service.GenerateKeywordIdeasRequest], + keyword_plan_idea_service.GenerateKeywordIdeaResponse, + ]: + r"""Return a callable for the generate keyword ideas method over gRPC. + + Returns a list of keyword ideas. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanIdeaError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateKeywordIdeasRequest], + ~.GenerateKeywordIdeaResponse]: + 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 "generate_keyword_ideas" not in self._stubs: + self._stubs["generate_keyword_ideas"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanIdeaService/GenerateKeywordIdeas", + request_serializer=keyword_plan_idea_service.GenerateKeywordIdeasRequest.serialize, + response_deserializer=keyword_plan_idea_service.GenerateKeywordIdeaResponse.deserialize, + ) + ) + return self._stubs["generate_keyword_ideas"] + + @property + def generate_keyword_historical_metrics( + self, + ) -> Callable[ + [keyword_plan_idea_service.GenerateKeywordHistoricalMetricsRequest], + keyword_plan_idea_service.GenerateKeywordHistoricalMetricsResponse, + ]: + r"""Return a callable for the generate keyword historical + metrics method over gRPC. + + Returns a list of keyword historical metrics. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateKeywordHistoricalMetricsRequest], + ~.GenerateKeywordHistoricalMetricsResponse]: + 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 "generate_keyword_historical_metrics" not in self._stubs: + self._stubs["generate_keyword_historical_metrics"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanIdeaService/GenerateKeywordHistoricalMetrics", + request_serializer=keyword_plan_idea_service.GenerateKeywordHistoricalMetricsRequest.serialize, + response_deserializer=keyword_plan_idea_service.GenerateKeywordHistoricalMetricsResponse.deserialize, + ) + ) + return self._stubs["generate_keyword_historical_metrics"] + + @property + def generate_ad_group_themes( + self, + ) -> Callable[ + [keyword_plan_idea_service.GenerateAdGroupThemesRequest], + keyword_plan_idea_service.GenerateAdGroupThemesResponse, + ]: + r"""Return a callable for the generate ad group themes method over gRPC. + + Returns a list of suggested AdGroups and suggested modifications + (text, match type) for the given keywords. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateAdGroupThemesRequest], + ~.GenerateAdGroupThemesResponse]: + 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 "generate_ad_group_themes" not in self._stubs: + self._stubs["generate_ad_group_themes"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanIdeaService/GenerateAdGroupThemes", + request_serializer=keyword_plan_idea_service.GenerateAdGroupThemesRequest.serialize, + response_deserializer=keyword_plan_idea_service.GenerateAdGroupThemesResponse.deserialize, + ) + ) + return self._stubs["generate_ad_group_themes"] + + @property + def generate_keyword_forecast_metrics( + self, + ) -> Callable[ + [keyword_plan_idea_service.GenerateKeywordForecastMetricsRequest], + keyword_plan_idea_service.GenerateKeywordForecastMetricsResponse, + ]: + r"""Return a callable for the generate keyword forecast + metrics method over gRPC. + + Returns metrics (such as impressions, clicks, total cost) of a + keyword forecast for the given campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateKeywordForecastMetricsRequest], + ~.GenerateKeywordForecastMetricsResponse]: + 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 "generate_keyword_forecast_metrics" not in self._stubs: + self._stubs["generate_keyword_forecast_metrics"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanIdeaService/GenerateKeywordForecastMetrics", + request_serializer=keyword_plan_idea_service.GenerateKeywordForecastMetricsRequest.serialize, + response_deserializer=keyword_plan_idea_service.GenerateKeywordForecastMetricsResponse.deserialize, + ) + ) + return self._stubs["generate_keyword_forecast_metrics"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("KeywordPlanIdeaServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..efd5eab39 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_idea_service/transports/grpc_asyncio.py @@ -0,0 +1,543 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import keyword_plan_idea_service +from .base import KeywordPlanIdeaServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.KeywordPlanIdeaService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.KeywordPlanIdeaService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class KeywordPlanIdeaServiceGrpcAsyncIOTransport( + KeywordPlanIdeaServiceTransport +): + """gRPC AsyncIO backend transport for KeywordPlanIdeaService. + + Service to generate keyword ideas. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 generate_keyword_ideas( + self, + ) -> Callable[ + [keyword_plan_idea_service.GenerateKeywordIdeasRequest], + Awaitable[keyword_plan_idea_service.GenerateKeywordIdeaResponse], + ]: + r"""Return a callable for the generate keyword ideas method over gRPC. + + Returns a list of keyword ideas. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `KeywordPlanIdeaError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateKeywordIdeasRequest], + Awaitable[~.GenerateKeywordIdeaResponse]]: + 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 "generate_keyword_ideas" not in self._stubs: + self._stubs["generate_keyword_ideas"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanIdeaService/GenerateKeywordIdeas", + request_serializer=keyword_plan_idea_service.GenerateKeywordIdeasRequest.serialize, + response_deserializer=keyword_plan_idea_service.GenerateKeywordIdeaResponse.deserialize, + ) + ) + return self._stubs["generate_keyword_ideas"] + + @property + def generate_keyword_historical_metrics( + self, + ) -> Callable[ + [keyword_plan_idea_service.GenerateKeywordHistoricalMetricsRequest], + Awaitable[ + keyword_plan_idea_service.GenerateKeywordHistoricalMetricsResponse + ], + ]: + r"""Return a callable for the generate keyword historical + metrics method over gRPC. + + Returns a list of keyword historical metrics. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateKeywordHistoricalMetricsRequest], + Awaitable[~.GenerateKeywordHistoricalMetricsResponse]]: + 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 "generate_keyword_historical_metrics" not in self._stubs: + self._stubs["generate_keyword_historical_metrics"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanIdeaService/GenerateKeywordHistoricalMetrics", + request_serializer=keyword_plan_idea_service.GenerateKeywordHistoricalMetricsRequest.serialize, + response_deserializer=keyword_plan_idea_service.GenerateKeywordHistoricalMetricsResponse.deserialize, + ) + ) + return self._stubs["generate_keyword_historical_metrics"] + + @property + def generate_ad_group_themes( + self, + ) -> Callable[ + [keyword_plan_idea_service.GenerateAdGroupThemesRequest], + Awaitable[keyword_plan_idea_service.GenerateAdGroupThemesResponse], + ]: + r"""Return a callable for the generate ad group themes method over gRPC. + + Returns a list of suggested AdGroups and suggested modifications + (text, match type) for the given keywords. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateAdGroupThemesRequest], + Awaitable[~.GenerateAdGroupThemesResponse]]: + 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 "generate_ad_group_themes" not in self._stubs: + self._stubs["generate_ad_group_themes"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanIdeaService/GenerateAdGroupThemes", + request_serializer=keyword_plan_idea_service.GenerateAdGroupThemesRequest.serialize, + response_deserializer=keyword_plan_idea_service.GenerateAdGroupThemesResponse.deserialize, + ) + ) + return self._stubs["generate_ad_group_themes"] + + @property + def generate_keyword_forecast_metrics( + self, + ) -> Callable[ + [keyword_plan_idea_service.GenerateKeywordForecastMetricsRequest], + Awaitable[ + keyword_plan_idea_service.GenerateKeywordForecastMetricsResponse + ], + ]: + r"""Return a callable for the generate keyword forecast + metrics method over gRPC. + + Returns metrics (such as impressions, clicks, total cost) of a + keyword forecast for the given campaign. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.GenerateKeywordForecastMetricsRequest], + Awaitable[~.GenerateKeywordForecastMetricsResponse]]: + 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 "generate_keyword_forecast_metrics" not in self._stubs: + self._stubs["generate_keyword_forecast_metrics"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanIdeaService/GenerateKeywordForecastMetrics", + request_serializer=keyword_plan_idea_service.GenerateKeywordForecastMetricsRequest.serialize, + response_deserializer=keyword_plan_idea_service.GenerateKeywordForecastMetricsResponse.deserialize, + ) + ) + return self._stubs["generate_keyword_forecast_metrics"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.generate_keyword_ideas: self._wrap_method( + self.generate_keyword_ideas, + default_timeout=None, + client_info=client_info, + ), + self.generate_keyword_historical_metrics: self._wrap_method( + self.generate_keyword_historical_metrics, + default_timeout=None, + client_info=client_info, + ), + self.generate_ad_group_themes: self._wrap_method( + self.generate_ad_group_themes, + default_timeout=None, + client_info=client_info, + ), + self.generate_keyword_forecast_metrics: self._wrap_method( + self.generate_keyword_forecast_metrics, + 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" + + +__all__ = ("KeywordPlanIdeaServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_service/__init__.py b/google/ads/googleads/v24/services/services/keyword_plan_service/__init__.py new file mode 100644 index 000000000..b1e557414 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import KeywordPlanServiceClient +from .async_client import KeywordPlanServiceAsyncClient + +__all__ = ( + "KeywordPlanServiceClient", + "KeywordPlanServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_service/async_client.py b/google/ads/googleads/v24/services/services/keyword_plan_service/async_client.py new file mode 100644 index 000000000..df8e67775 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_service/async_client.py @@ -0,0 +1,423 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import keyword_plan_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import KeywordPlanServiceTransport, DEFAULT_CLIENT_INFO +from .client import KeywordPlanServiceClient + +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 KeywordPlanServiceAsyncClient: + """Service to manage keyword plans.""" + + _client: KeywordPlanServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = KeywordPlanServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = KeywordPlanServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + KeywordPlanServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = KeywordPlanServiceClient._DEFAULT_UNIVERSE + + keyword_plan_path = staticmethod(KeywordPlanServiceClient.keyword_plan_path) + parse_keyword_plan_path = staticmethod( + KeywordPlanServiceClient.parse_keyword_plan_path + ) + common_billing_account_path = staticmethod( + KeywordPlanServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + KeywordPlanServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + KeywordPlanServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + KeywordPlanServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + KeywordPlanServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + KeywordPlanServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + KeywordPlanServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + KeywordPlanServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + KeywordPlanServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + KeywordPlanServiceClient.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: + KeywordPlanServiceAsyncClient: The constructed client. + """ + return KeywordPlanServiceClient.from_service_account_info.__func__(KeywordPlanServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + KeywordPlanServiceAsyncClient: The constructed client. + """ + return KeywordPlanServiceClient.from_service_account_file.__func__(KeywordPlanServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return KeywordPlanServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> KeywordPlanServiceTransport: + """Returns the transport used by the client instance. + + Returns: + KeywordPlanServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = KeywordPlanServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + KeywordPlanServiceTransport, + Callable[..., KeywordPlanServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the keyword plan 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,KeywordPlanServiceTransport,Callable[..., KeywordPlanServiceTransport]]]): + 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 KeywordPlanServiceTransport 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 = KeywordPlanServiceClient( + 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.ads.googleads.v24.services.KeywordPlanServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.KeywordPlanService", + "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.ads.googleads.v24.services.KeywordPlanService", + "credentialsType": None, + } + ), + ) + + async def mutate_keyword_plans( + self, + request: Optional[ + Union[keyword_plan_service.MutateKeywordPlansRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[keyword_plan_service.KeywordPlanOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> keyword_plan_service.MutateKeywordPlansResponse: + r"""Creates, updates, or removes keyword plans. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `KeywordPlanError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `StringLengthError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateKeywordPlansRequest, dict]]): + The request object. Request message for + [KeywordPlanService.MutateKeywordPlans][google.ads.googleads.v24.services.KeywordPlanService.MutateKeywordPlans]. + customer_id (:class:`str`): + Required. The ID of the customer + whose keyword plans are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanOperation]`): + Required. The list of operations to + perform on individual keyword plans. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateKeywordPlansResponse: + Response message for a keyword plan + mutate. + + """ + # 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 = [customer_id, operations] + 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, keyword_plan_service.MutateKeywordPlansRequest + ): + request = keyword_plan_service.MutateKeywordPlansRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_keyword_plans + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "KeywordPlanServiceAsyncClient": + 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__ = ("KeywordPlanServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_service/client.py b/google/ads/googleads/v24/services/services/keyword_plan_service/client.py new file mode 100644 index 000000000..351d56672 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_service/client.py @@ -0,0 +1,889 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import keyword_plan_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import KeywordPlanServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import KeywordPlanServiceGrpcTransport +from .transports.grpc_asyncio import KeywordPlanServiceGrpcAsyncIOTransport + + +class KeywordPlanServiceClientMeta(type): + """Metaclass for the KeywordPlanService 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[KeywordPlanServiceTransport]] + _transport_registry["grpc"] = KeywordPlanServiceGrpcTransport + _transport_registry["grpc_asyncio"] = KeywordPlanServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[KeywordPlanServiceTransport]: + """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 KeywordPlanServiceClient(metaclass=KeywordPlanServiceClientMeta): + """Service to manage keyword plans.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + KeywordPlanServiceClient: 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: + KeywordPlanServiceClient: 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) -> KeywordPlanServiceTransport: + """Returns the transport used by the client instance. + + Returns: + KeywordPlanServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def keyword_plan_path( + customer_id: str, + keyword_plan_id: str, + ) -> str: + """Returns a fully-qualified keyword_plan string.""" + return "customers/{customer_id}/keywordPlans/{keyword_plan_id}".format( + customer_id=customer_id, + keyword_plan_id=keyword_plan_id, + ) + + @staticmethod + def parse_keyword_plan_path(path: str) -> Dict[str, str]: + """Parses a keyword_plan path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/keywordPlans/(?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 = KeywordPlanServiceClient._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 = KeywordPlanServiceClient._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 + ): + """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 = KeywordPlanServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = KeywordPlanServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + KeywordPlanServiceClient._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 = KeywordPlanServiceClient._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): + """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, + KeywordPlanServiceTransport, + Callable[..., KeywordPlanServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the keyword plan 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,KeywordPlanServiceTransport,Callable[..., KeywordPlanServiceTransport]]]): + 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 KeywordPlanServiceTransport 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, + ) = KeywordPlanServiceClient._read_environment_variables() + self._client_cert_source = ( + KeywordPlanServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = KeywordPlanServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, KeywordPlanServiceTransport) + if transport_provided: + # transport is a KeywordPlanServiceTransport 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(KeywordPlanServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or KeywordPlanServiceClient._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[KeywordPlanServiceTransport], + Callable[..., KeywordPlanServiceTransport], + ] = ( + KeywordPlanServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., KeywordPlanServiceTransport], 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.ads.googleads.v24.services.KeywordPlanServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.KeywordPlanService", + "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.ads.googleads.v24.services.KeywordPlanService", + "credentialsType": None, + } + ), + ) + + def mutate_keyword_plans( + self, + request: Optional[ + Union[keyword_plan_service.MutateKeywordPlansRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[keyword_plan_service.KeywordPlanOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> keyword_plan_service.MutateKeywordPlansResponse: + r"""Creates, updates, or removes keyword plans. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `KeywordPlanError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateKeywordPlansRequest, dict]): + The request object. Request message for + [KeywordPlanService.MutateKeywordPlans][google.ads.googleads.v24.services.KeywordPlanService.MutateKeywordPlans]. + customer_id (str): + Required. The ID of the customer + whose keyword plans are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanOperation]): + Required. The list of operations to + perform on individual keyword plans. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateKeywordPlansResponse: + Response message for a keyword plan + mutate. + + """ + # 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 = [customer_id, operations] + 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, keyword_plan_service.MutateKeywordPlansRequest + ): + request = keyword_plan_service.MutateKeywordPlansRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_keyword_plans + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "KeywordPlanServiceClient": + 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() + + +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__ = ("KeywordPlanServiceClient",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_service/transports/README.rst b/google/ads/googleads/v24/services/services/keyword_plan_service/transports/README.rst new file mode 100644 index 000000000..dc80fbb31 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`KeywordPlanServiceTransport` is the ABC for all transports. +- public child `KeywordPlanServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `KeywordPlanServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseKeywordPlanServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `KeywordPlanServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/keyword_plan_service/transports/__init__.py b/google/ads/googleads/v24/services/services/keyword_plan_service/transports/__init__.py new file mode 100644 index 000000000..06e0b9c78 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import KeywordPlanServiceTransport +from .grpc import KeywordPlanServiceGrpcTransport +from .grpc_asyncio import KeywordPlanServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[KeywordPlanServiceTransport]] +_transport_registry["grpc"] = KeywordPlanServiceGrpcTransport +_transport_registry["grpc_asyncio"] = KeywordPlanServiceGrpcAsyncIOTransport + +__all__ = ( + "KeywordPlanServiceTransport", + "KeywordPlanServiceGrpcTransport", + "KeywordPlanServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_service/transports/base.py b/google/ads/googleads/v24/services/services/keyword_plan_service/transports/base.py new file mode 100644 index 000000000..2a0021440 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import keyword_plan_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 KeywordPlanServiceTransport(abc.ABC): + """Abstract transport class for KeywordPlanService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_keyword_plans: gapic_v1.method.wrap_method( + self.mutate_keyword_plans, + 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 mutate_keyword_plans( + self, + ) -> Callable[ + [keyword_plan_service.MutateKeywordPlansRequest], + Union[ + keyword_plan_service.MutateKeywordPlansResponse, + Awaitable[keyword_plan_service.MutateKeywordPlansResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("KeywordPlanServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_service/transports/grpc.py b/google/ads/googleads/v24/services/services/keyword_plan_service/transports/grpc.py new file mode 100644 index 000000000..f185e73d5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_service/transports/grpc.py @@ -0,0 +1,391 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import keyword_plan_service +from .base import KeywordPlanServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.KeywordPlanService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.KeywordPlanService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class KeywordPlanServiceGrpcTransport(KeywordPlanServiceTransport): + """gRPC backend transport for KeywordPlanService. + + Service to manage keyword plans. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_keyword_plans( + self, + ) -> Callable[ + [keyword_plan_service.MutateKeywordPlansRequest], + keyword_plan_service.MutateKeywordPlansResponse, + ]: + r"""Return a callable for the mutate keyword plans method over gRPC. + + Creates, updates, or removes keyword plans. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `KeywordPlanError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateKeywordPlansRequest], + ~.MutateKeywordPlansResponse]: + 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 "mutate_keyword_plans" not in self._stubs: + self._stubs["mutate_keyword_plans"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanService/MutateKeywordPlans", + request_serializer=keyword_plan_service.MutateKeywordPlansRequest.serialize, + response_deserializer=keyword_plan_service.MutateKeywordPlansResponse.deserialize, + ) + ) + return self._stubs["mutate_keyword_plans"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("KeywordPlanServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_plan_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/keyword_plan_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..47e1db3f6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_plan_service/transports/grpc_asyncio.py @@ -0,0 +1,412 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import keyword_plan_service +from .base import KeywordPlanServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.KeywordPlanService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.KeywordPlanService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class KeywordPlanServiceGrpcAsyncIOTransport(KeywordPlanServiceTransport): + """gRPC AsyncIO backend transport for KeywordPlanService. + + Service to manage keyword plans. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_keyword_plans( + self, + ) -> Callable[ + [keyword_plan_service.MutateKeywordPlansRequest], + Awaitable[keyword_plan_service.MutateKeywordPlansResponse], + ]: + r"""Return a callable for the mutate keyword plans method over gRPC. + + Creates, updates, or removes keyword plans. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `KeywordPlanError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `QuotaError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateKeywordPlansRequest], + Awaitable[~.MutateKeywordPlansResponse]]: + 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 "mutate_keyword_plans" not in self._stubs: + self._stubs["mutate_keyword_plans"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordPlanService/MutateKeywordPlans", + request_serializer=keyword_plan_service.MutateKeywordPlansRequest.serialize, + response_deserializer=keyword_plan_service.MutateKeywordPlansResponse.deserialize, + ) + ) + return self._stubs["mutate_keyword_plans"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_keyword_plans: self._wrap_method( + self.mutate_keyword_plans, + 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" + + +__all__ = ("KeywordPlanServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_theme_constant_service/__init__.py b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/__init__.py new file mode 100644 index 000000000..ba06db70a --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import KeywordThemeConstantServiceClient +from .async_client import KeywordThemeConstantServiceAsyncClient + +__all__ = ( + "KeywordThemeConstantServiceClient", + "KeywordThemeConstantServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/keyword_theme_constant_service/async_client.py b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/async_client.py new file mode 100644 index 000000000..e9186ddfd --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/async_client.py @@ -0,0 +1,388 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + keyword_theme_constant_service, +) +from .transports.base import ( + KeywordThemeConstantServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import KeywordThemeConstantServiceClient + +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 KeywordThemeConstantServiceAsyncClient: + """Service to fetch Smart Campaign keyword themes.""" + + _client: KeywordThemeConstantServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = KeywordThemeConstantServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + KeywordThemeConstantServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + KeywordThemeConstantServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = KeywordThemeConstantServiceClient._DEFAULT_UNIVERSE + + keyword_theme_constant_path = staticmethod( + KeywordThemeConstantServiceClient.keyword_theme_constant_path + ) + parse_keyword_theme_constant_path = staticmethod( + KeywordThemeConstantServiceClient.parse_keyword_theme_constant_path + ) + common_billing_account_path = staticmethod( + KeywordThemeConstantServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + KeywordThemeConstantServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + KeywordThemeConstantServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + KeywordThemeConstantServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + KeywordThemeConstantServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + KeywordThemeConstantServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + KeywordThemeConstantServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + KeywordThemeConstantServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + KeywordThemeConstantServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + KeywordThemeConstantServiceClient.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: + KeywordThemeConstantServiceAsyncClient: The constructed client. + """ + return KeywordThemeConstantServiceClient.from_service_account_info.__func__(KeywordThemeConstantServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + KeywordThemeConstantServiceAsyncClient: The constructed client. + """ + return KeywordThemeConstantServiceClient.from_service_account_file.__func__(KeywordThemeConstantServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return KeywordThemeConstantServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> KeywordThemeConstantServiceTransport: + """Returns the transport used by the client instance. + + Returns: + KeywordThemeConstantServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = KeywordThemeConstantServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + KeywordThemeConstantServiceTransport, + Callable[..., KeywordThemeConstantServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the keyword theme constant 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,KeywordThemeConstantServiceTransport,Callable[..., KeywordThemeConstantServiceTransport]]]): + 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 KeywordThemeConstantServiceTransport 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 = KeywordThemeConstantServiceClient( + 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.ads.googleads.v24.services.KeywordThemeConstantServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.KeywordThemeConstantService", + "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.ads.googleads.v24.services.KeywordThemeConstantService", + "credentialsType": None, + } + ), + ) + + async def suggest_keyword_theme_constants( + self, + request: Optional[ + Union[ + keyword_theme_constant_service.SuggestKeywordThemeConstantsRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> keyword_theme_constant_service.SuggestKeywordThemeConstantsResponse: + r"""Returns KeywordThemeConstant suggestions by keyword themes. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.SuggestKeywordThemeConstantsRequest, dict]]): + The request object. Request message for + [KeywordThemeConstantService.SuggestKeywordThemeConstants][google.ads.googleads.v24.services.KeywordThemeConstantService.SuggestKeywordThemeConstants]. + 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.googleads.v24.services.types.SuggestKeywordThemeConstantsResponse: + Response message for + [KeywordThemeConstantService.SuggestKeywordThemeConstants][google.ads.googleads.v24.services.KeywordThemeConstantService.SuggestKeywordThemeConstants]. + + """ + # 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, + keyword_theme_constant_service.SuggestKeywordThemeConstantsRequest, + ): + request = keyword_theme_constant_service.SuggestKeywordThemeConstantsRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.suggest_keyword_theme_constants + ] + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "KeywordThemeConstantServiceAsyncClient": + 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__ = ("KeywordThemeConstantServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/keyword_theme_constant_service/client.py b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/client.py new file mode 100644 index 000000000..6ae6939fb --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/client.py @@ -0,0 +1,862 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + keyword_theme_constant_service, +) +from .transports.base import ( + KeywordThemeConstantServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import KeywordThemeConstantServiceGrpcTransport +from .transports.grpc_asyncio import ( + KeywordThemeConstantServiceGrpcAsyncIOTransport, +) + + +class KeywordThemeConstantServiceClientMeta(type): + """Metaclass for the KeywordThemeConstantService 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[KeywordThemeConstantServiceTransport]] + _transport_registry["grpc"] = KeywordThemeConstantServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + KeywordThemeConstantServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[KeywordThemeConstantServiceTransport]: + """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 KeywordThemeConstantServiceClient( + metaclass=KeywordThemeConstantServiceClientMeta +): + """Service to fetch Smart Campaign keyword themes.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + KeywordThemeConstantServiceClient: 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: + KeywordThemeConstantServiceClient: 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) -> KeywordThemeConstantServiceTransport: + """Returns the transport used by the client instance. + + Returns: + KeywordThemeConstantServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def keyword_theme_constant_path( + express_category_id: str, + express_sub_category_id: str, + ) -> str: + """Returns a fully-qualified keyword_theme_constant string.""" + return "keywordThemeConstants/{express_category_id}~{express_sub_category_id}".format( + express_category_id=express_category_id, + express_sub_category_id=express_sub_category_id, + ) + + @staticmethod + def parse_keyword_theme_constant_path(path: str) -> Dict[str, str]: + """Parses a keyword_theme_constant path into its component segments.""" + m = re.match( + r"^keywordThemeConstants/(?P.+?)~(?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 = ( + KeywordThemeConstantServiceClient._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 = ( + KeywordThemeConstantServiceClient._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 + ): + """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 = ( + KeywordThemeConstantServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + KeywordThemeConstantServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = KeywordThemeConstantServiceClient._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 = KeywordThemeConstantServiceClient._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): + """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, + KeywordThemeConstantServiceTransport, + Callable[..., KeywordThemeConstantServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the keyword theme constant 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,KeywordThemeConstantServiceTransport,Callable[..., KeywordThemeConstantServiceTransport]]]): + 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 KeywordThemeConstantServiceTransport 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, + ) = KeywordThemeConstantServiceClient._read_environment_variables() + self._client_cert_source = ( + KeywordThemeConstantServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + KeywordThemeConstantServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, KeywordThemeConstantServiceTransport + ) + if transport_provided: + # transport is a KeywordThemeConstantServiceTransport 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( + KeywordThemeConstantServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or KeywordThemeConstantServiceClient._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[KeywordThemeConstantServiceTransport], + Callable[..., KeywordThemeConstantServiceTransport], + ] = ( + KeywordThemeConstantServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., KeywordThemeConstantServiceTransport], + 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.ads.googleads.v24.services.KeywordThemeConstantServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.KeywordThemeConstantService", + "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.ads.googleads.v24.services.KeywordThemeConstantService", + "credentialsType": None, + } + ), + ) + + def suggest_keyword_theme_constants( + self, + request: Optional[ + Union[ + keyword_theme_constant_service.SuggestKeywordThemeConstantsRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> keyword_theme_constant_service.SuggestKeywordThemeConstantsResponse: + r"""Returns KeywordThemeConstant suggestions by keyword themes. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.SuggestKeywordThemeConstantsRequest, dict]): + The request object. Request message for + [KeywordThemeConstantService.SuggestKeywordThemeConstants][google.ads.googleads.v24.services.KeywordThemeConstantService.SuggestKeywordThemeConstants]. + 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.googleads.v24.services.types.SuggestKeywordThemeConstantsResponse: + Response message for + [KeywordThemeConstantService.SuggestKeywordThemeConstants][google.ads.googleads.v24.services.KeywordThemeConstantService.SuggestKeywordThemeConstants]. + + """ + # 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, + keyword_theme_constant_service.SuggestKeywordThemeConstantsRequest, + ): + request = keyword_theme_constant_service.SuggestKeywordThemeConstantsRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.suggest_keyword_theme_constants + ] + + # 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) -> "KeywordThemeConstantServiceClient": + 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() + + +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__ = ("KeywordThemeConstantServiceClient",) diff --git a/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/README.rst b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/README.rst new file mode 100644 index 000000000..a16e0a650 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`KeywordThemeConstantServiceTransport` is the ABC for all transports. +- public child `KeywordThemeConstantServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `KeywordThemeConstantServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseKeywordThemeConstantServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `KeywordThemeConstantServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/__init__.py b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/__init__.py new file mode 100644 index 000000000..464231fb8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import KeywordThemeConstantServiceTransport +from .grpc import KeywordThemeConstantServiceGrpcTransport +from .grpc_asyncio import KeywordThemeConstantServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[KeywordThemeConstantServiceTransport]] +_transport_registry["grpc"] = KeywordThemeConstantServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + KeywordThemeConstantServiceGrpcAsyncIOTransport +) + +__all__ = ( + "KeywordThemeConstantServiceTransport", + "KeywordThemeConstantServiceGrpcTransport", + "KeywordThemeConstantServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/base.py b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/base.py new file mode 100644 index 000000000..bfd82b7b4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + keyword_theme_constant_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 KeywordThemeConstantServiceTransport(abc.ABC): + """Abstract transport class for KeywordThemeConstantService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.suggest_keyword_theme_constants: gapic_v1.method.wrap_method( + self.suggest_keyword_theme_constants, + 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 suggest_keyword_theme_constants( + self, + ) -> Callable[ + [keyword_theme_constant_service.SuggestKeywordThemeConstantsRequest], + Union[ + keyword_theme_constant_service.SuggestKeywordThemeConstantsResponse, + Awaitable[ + keyword_theme_constant_service.SuggestKeywordThemeConstantsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("KeywordThemeConstantServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/grpc.py b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/grpc.py new file mode 100644 index 000000000..6f1676769 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/grpc.py @@ -0,0 +1,392 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + keyword_theme_constant_service, +) +from .base import KeywordThemeConstantServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.KeywordThemeConstantService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.KeywordThemeConstantService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class KeywordThemeConstantServiceGrpcTransport( + KeywordThemeConstantServiceTransport +): + """gRPC backend transport for KeywordThemeConstantService. + + Service to fetch Smart Campaign keyword themes. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 suggest_keyword_theme_constants( + self, + ) -> Callable[ + [keyword_theme_constant_service.SuggestKeywordThemeConstantsRequest], + keyword_theme_constant_service.SuggestKeywordThemeConstantsResponse, + ]: + r"""Return a callable for the suggest keyword theme + constants method over gRPC. + + Returns KeywordThemeConstant suggestions by keyword themes. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.SuggestKeywordThemeConstantsRequest], + ~.SuggestKeywordThemeConstantsResponse]: + 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 "suggest_keyword_theme_constants" not in self._stubs: + self._stubs["suggest_keyword_theme_constants"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordThemeConstantService/SuggestKeywordThemeConstants", + request_serializer=keyword_theme_constant_service.SuggestKeywordThemeConstantsRequest.serialize, + response_deserializer=keyword_theme_constant_service.SuggestKeywordThemeConstantsResponse.deserialize, + ) + ) + return self._stubs["suggest_keyword_theme_constants"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("KeywordThemeConstantServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..a60b257b4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/keyword_theme_constant_service/transports/grpc_asyncio.py @@ -0,0 +1,415 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + keyword_theme_constant_service, +) +from .base import KeywordThemeConstantServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.KeywordThemeConstantService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.KeywordThemeConstantService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class KeywordThemeConstantServiceGrpcAsyncIOTransport( + KeywordThemeConstantServiceTransport +): + """gRPC AsyncIO backend transport for KeywordThemeConstantService. + + Service to fetch Smart Campaign keyword themes. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 suggest_keyword_theme_constants( + self, + ) -> Callable[ + [keyword_theme_constant_service.SuggestKeywordThemeConstantsRequest], + Awaitable[ + keyword_theme_constant_service.SuggestKeywordThemeConstantsResponse + ], + ]: + r"""Return a callable for the suggest keyword theme + constants method over gRPC. + + Returns KeywordThemeConstant suggestions by keyword themes. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.SuggestKeywordThemeConstantsRequest], + Awaitable[~.SuggestKeywordThemeConstantsResponse]]: + 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 "suggest_keyword_theme_constants" not in self._stubs: + self._stubs["suggest_keyword_theme_constants"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.KeywordThemeConstantService/SuggestKeywordThemeConstants", + request_serializer=keyword_theme_constant_service.SuggestKeywordThemeConstantsRequest.serialize, + response_deserializer=keyword_theme_constant_service.SuggestKeywordThemeConstantsResponse.deserialize, + ) + ) + return self._stubs["suggest_keyword_theme_constants"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.suggest_keyword_theme_constants: self._wrap_method( + self.suggest_keyword_theme_constants, + 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" + + +__all__ = ("KeywordThemeConstantServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/label_service/__init__.py b/google/ads/googleads/v24/services/services/label_service/__init__.py new file mode 100644 index 000000000..9038ed400 --- /dev/null +++ b/google/ads/googleads/v24/services/services/label_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import LabelServiceClient +from .async_client import LabelServiceAsyncClient + +__all__ = ( + "LabelServiceClient", + "LabelServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/label_service/async_client.py b/google/ads/googleads/v24/services/services/label_service/async_client.py new file mode 100644 index 000000000..8d16dc74f --- /dev/null +++ b/google/ads/googleads/v24/services/services/label_service/async_client.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import label_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import LabelServiceTransport, DEFAULT_CLIENT_INFO +from .client import LabelServiceClient + +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 LabelServiceAsyncClient: + """Service to manage labels.""" + + _client: LabelServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = LabelServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = LabelServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = LabelServiceClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = LabelServiceClient._DEFAULT_UNIVERSE + + label_path = staticmethod(LabelServiceClient.label_path) + parse_label_path = staticmethod(LabelServiceClient.parse_label_path) + common_billing_account_path = staticmethod( + LabelServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + LabelServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(LabelServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + LabelServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + LabelServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + LabelServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod(LabelServiceClient.common_project_path) + parse_common_project_path = staticmethod( + LabelServiceClient.parse_common_project_path + ) + common_location_path = staticmethod(LabelServiceClient.common_location_path) + parse_common_location_path = staticmethod( + LabelServiceClient.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: + LabelServiceAsyncClient: The constructed client. + """ + return LabelServiceClient.from_service_account_info.__func__(LabelServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + LabelServiceAsyncClient: The constructed client. + """ + return LabelServiceClient.from_service_account_file.__func__(LabelServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return LabelServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> LabelServiceTransport: + """Returns the transport used by the client instance. + + Returns: + LabelServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = LabelServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, LabelServiceTransport, Callable[..., LabelServiceTransport] + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the label 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,LabelServiceTransport,Callable[..., LabelServiceTransport]]]): + 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 LabelServiceTransport 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 = LabelServiceClient( + 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.ads.googleads.v24.services.LabelServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.LabelService", + "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.ads.googleads.v24.services.LabelService", + "credentialsType": None, + } + ), + ) + + async def mutate_labels( + self, + request: Optional[ + Union[label_service.MutateLabelsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[label_service.LabelOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> label_service.MutateLabelsResponse: + r"""Creates, updates, or removes labels. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `LabelError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateLabelsRequest, dict]]): + The request object. Request message for + [LabelService.MutateLabels][google.ads.googleads.v24.services.LabelService.MutateLabels]. + customer_id (:class:`str`): + Required. ID of the customer whose + labels are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.LabelOperation]`): + Required. The list of operations to + perform on labels. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateLabelsResponse: + Response message for a labels mutate. + """ + # 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 = [customer_id, operations] + 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, label_service.MutateLabelsRequest): + request = label_service.MutateLabelsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_labels + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "LabelServiceAsyncClient": + 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__ = ("LabelServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/label_service/client.py b/google/ads/googleads/v24/services/services/label_service/client.py new file mode 100644 index 000000000..daa2b77aa --- /dev/null +++ b/google/ads/googleads/v24/services/services/label_service/client.py @@ -0,0 +1,880 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import label_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import LabelServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import LabelServiceGrpcTransport +from .transports.grpc_asyncio import LabelServiceGrpcAsyncIOTransport + + +class LabelServiceClientMeta(type): + """Metaclass for the LabelService 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[LabelServiceTransport]] + _transport_registry["grpc"] = LabelServiceGrpcTransport + _transport_registry["grpc_asyncio"] = LabelServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[LabelServiceTransport]: + """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 LabelServiceClient(metaclass=LabelServiceClientMeta): + """Service to manage labels.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + LabelServiceClient: 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: + LabelServiceClient: 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) -> LabelServiceTransport: + """Returns the transport used by the client instance. + + Returns: + LabelServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def label_path( + customer_id: str, + label_id: str, + ) -> str: + """Returns a fully-qualified label string.""" + return "customers/{customer_id}/labels/{label_id}".format( + customer_id=customer_id, + label_id=label_id, + ) + + @staticmethod + def parse_label_path(path: str) -> Dict[str, str]: + """Parses a label path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/labels/(?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 = LabelServiceClient._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 = LabelServiceClient._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 + ): + """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 = LabelServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = LabelServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = LabelServiceClient._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 = LabelServiceClient._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): + """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, LabelServiceTransport, Callable[..., LabelServiceTransport] + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the label 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,LabelServiceTransport,Callable[..., LabelServiceTransport]]]): + 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 LabelServiceTransport 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, + ) = LabelServiceClient._read_environment_variables() + self._client_cert_source = LabelServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = LabelServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, LabelServiceTransport) + if transport_provided: + # transport is a LabelServiceTransport 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(LabelServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or LabelServiceClient._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[LabelServiceTransport], + Callable[..., LabelServiceTransport], + ] = ( + LabelServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., LabelServiceTransport], 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.ads.googleads.v24.services.LabelServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.LabelService", + "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.ads.googleads.v24.services.LabelService", + "credentialsType": None, + } + ), + ) + + def mutate_labels( + self, + request: Optional[ + Union[label_service.MutateLabelsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[label_service.LabelOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> label_service.MutateLabelsResponse: + r"""Creates, updates, or removes labels. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `LabelError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateLabelsRequest, dict]): + The request object. Request message for + [LabelService.MutateLabels][google.ads.googleads.v24.services.LabelService.MutateLabels]. + customer_id (str): + Required. ID of the customer whose + labels are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.LabelOperation]): + Required. The list of operations to + perform on labels. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateLabelsResponse: + Response message for a labels mutate. + """ + # 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 = [customer_id, operations] + 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, label_service.MutateLabelsRequest): + request = label_service.MutateLabelsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.mutate_labels] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "LabelServiceClient": + 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() + + +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__ = ("LabelServiceClient",) diff --git a/google/ads/googleads/v24/services/services/label_service/transports/README.rst b/google/ads/googleads/v24/services/services/label_service/transports/README.rst new file mode 100644 index 000000000..3adfdf30e --- /dev/null +++ b/google/ads/googleads/v24/services/services/label_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`LabelServiceTransport` is the ABC for all transports. +- public child `LabelServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `LabelServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseLabelServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `LabelServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/label_service/transports/__init__.py b/google/ads/googleads/v24/services/services/label_service/transports/__init__.py new file mode 100644 index 000000000..c76faff26 --- /dev/null +++ b/google/ads/googleads/v24/services/services/label_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import LabelServiceTransport +from .grpc import LabelServiceGrpcTransport +from .grpc_asyncio import LabelServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[LabelServiceTransport]] +_transport_registry["grpc"] = LabelServiceGrpcTransport +_transport_registry["grpc_asyncio"] = LabelServiceGrpcAsyncIOTransport + +__all__ = ( + "LabelServiceTransport", + "LabelServiceGrpcTransport", + "LabelServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/label_service/transports/base.py b/google/ads/googleads/v24/services/services/label_service/transports/base.py new file mode 100644 index 000000000..f4e6f93a1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/label_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import label_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 LabelServiceTransport(abc.ABC): + """Abstract transport class for LabelService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_labels: gapic_v1.method.wrap_method( + self.mutate_labels, + 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 mutate_labels( + self, + ) -> Callable[ + [label_service.MutateLabelsRequest], + Union[ + label_service.MutateLabelsResponse, + Awaitable[label_service.MutateLabelsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("LabelServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/label_service/transports/grpc.py b/google/ads/googleads/v24/services/services/label_service/transports/grpc.py new file mode 100644 index 000000000..e3c4e508a --- /dev/null +++ b/google/ads/googleads/v24/services/services/label_service/transports/grpc.py @@ -0,0 +1,392 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import label_service +from .base import LabelServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.LabelService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.LabelService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class LabelServiceGrpcTransport(LabelServiceTransport): + """gRPC backend transport for LabelService. + + Service to manage labels. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_labels( + self, + ) -> Callable[ + [label_service.MutateLabelsRequest], label_service.MutateLabelsResponse + ]: + r"""Return a callable for the mutate labels method over gRPC. + + Creates, updates, or removes labels. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `LabelError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateLabelsRequest], + ~.MutateLabelsResponse]: + 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 "mutate_labels" not in self._stubs: + self._stubs["mutate_labels"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.LabelService/MutateLabels", + request_serializer=label_service.MutateLabelsRequest.serialize, + response_deserializer=label_service.MutateLabelsResponse.deserialize, + ) + return self._stubs["mutate_labels"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("LabelServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/label_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/label_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..ff70c6577 --- /dev/null +++ b/google/ads/googleads/v24/services/services/label_service/transports/grpc_asyncio.py @@ -0,0 +1,414 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import label_service +from .base import LabelServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.LabelService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.LabelService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class LabelServiceGrpcAsyncIOTransport(LabelServiceTransport): + """gRPC AsyncIO backend transport for LabelService. + + Service to manage labels. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_labels( + self, + ) -> Callable[ + [label_service.MutateLabelsRequest], + Awaitable[label_service.MutateLabelsResponse], + ]: + r"""Return a callable for the mutate labels method over gRPC. + + Creates, updates, or removes labels. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `LabelError <>`__ `MutateError <>`__ + `NewResourceCreationError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateLabelsRequest], + Awaitable[~.MutateLabelsResponse]]: + 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 "mutate_labels" not in self._stubs: + self._stubs["mutate_labels"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.LabelService/MutateLabels", + request_serializer=label_service.MutateLabelsRequest.serialize, + response_deserializer=label_service.MutateLabelsResponse.deserialize, + ) + return self._stubs["mutate_labels"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_labels: self._wrap_method( + self.mutate_labels, + 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" + + +__all__ = ("LabelServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/local_services_lead_service/__init__.py b/google/ads/googleads/v24/services/services/local_services_lead_service/__init__.py new file mode 100644 index 000000000..1d7f806d0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/local_services_lead_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import LocalServicesLeadServiceClient +from .async_client import LocalServicesLeadServiceAsyncClient + +__all__ = ( + "LocalServicesLeadServiceClient", + "LocalServicesLeadServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/local_services_lead_service/async_client.py b/google/ads/googleads/v24/services/services/local_services_lead_service/async_client.py new file mode 100644 index 000000000..ff9561e58 --- /dev/null +++ b/google/ads/googleads/v24/services/services/local_services_lead_service/async_client.py @@ -0,0 +1,496 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import local_services_lead_service +from .transports.base import ( + LocalServicesLeadServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import LocalServicesLeadServiceClient + +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 LocalServicesLeadServiceAsyncClient: + """This service allows management of LocalServicesLead + resources. + """ + + _client: LocalServicesLeadServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = LocalServicesLeadServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = LocalServicesLeadServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + LocalServicesLeadServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = LocalServicesLeadServiceClient._DEFAULT_UNIVERSE + + local_services_lead_path = staticmethod( + LocalServicesLeadServiceClient.local_services_lead_path + ) + parse_local_services_lead_path = staticmethod( + LocalServicesLeadServiceClient.parse_local_services_lead_path + ) + common_billing_account_path = staticmethod( + LocalServicesLeadServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + LocalServicesLeadServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + LocalServicesLeadServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + LocalServicesLeadServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + LocalServicesLeadServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + LocalServicesLeadServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + LocalServicesLeadServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + LocalServicesLeadServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + LocalServicesLeadServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + LocalServicesLeadServiceClient.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: + LocalServicesLeadServiceAsyncClient: The constructed client. + """ + return LocalServicesLeadServiceClient.from_service_account_info.__func__(LocalServicesLeadServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + LocalServicesLeadServiceAsyncClient: The constructed client. + """ + return LocalServicesLeadServiceClient.from_service_account_file.__func__(LocalServicesLeadServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return LocalServicesLeadServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> LocalServicesLeadServiceTransport: + """Returns the transport used by the client instance. + + Returns: + LocalServicesLeadServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = LocalServicesLeadServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + LocalServicesLeadServiceTransport, + Callable[..., LocalServicesLeadServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the local services lead 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,LocalServicesLeadServiceTransport,Callable[..., LocalServicesLeadServiceTransport]]]): + 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 LocalServicesLeadServiceTransport 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 = LocalServicesLeadServiceClient( + 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.ads.googleads.v24.services.LocalServicesLeadServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.LocalServicesLeadService", + "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.ads.googleads.v24.services.LocalServicesLeadService", + "credentialsType": None, + } + ), + ) + + async def append_lead_conversation( + self, + request: Optional[ + Union[ + local_services_lead_service.AppendLeadConversationRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + conversations: Optional[ + MutableSequence[local_services_lead_service.Conversation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> local_services_lead_service.AppendLeadConversationResponse: + r"""RPC to append Local Services Lead Conversation + resources to Local Services Lead resources. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.AppendLeadConversationRequest, dict]]): + The request object. Request message for + [LocalServicesLeadService.AppendLeadConversation][google.ads.googleads.v24.services.LocalServicesLeadService.AppendLeadConversation]. + customer_id (:class:`str`): + Required. The Id of the customer + which owns the leads onto which the + conversations will be appended. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + conversations (:class:`MutableSequence[google.ads.googleads.v24.services.types.Conversation]`): + Required. Conversations that are + being appended. + + This corresponds to the ``conversations`` 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.ads.googleads.v24.services.types.AppendLeadConversationResponse: + Response message for + [LocalServicesLeadService.AppendLeadConversation][google.ads.googleads.v24.services.LocalServicesLeadService.AppendLeadConversation]. + + """ + # 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 = [customer_id, conversations] + 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, local_services_lead_service.AppendLeadConversationRequest + ): + request = local_services_lead_service.AppendLeadConversationRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if conversations: + request.conversations.extend(conversations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.append_lead_conversation + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 provide_lead_feedback( + self, + request: Optional[ + Union[local_services_lead_service.ProvideLeadFeedbackRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> local_services_lead_service.ProvideLeadFeedbackResponse: + r"""RPC to provide feedback on Local Services Lead + resources. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ProvideLeadFeedbackRequest, dict]]): + The request object. Request message for + [LocalServicesLeadService.ProvideLeadFeedback][google.ads.googleads.v24.services.LocalServicesLeadService.ProvideLeadFeedback]. + 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.googleads.v24.services.types.ProvideLeadFeedbackResponse: + Response message for + [LocalServicesLeadService.ProvideLeadFeedback][google.ads.googleads.v24.services.LocalServicesLeadService.ProvideLeadFeedback]. + + """ + # 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, local_services_lead_service.ProvideLeadFeedbackRequest + ): + request = local_services_lead_service.ProvideLeadFeedbackRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.provide_lead_feedback + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_name),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "LocalServicesLeadServiceAsyncClient": + 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__ = ("LocalServicesLeadServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/local_services_lead_service/client.py b/google/ads/googleads/v24/services/services/local_services_lead_service/client.py new file mode 100644 index 000000000..22d2714e8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/local_services_lead_service/client.py @@ -0,0 +1,974 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import local_services_lead_service +from .transports.base import ( + LocalServicesLeadServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import LocalServicesLeadServiceGrpcTransport +from .transports.grpc_asyncio import ( + LocalServicesLeadServiceGrpcAsyncIOTransport, +) + + +class LocalServicesLeadServiceClientMeta(type): + """Metaclass for the LocalServicesLeadService 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[LocalServicesLeadServiceTransport]] + _transport_registry["grpc"] = LocalServicesLeadServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + LocalServicesLeadServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[LocalServicesLeadServiceTransport]: + """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 LocalServicesLeadServiceClient( + metaclass=LocalServicesLeadServiceClientMeta +): + """This service allows management of LocalServicesLead + resources. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + LocalServicesLeadServiceClient: 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: + LocalServicesLeadServiceClient: 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) -> LocalServicesLeadServiceTransport: + """Returns the transport used by the client instance. + + Returns: + LocalServicesLeadServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def local_services_lead_path( + customer_id: str, + local_services_lead_id: str, + ) -> str: + """Returns a fully-qualified local_services_lead string.""" + return "customers/{customer_id}/localServicesLeads/{local_services_lead_id}".format( + customer_id=customer_id, + local_services_lead_id=local_services_lead_id, + ) + + @staticmethod + def parse_local_services_lead_path(path: str) -> Dict[str, str]: + """Parses a local_services_lead path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/localServicesLeads/(?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 = ( + LocalServicesLeadServiceClient._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 = ( + LocalServicesLeadServiceClient._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 + ): + """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 = LocalServicesLeadServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = LocalServicesLeadServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = LocalServicesLeadServiceClient._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 = LocalServicesLeadServiceClient._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): + """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, + LocalServicesLeadServiceTransport, + Callable[..., LocalServicesLeadServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the local services lead 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,LocalServicesLeadServiceTransport,Callable[..., LocalServicesLeadServiceTransport]]]): + 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 LocalServicesLeadServiceTransport 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, + ) = LocalServicesLeadServiceClient._read_environment_variables() + self._client_cert_source = ( + LocalServicesLeadServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + LocalServicesLeadServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, LocalServicesLeadServiceTransport + ) + if transport_provided: + # transport is a LocalServicesLeadServiceTransport 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(LocalServicesLeadServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or LocalServicesLeadServiceClient._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[LocalServicesLeadServiceTransport], + Callable[..., LocalServicesLeadServiceTransport], + ] = ( + LocalServicesLeadServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., LocalServicesLeadServiceTransport], 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.ads.googleads.v24.services.LocalServicesLeadServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.LocalServicesLeadService", + "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.ads.googleads.v24.services.LocalServicesLeadService", + "credentialsType": None, + } + ), + ) + + def append_lead_conversation( + self, + request: Optional[ + Union[ + local_services_lead_service.AppendLeadConversationRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + conversations: Optional[ + MutableSequence[local_services_lead_service.Conversation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> local_services_lead_service.AppendLeadConversationResponse: + r"""RPC to append Local Services Lead Conversation + resources to Local Services Lead resources. + + Args: + request (Union[google.ads.googleads.v24.services.types.AppendLeadConversationRequest, dict]): + The request object. Request message for + [LocalServicesLeadService.AppendLeadConversation][google.ads.googleads.v24.services.LocalServicesLeadService.AppendLeadConversation]. + customer_id (str): + Required. The Id of the customer + which owns the leads onto which the + conversations will be appended. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + conversations (MutableSequence[google.ads.googleads.v24.services.types.Conversation]): + Required. Conversations that are + being appended. + + This corresponds to the ``conversations`` 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.ads.googleads.v24.services.types.AppendLeadConversationResponse: + Response message for + [LocalServicesLeadService.AppendLeadConversation][google.ads.googleads.v24.services.LocalServicesLeadService.AppendLeadConversation]. + + """ + # 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 = [customer_id, conversations] + 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, local_services_lead_service.AppendLeadConversationRequest + ): + request = local_services_lead_service.AppendLeadConversationRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if conversations is not None: + request.conversations = conversations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.append_lead_conversation + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 provide_lead_feedback( + self, + request: Optional[ + Union[local_services_lead_service.ProvideLeadFeedbackRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> local_services_lead_service.ProvideLeadFeedbackResponse: + r"""RPC to provide feedback on Local Services Lead + resources. + + Args: + request (Union[google.ads.googleads.v24.services.types.ProvideLeadFeedbackRequest, dict]): + The request object. Request message for + [LocalServicesLeadService.ProvideLeadFeedback][google.ads.googleads.v24.services.LocalServicesLeadService.ProvideLeadFeedback]. + 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.googleads.v24.services.types.ProvideLeadFeedbackResponse: + Response message for + [LocalServicesLeadService.ProvideLeadFeedback][google.ads.googleads.v24.services.LocalServicesLeadService.ProvideLeadFeedback]. + + """ + # 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, local_services_lead_service.ProvideLeadFeedbackRequest + ): + request = local_services_lead_service.ProvideLeadFeedbackRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.provide_lead_feedback + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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) -> "LocalServicesLeadServiceClient": + 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() + + +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__ = ("LocalServicesLeadServiceClient",) diff --git a/google/ads/googleads/v24/services/services/local_services_lead_service/transports/README.rst b/google/ads/googleads/v24/services/services/local_services_lead_service/transports/README.rst new file mode 100644 index 000000000..29b286c9a --- /dev/null +++ b/google/ads/googleads/v24/services/services/local_services_lead_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`LocalServicesLeadServiceTransport` is the ABC for all transports. +- public child `LocalServicesLeadServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `LocalServicesLeadServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseLocalServicesLeadServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `LocalServicesLeadServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/local_services_lead_service/transports/__init__.py b/google/ads/googleads/v24/services/services/local_services_lead_service/transports/__init__.py new file mode 100644 index 000000000..ea38b42f9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/local_services_lead_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import LocalServicesLeadServiceTransport +from .grpc import LocalServicesLeadServiceGrpcTransport +from .grpc_asyncio import LocalServicesLeadServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[LocalServicesLeadServiceTransport]] +_transport_registry["grpc"] = LocalServicesLeadServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + LocalServicesLeadServiceGrpcAsyncIOTransport +) + +__all__ = ( + "LocalServicesLeadServiceTransport", + "LocalServicesLeadServiceGrpcTransport", + "LocalServicesLeadServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/local_services_lead_service/transports/base.py b/google/ads/googleads/v24/services/services/local_services_lead_service/transports/base.py new file mode 100644 index 000000000..d3fe848df --- /dev/null +++ b/google/ads/googleads/v24/services/services/local_services_lead_service/transports/base.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import local_services_lead_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 LocalServicesLeadServiceTransport(abc.ABC): + """Abstract transport class for LocalServicesLeadService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.append_lead_conversation: gapic_v1.method.wrap_method( + self.append_lead_conversation, + default_timeout=None, + client_info=client_info, + ), + self.provide_lead_feedback: gapic_v1.method.wrap_method( + self.provide_lead_feedback, + 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 append_lead_conversation( + self, + ) -> Callable[ + [local_services_lead_service.AppendLeadConversationRequest], + Union[ + local_services_lead_service.AppendLeadConversationResponse, + Awaitable[ + local_services_lead_service.AppendLeadConversationResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def provide_lead_feedback( + self, + ) -> Callable[ + [local_services_lead_service.ProvideLeadFeedbackRequest], + Union[ + local_services_lead_service.ProvideLeadFeedbackResponse, + Awaitable[local_services_lead_service.ProvideLeadFeedbackResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("LocalServicesLeadServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/local_services_lead_service/transports/grpc.py b/google/ads/googleads/v24/services/services/local_services_lead_service/transports/grpc.py new file mode 100644 index 000000000..2cea5f3ab --- /dev/null +++ b/google/ads/googleads/v24/services/services/local_services_lead_service/transports/grpc.py @@ -0,0 +1,417 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import local_services_lead_service +from .base import LocalServicesLeadServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.LocalServicesLeadService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.LocalServicesLeadService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class LocalServicesLeadServiceGrpcTransport(LocalServicesLeadServiceTransport): + """gRPC backend transport for LocalServicesLeadService. + + This service allows management of LocalServicesLead + resources. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 append_lead_conversation( + self, + ) -> Callable[ + [local_services_lead_service.AppendLeadConversationRequest], + local_services_lead_service.AppendLeadConversationResponse, + ]: + r"""Return a callable for the append lead conversation method over gRPC. + + RPC to append Local Services Lead Conversation + resources to Local Services Lead resources. + + Returns: + Callable[[~.AppendLeadConversationRequest], + ~.AppendLeadConversationResponse]: + 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 "append_lead_conversation" not in self._stubs: + self._stubs["append_lead_conversation"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.LocalServicesLeadService/AppendLeadConversation", + request_serializer=local_services_lead_service.AppendLeadConversationRequest.serialize, + response_deserializer=local_services_lead_service.AppendLeadConversationResponse.deserialize, + ) + ) + return self._stubs["append_lead_conversation"] + + @property + def provide_lead_feedback( + self, + ) -> Callable[ + [local_services_lead_service.ProvideLeadFeedbackRequest], + local_services_lead_service.ProvideLeadFeedbackResponse, + ]: + r"""Return a callable for the provide lead feedback method over gRPC. + + RPC to provide feedback on Local Services Lead + resources. + + Returns: + Callable[[~.ProvideLeadFeedbackRequest], + ~.ProvideLeadFeedbackResponse]: + 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 "provide_lead_feedback" not in self._stubs: + self._stubs["provide_lead_feedback"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.LocalServicesLeadService/ProvideLeadFeedback", + request_serializer=local_services_lead_service.ProvideLeadFeedbackRequest.serialize, + response_deserializer=local_services_lead_service.ProvideLeadFeedbackResponse.deserialize, + ) + ) + return self._stubs["provide_lead_feedback"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("LocalServicesLeadServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/local_services_lead_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/local_services_lead_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..0057c5c43 --- /dev/null +++ b/google/ads/googleads/v24/services/services/local_services_lead_service/transports/grpc_asyncio.py @@ -0,0 +1,445 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import local_services_lead_service +from .base import LocalServicesLeadServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.LocalServicesLeadService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.LocalServicesLeadService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class LocalServicesLeadServiceGrpcAsyncIOTransport( + LocalServicesLeadServiceTransport +): + """gRPC AsyncIO backend transport for LocalServicesLeadService. + + This service allows management of LocalServicesLead + resources. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 append_lead_conversation( + self, + ) -> Callable[ + [local_services_lead_service.AppendLeadConversationRequest], + Awaitable[local_services_lead_service.AppendLeadConversationResponse], + ]: + r"""Return a callable for the append lead conversation method over gRPC. + + RPC to append Local Services Lead Conversation + resources to Local Services Lead resources. + + Returns: + Callable[[~.AppendLeadConversationRequest], + Awaitable[~.AppendLeadConversationResponse]]: + 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 "append_lead_conversation" not in self._stubs: + self._stubs["append_lead_conversation"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.LocalServicesLeadService/AppendLeadConversation", + request_serializer=local_services_lead_service.AppendLeadConversationRequest.serialize, + response_deserializer=local_services_lead_service.AppendLeadConversationResponse.deserialize, + ) + ) + return self._stubs["append_lead_conversation"] + + @property + def provide_lead_feedback( + self, + ) -> Callable[ + [local_services_lead_service.ProvideLeadFeedbackRequest], + Awaitable[local_services_lead_service.ProvideLeadFeedbackResponse], + ]: + r"""Return a callable for the provide lead feedback method over gRPC. + + RPC to provide feedback on Local Services Lead + resources. + + Returns: + Callable[[~.ProvideLeadFeedbackRequest], + Awaitable[~.ProvideLeadFeedbackResponse]]: + 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 "provide_lead_feedback" not in self._stubs: + self._stubs["provide_lead_feedback"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.LocalServicesLeadService/ProvideLeadFeedback", + request_serializer=local_services_lead_service.ProvideLeadFeedbackRequest.serialize, + response_deserializer=local_services_lead_service.ProvideLeadFeedbackResponse.deserialize, + ) + ) + return self._stubs["provide_lead_feedback"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.append_lead_conversation: self._wrap_method( + self.append_lead_conversation, + default_timeout=None, + client_info=client_info, + ), + self.provide_lead_feedback: self._wrap_method( + self.provide_lead_feedback, + 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" + + +__all__ = ("LocalServicesLeadServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/offline_user_data_job_service/__init__.py b/google/ads/googleads/v24/services/services/offline_user_data_job_service/__init__.py new file mode 100644 index 000000000..af4c0d093 --- /dev/null +++ b/google/ads/googleads/v24/services/services/offline_user_data_job_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import OfflineUserDataJobServiceClient +from .async_client import OfflineUserDataJobServiceAsyncClient + +__all__ = ( + "OfflineUserDataJobServiceClient", + "OfflineUserDataJobServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/offline_user_data_job_service/async_client.py b/google/ads/googleads/v24/services/services/offline_user_data_job_service/async_client.py new file mode 100644 index 000000000..9d51e32b0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/offline_user_data_job_service/async_client.py @@ -0,0 +1,682 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.resources.types import offline_user_data_job +from google.ads.googleads.v24.services.types import ( + offline_user_data_job_service, +) +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore +from google.protobuf import empty_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + OfflineUserDataJobServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import OfflineUserDataJobServiceClient + +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 OfflineUserDataJobServiceAsyncClient: + """Service to manage offline user data jobs.""" + + _client: OfflineUserDataJobServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = OfflineUserDataJobServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + OfflineUserDataJobServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + OfflineUserDataJobServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = OfflineUserDataJobServiceClient._DEFAULT_UNIVERSE + + offline_user_data_job_path = staticmethod( + OfflineUserDataJobServiceClient.offline_user_data_job_path + ) + parse_offline_user_data_job_path = staticmethod( + OfflineUserDataJobServiceClient.parse_offline_user_data_job_path + ) + common_billing_account_path = staticmethod( + OfflineUserDataJobServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + OfflineUserDataJobServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + OfflineUserDataJobServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + OfflineUserDataJobServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + OfflineUserDataJobServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + OfflineUserDataJobServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + OfflineUserDataJobServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + OfflineUserDataJobServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + OfflineUserDataJobServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + OfflineUserDataJobServiceClient.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: + OfflineUserDataJobServiceAsyncClient: The constructed client. + """ + return OfflineUserDataJobServiceClient.from_service_account_info.__func__(OfflineUserDataJobServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + OfflineUserDataJobServiceAsyncClient: The constructed client. + """ + return OfflineUserDataJobServiceClient.from_service_account_file.__func__(OfflineUserDataJobServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return OfflineUserDataJobServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> OfflineUserDataJobServiceTransport: + """Returns the transport used by the client instance. + + Returns: + OfflineUserDataJobServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = OfflineUserDataJobServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + OfflineUserDataJobServiceTransport, + Callable[..., OfflineUserDataJobServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the offline user data job 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,OfflineUserDataJobServiceTransport,Callable[..., OfflineUserDataJobServiceTransport]]]): + 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 OfflineUserDataJobServiceTransport 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 = OfflineUserDataJobServiceClient( + 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.ads.googleads.v24.services.OfflineUserDataJobServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.OfflineUserDataJobService", + "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.ads.googleads.v24.services.OfflineUserDataJobService", + "credentialsType": None, + } + ), + ) + + async def create_offline_user_data_job( + self, + request: Optional[ + Union[ + offline_user_data_job_service.CreateOfflineUserDataJobRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + job: Optional[offline_user_data_job.OfflineUserDataJob] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> offline_user_data_job_service.CreateOfflineUserDataJobResponse: + r"""Creates an offline user data job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `NotAllowlistedError <>`__ `OfflineUserDataJobError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.CreateOfflineUserDataJobRequest, dict]]): + The request object. Request message for + [OfflineUserDataJobService.CreateOfflineUserDataJob][google.ads.googleads.v24.services.OfflineUserDataJobService.CreateOfflineUserDataJob]. + customer_id (:class:`str`): + Required. The ID of the customer for + which to create an offline user data + job. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + job (:class:`google.ads.googleads.v24.resources.types.OfflineUserDataJob`): + Required. The offline user data job + to be created. + + This corresponds to the ``job`` 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.ads.googleads.v24.services.types.CreateOfflineUserDataJobResponse: + Response message for + [OfflineUserDataJobService.CreateOfflineUserDataJob][google.ads.googleads.v24.services.OfflineUserDataJobService.CreateOfflineUserDataJob]. + + """ + # 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 = [customer_id, job] + 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, + offline_user_data_job_service.CreateOfflineUserDataJobRequest, + ): + request = ( + offline_user_data_job_service.CreateOfflineUserDataJobRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if job is not None: + request.job = job + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.create_offline_user_data_job + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 add_offline_user_data_job_operations( + self, + request: Optional[ + Union[ + offline_user_data_job_service.AddOfflineUserDataJobOperationsRequest, + dict, + ] + ] = None, + *, + resource_name: Optional[str] = None, + operations: Optional[ + MutableSequence[ + offline_user_data_job_service.OfflineUserDataJobOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> offline_user_data_job_service.AddOfflineUserDataJobOperationsResponse: + r"""Adds operations to the offline user data job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `OfflineUserDataJobError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.AddOfflineUserDataJobOperationsRequest, dict]]): + The request object. Request message for + [OfflineUserDataJobService.AddOfflineUserDataJobOperations][google.ads.googleads.v24.services.OfflineUserDataJobService.AddOfflineUserDataJobOperations]. + resource_name (:class:`str`): + Required. The resource name of the + OfflineUserDataJob. + + This corresponds to the ``resource_name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.OfflineUserDataJobOperation]`): + Required. The list of operations to + be done. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.AddOfflineUserDataJobOperationsResponse: + Response message for + [OfflineUserDataJobService.AddOfflineUserDataJobOperations][google.ads.googleads.v24.services.OfflineUserDataJobService.AddOfflineUserDataJobOperations]. + + """ + # 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 = [resource_name, operations] + 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, + offline_user_data_job_service.AddOfflineUserDataJobOperationsRequest, + ): + request = offline_user_data_job_service.AddOfflineUserDataJobOperationsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.add_offline_user_data_job_operations + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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 run_offline_user_data_job( + self, + request: Optional[ + Union[ + offline_user_data_job_service.RunOfflineUserDataJobRequest, dict + ] + ] = None, + *, + resource_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]]] = (), + ) -> operation_async.AsyncOperation: + r"""Runs the offline user data job. + + When finished, the long running operation will contain the + processing result or failure information, if any. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `OfflineUserDataJobError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.RunOfflineUserDataJobRequest, dict]]): + The request object. Request message for + [OfflineUserDataJobService.RunOfflineUserDataJob][google.ads.googleads.v24.services.OfflineUserDataJobService.RunOfflineUserDataJob]. + resource_name (:class:`str`): + Required. The resource name of the + OfflineUserDataJob to run. + + This corresponds to the ``resource_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.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 = [resource_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, offline_user_data_job_service.RunOfflineUserDataJobRequest + ): + request = ( + offline_user_data_job_service.RunOfflineUserDataJobRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.run_offline_user_data_job + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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=offline_user_data_job.OfflineUserDataJobMetadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "OfflineUserDataJobServiceAsyncClient": + 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__ = ("OfflineUserDataJobServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/offline_user_data_job_service/client.py b/google/ads/googleads/v24/services/services/offline_user_data_job_service/client.py new file mode 100644 index 000000000..3234dfa2a --- /dev/null +++ b/google/ads/googleads/v24/services/services/offline_user_data_job_service/client.py @@ -0,0 +1,1160 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.resources.types import offline_user_data_job +from google.ads.googleads.v24.services.types import ( + offline_user_data_job_service, +) +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore +from google.protobuf import empty_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + OfflineUserDataJobServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import OfflineUserDataJobServiceGrpcTransport +from .transports.grpc_asyncio import ( + OfflineUserDataJobServiceGrpcAsyncIOTransport, +) + + +class OfflineUserDataJobServiceClientMeta(type): + """Metaclass for the OfflineUserDataJobService 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[OfflineUserDataJobServiceTransport]] + _transport_registry["grpc"] = OfflineUserDataJobServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + OfflineUserDataJobServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[OfflineUserDataJobServiceTransport]: + """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 OfflineUserDataJobServiceClient( + metaclass=OfflineUserDataJobServiceClientMeta +): + """Service to manage offline user data jobs.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + OfflineUserDataJobServiceClient: 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: + OfflineUserDataJobServiceClient: 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) -> OfflineUserDataJobServiceTransport: + """Returns the transport used by the client instance. + + Returns: + OfflineUserDataJobServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def offline_user_data_job_path( + customer_id: str, + offline_user_data_update_id: str, + ) -> str: + """Returns a fully-qualified offline_user_data_job string.""" + return "customers/{customer_id}/offlineUserDataJobs/{offline_user_data_update_id}".format( + customer_id=customer_id, + offline_user_data_update_id=offline_user_data_update_id, + ) + + @staticmethod + def parse_offline_user_data_job_path(path: str) -> Dict[str, str]: + """Parses a offline_user_data_job path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/offlineUserDataJobs/(?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 = ( + OfflineUserDataJobServiceClient._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 = ( + OfflineUserDataJobServiceClient._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 + ): + """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 = ( + OfflineUserDataJobServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = OfflineUserDataJobServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = OfflineUserDataJobServiceClient._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 = OfflineUserDataJobServiceClient._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): + """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, + OfflineUserDataJobServiceTransport, + Callable[..., OfflineUserDataJobServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the offline user data job 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,OfflineUserDataJobServiceTransport,Callable[..., OfflineUserDataJobServiceTransport]]]): + 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 OfflineUserDataJobServiceTransport 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, + ) = OfflineUserDataJobServiceClient._read_environment_variables() + self._client_cert_source = ( + OfflineUserDataJobServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + OfflineUserDataJobServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, OfflineUserDataJobServiceTransport + ) + if transport_provided: + # transport is a OfflineUserDataJobServiceTransport 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( + OfflineUserDataJobServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or OfflineUserDataJobServiceClient._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[OfflineUserDataJobServiceTransport], + Callable[..., OfflineUserDataJobServiceTransport], + ] = ( + OfflineUserDataJobServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., OfflineUserDataJobServiceTransport], 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.ads.googleads.v24.services.OfflineUserDataJobServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.OfflineUserDataJobService", + "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.ads.googleads.v24.services.OfflineUserDataJobService", + "credentialsType": None, + } + ), + ) + + def create_offline_user_data_job( + self, + request: Optional[ + Union[ + offline_user_data_job_service.CreateOfflineUserDataJobRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + job: Optional[offline_user_data_job.OfflineUserDataJob] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> offline_user_data_job_service.CreateOfflineUserDataJobResponse: + r"""Creates an offline user data job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `NotAllowlistedError <>`__ `OfflineUserDataJobError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.CreateOfflineUserDataJobRequest, dict]): + The request object. Request message for + [OfflineUserDataJobService.CreateOfflineUserDataJob][google.ads.googleads.v24.services.OfflineUserDataJobService.CreateOfflineUserDataJob]. + customer_id (str): + Required. The ID of the customer for + which to create an offline user data + job. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + job (google.ads.googleads.v24.resources.types.OfflineUserDataJob): + Required. The offline user data job + to be created. + + This corresponds to the ``job`` 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.ads.googleads.v24.services.types.CreateOfflineUserDataJobResponse: + Response message for + [OfflineUserDataJobService.CreateOfflineUserDataJob][google.ads.googleads.v24.services.OfflineUserDataJobService.CreateOfflineUserDataJob]. + + """ + # 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 = [customer_id, job] + 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, + offline_user_data_job_service.CreateOfflineUserDataJobRequest, + ): + request = ( + offline_user_data_job_service.CreateOfflineUserDataJobRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if job is not None: + request.job = job + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.create_offline_user_data_job + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 add_offline_user_data_job_operations( + self, + request: Optional[ + Union[ + offline_user_data_job_service.AddOfflineUserDataJobOperationsRequest, + dict, + ] + ] = None, + *, + resource_name: Optional[str] = None, + operations: Optional[ + MutableSequence[ + offline_user_data_job_service.OfflineUserDataJobOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> offline_user_data_job_service.AddOfflineUserDataJobOperationsResponse: + r"""Adds operations to the offline user data job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `OfflineUserDataJobError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.AddOfflineUserDataJobOperationsRequest, dict]): + The request object. Request message for + [OfflineUserDataJobService.AddOfflineUserDataJobOperations][google.ads.googleads.v24.services.OfflineUserDataJobService.AddOfflineUserDataJobOperations]. + resource_name (str): + Required. The resource name of the + OfflineUserDataJob. + + This corresponds to the ``resource_name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.OfflineUserDataJobOperation]): + Required. The list of operations to + be done. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.AddOfflineUserDataJobOperationsResponse: + Response message for + [OfflineUserDataJobService.AddOfflineUserDataJobOperations][google.ads.googleads.v24.services.OfflineUserDataJobService.AddOfflineUserDataJobOperations]. + + """ + # 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 = [resource_name, operations] + 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, + offline_user_data_job_service.AddOfflineUserDataJobOperationsRequest, + ): + request = offline_user_data_job_service.AddOfflineUserDataJobOperationsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.add_offline_user_data_job_operations + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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 run_offline_user_data_job( + self, + request: Optional[ + Union[ + offline_user_data_job_service.RunOfflineUserDataJobRequest, dict + ] + ] = None, + *, + resource_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]]] = (), + ) -> operation.Operation: + r"""Runs the offline user data job. + + When finished, the long running operation will contain the + processing result or failure information, if any. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `OfflineUserDataJobError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.RunOfflineUserDataJobRequest, dict]): + The request object. Request message for + [OfflineUserDataJobService.RunOfflineUserDataJob][google.ads.googleads.v24.services.OfflineUserDataJobService.RunOfflineUserDataJob]. + resource_name (str): + Required. The resource name of the + OfflineUserDataJob to run. + + This corresponds to the ``resource_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.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 = [resource_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, offline_user_data_job_service.RunOfflineUserDataJobRequest + ): + request = ( + offline_user_data_job_service.RunOfflineUserDataJobRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.run_offline_user_data_job + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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=offline_user_data_job.OfflineUserDataJobMetadata, + ) + + # Done; return the response. + return response + + def __enter__(self) -> "OfflineUserDataJobServiceClient": + 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() + + +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__ = ("OfflineUserDataJobServiceClient",) diff --git a/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/README.rst b/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/README.rst new file mode 100644 index 000000000..fc76d7bf3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`OfflineUserDataJobServiceTransport` is the ABC for all transports. +- public child `OfflineUserDataJobServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `OfflineUserDataJobServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseOfflineUserDataJobServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `OfflineUserDataJobServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/__init__.py b/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/__init__.py new file mode 100644 index 000000000..3189b3ac1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import OfflineUserDataJobServiceTransport +from .grpc import OfflineUserDataJobServiceGrpcTransport +from .grpc_asyncio import OfflineUserDataJobServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[OfflineUserDataJobServiceTransport]] +_transport_registry["grpc"] = OfflineUserDataJobServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + OfflineUserDataJobServiceGrpcAsyncIOTransport +) + +__all__ = ( + "OfflineUserDataJobServiceTransport", + "OfflineUserDataJobServiceGrpcTransport", + "OfflineUserDataJobServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/base.py b/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/base.py new file mode 100644 index 000000000..cde13a397 --- /dev/null +++ b/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/base.py @@ -0,0 +1,216 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + offline_user_data_job_service, +) +from google.longrunning import operations_pb2 # type: ignore + +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 OfflineUserDataJobServiceTransport(abc.ABC): + """Abstract transport class for OfflineUserDataJobService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.create_offline_user_data_job: gapic_v1.method.wrap_method( + self.create_offline_user_data_job, + default_timeout=None, + client_info=client_info, + ), + self.add_offline_user_data_job_operations: gapic_v1.method.wrap_method( + self.add_offline_user_data_job_operations, + default_timeout=None, + client_info=client_info, + ), + self.run_offline_user_data_job: gapic_v1.method.wrap_method( + self.run_offline_user_data_job, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def operations_client(self): + """Return the client designed to process long-running operations.""" + raise NotImplementedError() + + @property + def create_offline_user_data_job( + self, + ) -> Callable[ + [offline_user_data_job_service.CreateOfflineUserDataJobRequest], + Union[ + offline_user_data_job_service.CreateOfflineUserDataJobResponse, + Awaitable[ + offline_user_data_job_service.CreateOfflineUserDataJobResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def add_offline_user_data_job_operations( + self, + ) -> Callable[ + [offline_user_data_job_service.AddOfflineUserDataJobOperationsRequest], + Union[ + offline_user_data_job_service.AddOfflineUserDataJobOperationsResponse, + Awaitable[ + offline_user_data_job_service.AddOfflineUserDataJobOperationsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def run_offline_user_data_job( + self, + ) -> Callable[ + [offline_user_data_job_service.RunOfflineUserDataJobRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("OfflineUserDataJobServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/grpc.py b/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/grpc.py new file mode 100644 index 000000000..380d1455d --- /dev/null +++ b/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/grpc.py @@ -0,0 +1,490 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import operations_v1 +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + offline_user_data_job_service, +) +from google.longrunning import operations_pb2 # type: ignore +from .base import OfflineUserDataJobServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.OfflineUserDataJobService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.OfflineUserDataJobService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class OfflineUserDataJobServiceGrpcTransport( + OfflineUserDataJobServiceTransport +): + """gRPC backend transport for OfflineUserDataJobService. + + Service to manage offline user data jobs. + + 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 = "googleads.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: 'googleads.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. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client: Optional[operations_v1.OperationsClient] = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if 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 = "googleads.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 operations_client(self) -> operations_v1.OperationsClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Quick check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsClient( + self._logged_channel + ) + + # Return the client from cache. + return self._operations_client + + @property + def create_offline_user_data_job( + self, + ) -> Callable[ + [offline_user_data_job_service.CreateOfflineUserDataJobRequest], + offline_user_data_job_service.CreateOfflineUserDataJobResponse, + ]: + r"""Return a callable for the create offline user data job method over gRPC. + + Creates an offline user data job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `NotAllowlistedError <>`__ `OfflineUserDataJobError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.CreateOfflineUserDataJobRequest], + ~.CreateOfflineUserDataJobResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_offline_user_data_job" not in self._stubs: + self._stubs["create_offline_user_data_job"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.OfflineUserDataJobService/CreateOfflineUserDataJob", + request_serializer=offline_user_data_job_service.CreateOfflineUserDataJobRequest.serialize, + response_deserializer=offline_user_data_job_service.CreateOfflineUserDataJobResponse.deserialize, + ) + ) + return self._stubs["create_offline_user_data_job"] + + @property + def add_offline_user_data_job_operations( + self, + ) -> Callable[ + [offline_user_data_job_service.AddOfflineUserDataJobOperationsRequest], + offline_user_data_job_service.AddOfflineUserDataJobOperationsResponse, + ]: + r"""Return a callable for the add offline user data job + operations method over gRPC. + + Adds operations to the offline user data job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `OfflineUserDataJobError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.AddOfflineUserDataJobOperationsRequest], + ~.AddOfflineUserDataJobOperationsResponse]: + 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 "add_offline_user_data_job_operations" not in self._stubs: + self._stubs["add_offline_user_data_job_operations"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.OfflineUserDataJobService/AddOfflineUserDataJobOperations", + request_serializer=offline_user_data_job_service.AddOfflineUserDataJobOperationsRequest.serialize, + response_deserializer=offline_user_data_job_service.AddOfflineUserDataJobOperationsResponse.deserialize, + ) + ) + return self._stubs["add_offline_user_data_job_operations"] + + @property + def run_offline_user_data_job( + self, + ) -> Callable[ + [offline_user_data_job_service.RunOfflineUserDataJobRequest], + operations_pb2.Operation, + ]: + r"""Return a callable for the run offline user data job method over gRPC. + + Runs the offline user data job. + + When finished, the long running operation will contain the + processing result or failure information, if any. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `OfflineUserDataJobError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.RunOfflineUserDataJobRequest], + ~.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 "run_offline_user_data_job" not in self._stubs: + self._stubs["run_offline_user_data_job"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.OfflineUserDataJobService/RunOfflineUserDataJob", + request_serializer=offline_user_data_job_service.RunOfflineUserDataJobRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + ) + return self._stubs["run_offline_user_data_job"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("OfflineUserDataJobServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..a0f78ff65 --- /dev/null +++ b/google/ads/googleads/v24/services/services/offline_user_data_job_service/transports/grpc_asyncio.py @@ -0,0 +1,527 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.api_core import operations_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + offline_user_data_job_service, +) +from google.longrunning import operations_pb2 # type: ignore +from .base import OfflineUserDataJobServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.OfflineUserDataJobService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.OfflineUserDataJobService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class OfflineUserDataJobServiceGrpcAsyncIOTransport( + OfflineUserDataJobServiceTransport +): + """gRPC AsyncIO backend transport for OfflineUserDataJobService. + + Service to manage offline user data jobs. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client: Optional[ + operations_v1.OperationsAsyncClient + ] = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if 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 operations_client(self) -> operations_v1.OperationsAsyncClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Quick check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsAsyncClient( + self._logged_channel + ) + + # Return the client from cache. + return self._operations_client + + @property + def create_offline_user_data_job( + self, + ) -> Callable[ + [offline_user_data_job_service.CreateOfflineUserDataJobRequest], + Awaitable[ + offline_user_data_job_service.CreateOfflineUserDataJobResponse + ], + ]: + r"""Return a callable for the create offline user data job method over gRPC. + + Creates an offline user data job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `NotAllowlistedError <>`__ `OfflineUserDataJobError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.CreateOfflineUserDataJobRequest], + Awaitable[~.CreateOfflineUserDataJobResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_offline_user_data_job" not in self._stubs: + self._stubs["create_offline_user_data_job"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.OfflineUserDataJobService/CreateOfflineUserDataJob", + request_serializer=offline_user_data_job_service.CreateOfflineUserDataJobRequest.serialize, + response_deserializer=offline_user_data_job_service.CreateOfflineUserDataJobResponse.deserialize, + ) + ) + return self._stubs["create_offline_user_data_job"] + + @property + def add_offline_user_data_job_operations( + self, + ) -> Callable[ + [offline_user_data_job_service.AddOfflineUserDataJobOperationsRequest], + Awaitable[ + offline_user_data_job_service.AddOfflineUserDataJobOperationsResponse + ], + ]: + r"""Return a callable for the add offline user data job + operations method over gRPC. + + Adds operations to the offline user data job. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `OfflineUserDataJobError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.AddOfflineUserDataJobOperationsRequest], + Awaitable[~.AddOfflineUserDataJobOperationsResponse]]: + 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 "add_offline_user_data_job_operations" not in self._stubs: + self._stubs["add_offline_user_data_job_operations"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.OfflineUserDataJobService/AddOfflineUserDataJobOperations", + request_serializer=offline_user_data_job_service.AddOfflineUserDataJobOperationsRequest.serialize, + response_deserializer=offline_user_data_job_service.AddOfflineUserDataJobOperationsResponse.deserialize, + ) + ) + return self._stubs["add_offline_user_data_job_operations"] + + @property + def run_offline_user_data_job( + self, + ) -> Callable[ + [offline_user_data_job_service.RunOfflineUserDataJobRequest], + Awaitable[operations_pb2.Operation], + ]: + r"""Return a callable for the run offline user data job method over gRPC. + + Runs the offline user data job. + + When finished, the long running operation will contain the + processing result or failure information, if any. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `HeaderError <>`__ `InternalError <>`__ + `OfflineUserDataJobError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.RunOfflineUserDataJobRequest], + 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 "run_offline_user_data_job" not in self._stubs: + self._stubs["run_offline_user_data_job"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.OfflineUserDataJobService/RunOfflineUserDataJob", + request_serializer=offline_user_data_job_service.RunOfflineUserDataJobRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + ) + return self._stubs["run_offline_user_data_job"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.create_offline_user_data_job: self._wrap_method( + self.create_offline_user_data_job, + default_timeout=None, + client_info=client_info, + ), + self.add_offline_user_data_job_operations: self._wrap_method( + self.add_offline_user_data_job_operations, + default_timeout=None, + client_info=client_info, + ), + self.run_offline_user_data_job: self._wrap_method( + self.run_offline_user_data_job, + 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" + + +__all__ = ("OfflineUserDataJobServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/payments_account_service/__init__.py b/google/ads/googleads/v24/services/services/payments_account_service/__init__.py new file mode 100644 index 000000000..4a2d3b4b4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/payments_account_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import PaymentsAccountServiceClient +from .async_client import PaymentsAccountServiceAsyncClient + +__all__ = ( + "PaymentsAccountServiceClient", + "PaymentsAccountServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/payments_account_service/async_client.py b/google/ads/googleads/v24/services/services/payments_account_service/async_client.py new file mode 100644 index 000000000..a878a3d03 --- /dev/null +++ b/google/ads/googleads/v24/services/services/payments_account_service/async_client.py @@ -0,0 +1,423 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import payments_account_service +from .transports.base import ( + PaymentsAccountServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import PaymentsAccountServiceClient + +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 PaymentsAccountServiceAsyncClient: + """Service to provide payments accounts that can be used to set + up consolidated billing. + """ + + _client: PaymentsAccountServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = PaymentsAccountServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = PaymentsAccountServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + PaymentsAccountServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = PaymentsAccountServiceClient._DEFAULT_UNIVERSE + + customer_path = staticmethod(PaymentsAccountServiceClient.customer_path) + parse_customer_path = staticmethod( + PaymentsAccountServiceClient.parse_customer_path + ) + payments_account_path = staticmethod( + PaymentsAccountServiceClient.payments_account_path + ) + parse_payments_account_path = staticmethod( + PaymentsAccountServiceClient.parse_payments_account_path + ) + common_billing_account_path = staticmethod( + PaymentsAccountServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + PaymentsAccountServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + PaymentsAccountServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + PaymentsAccountServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + PaymentsAccountServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + PaymentsAccountServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + PaymentsAccountServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + PaymentsAccountServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + PaymentsAccountServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + PaymentsAccountServiceClient.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: + PaymentsAccountServiceAsyncClient: The constructed client. + """ + return PaymentsAccountServiceClient.from_service_account_info.__func__(PaymentsAccountServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + PaymentsAccountServiceAsyncClient: The constructed client. + """ + return PaymentsAccountServiceClient.from_service_account_file.__func__(PaymentsAccountServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return PaymentsAccountServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> PaymentsAccountServiceTransport: + """Returns the transport used by the client instance. + + Returns: + PaymentsAccountServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = PaymentsAccountServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + PaymentsAccountServiceTransport, + Callable[..., PaymentsAccountServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the payments account 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,PaymentsAccountServiceTransport,Callable[..., PaymentsAccountServiceTransport]]]): + 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 PaymentsAccountServiceTransport 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 = PaymentsAccountServiceClient( + 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.ads.googleads.v24.services.PaymentsAccountServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.PaymentsAccountService", + "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.ads.googleads.v24.services.PaymentsAccountService", + "credentialsType": None, + } + ), + ) + + async def list_payments_accounts( + self, + request: Optional[ + Union[payments_account_service.ListPaymentsAccountsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> payments_account_service.ListPaymentsAccountsResponse: + r"""Returns all payments accounts associated with all managers + between the login customer ID and specified serving customer in + the hierarchy, inclusive. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `PaymentsAccountError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListPaymentsAccountsRequest, dict]]): + The request object. Request message for fetching all + accessible payments accounts. + customer_id (:class:`str`): + Required. The ID of the customer to + apply the PaymentsAccount list operation + to. + + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.ListPaymentsAccountsResponse: + Response message for + [PaymentsAccountService.ListPaymentsAccounts][google.ads.googleads.v24.services.PaymentsAccountService.ListPaymentsAccounts]. + + """ + # 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 = [customer_id] + 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, payments_account_service.ListPaymentsAccountsRequest + ): + request = payments_account_service.ListPaymentsAccountsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_payments_accounts + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "PaymentsAccountServiceAsyncClient": + 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__ = ("PaymentsAccountServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/payments_account_service/client.py b/google/ads/googleads/v24/services/services/payments_account_service/client.py new file mode 100644 index 000000000..f5a38745b --- /dev/null +++ b/google/ads/googleads/v24/services/services/payments_account_service/client.py @@ -0,0 +1,900 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import payments_account_service +from .transports.base import ( + PaymentsAccountServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import PaymentsAccountServiceGrpcTransport +from .transports.grpc_asyncio import PaymentsAccountServiceGrpcAsyncIOTransport + + +class PaymentsAccountServiceClientMeta(type): + """Metaclass for the PaymentsAccountService 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[PaymentsAccountServiceTransport]] + _transport_registry["grpc"] = PaymentsAccountServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + PaymentsAccountServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[PaymentsAccountServiceTransport]: + """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 PaymentsAccountServiceClient(metaclass=PaymentsAccountServiceClientMeta): + """Service to provide payments accounts that can be used to set + up consolidated billing. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + PaymentsAccountServiceClient: 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: + PaymentsAccountServiceClient: 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) -> PaymentsAccountServiceTransport: + """Returns the transport used by the client instance. + + Returns: + PaymentsAccountServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def payments_account_path( + customer_id: str, + payments_account_id: str, + ) -> str: + """Returns a fully-qualified payments_account string.""" + return "customers/{customer_id}/paymentsAccounts/{payments_account_id}".format( + customer_id=customer_id, + payments_account_id=payments_account_id, + ) + + @staticmethod + def parse_payments_account_path(path: str) -> Dict[str, str]: + """Parses a payments_account path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/paymentsAccounts/(?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 = ( + PaymentsAccountServiceClient._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 = ( + PaymentsAccountServiceClient._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 + ): + """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 = PaymentsAccountServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = PaymentsAccountServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + PaymentsAccountServiceClient._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 = PaymentsAccountServiceClient._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): + """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, + PaymentsAccountServiceTransport, + Callable[..., PaymentsAccountServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the payments account 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,PaymentsAccountServiceTransport,Callable[..., PaymentsAccountServiceTransport]]]): + 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 PaymentsAccountServiceTransport 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, + ) = PaymentsAccountServiceClient._read_environment_variables() + self._client_cert_source = ( + PaymentsAccountServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + PaymentsAccountServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, PaymentsAccountServiceTransport + ) + if transport_provided: + # transport is a PaymentsAccountServiceTransport 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(PaymentsAccountServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or PaymentsAccountServiceClient._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[PaymentsAccountServiceTransport], + Callable[..., PaymentsAccountServiceTransport], + ] = ( + PaymentsAccountServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., PaymentsAccountServiceTransport], 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.ads.googleads.v24.services.PaymentsAccountServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.PaymentsAccountService", + "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.ads.googleads.v24.services.PaymentsAccountService", + "credentialsType": None, + } + ), + ) + + def list_payments_accounts( + self, + request: Optional[ + Union[payments_account_service.ListPaymentsAccountsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> payments_account_service.ListPaymentsAccountsResponse: + r"""Returns all payments accounts associated with all managers + between the login customer ID and specified serving customer in + the hierarchy, inclusive. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `PaymentsAccountError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListPaymentsAccountsRequest, dict]): + The request object. Request message for fetching all + accessible payments accounts. + customer_id (str): + Required. The ID of the customer to + apply the PaymentsAccount list operation + to. + + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.ListPaymentsAccountsResponse: + Response message for + [PaymentsAccountService.ListPaymentsAccounts][google.ads.googleads.v24.services.PaymentsAccountService.ListPaymentsAccounts]. + + """ + # 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 = [customer_id] + 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, payments_account_service.ListPaymentsAccountsRequest + ): + request = payments_account_service.ListPaymentsAccountsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_payments_accounts + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "PaymentsAccountServiceClient": + 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() + + +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__ = ("PaymentsAccountServiceClient",) diff --git a/google/ads/googleads/v24/services/services/payments_account_service/transports/README.rst b/google/ads/googleads/v24/services/services/payments_account_service/transports/README.rst new file mode 100644 index 000000000..43b4c858d --- /dev/null +++ b/google/ads/googleads/v24/services/services/payments_account_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`PaymentsAccountServiceTransport` is the ABC for all transports. +- public child `PaymentsAccountServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `PaymentsAccountServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BasePaymentsAccountServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `PaymentsAccountServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/payments_account_service/transports/__init__.py b/google/ads/googleads/v24/services/services/payments_account_service/transports/__init__.py new file mode 100644 index 000000000..b617e26e5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/payments_account_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import PaymentsAccountServiceTransport +from .grpc import PaymentsAccountServiceGrpcTransport +from .grpc_asyncio import PaymentsAccountServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[PaymentsAccountServiceTransport]] +_transport_registry["grpc"] = PaymentsAccountServiceGrpcTransport +_transport_registry["grpc_asyncio"] = PaymentsAccountServiceGrpcAsyncIOTransport + +__all__ = ( + "PaymentsAccountServiceTransport", + "PaymentsAccountServiceGrpcTransport", + "PaymentsAccountServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/payments_account_service/transports/base.py b/google/ads/googleads/v24/services/services/payments_account_service/transports/base.py new file mode 100644 index 000000000..d282e55fe --- /dev/null +++ b/google/ads/googleads/v24/services/services/payments_account_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import payments_account_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 PaymentsAccountServiceTransport(abc.ABC): + """Abstract transport class for PaymentsAccountService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.list_payments_accounts: gapic_v1.method.wrap_method( + self.list_payments_accounts, + 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_payments_accounts( + self, + ) -> Callable[ + [payments_account_service.ListPaymentsAccountsRequest], + Union[ + payments_account_service.ListPaymentsAccountsResponse, + Awaitable[payments_account_service.ListPaymentsAccountsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("PaymentsAccountServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/payments_account_service/transports/grpc.py b/google/ads/googleads/v24/services/services/payments_account_service/transports/grpc.py new file mode 100644 index 000000000..cb996faf6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/payments_account_service/transports/grpc.py @@ -0,0 +1,391 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import payments_account_service +from .base import PaymentsAccountServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.PaymentsAccountService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.PaymentsAccountService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class PaymentsAccountServiceGrpcTransport(PaymentsAccountServiceTransport): + """gRPC backend transport for PaymentsAccountService. + + Service to provide payments accounts that can be used to set + up consolidated billing. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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_payments_accounts( + self, + ) -> Callable[ + [payments_account_service.ListPaymentsAccountsRequest], + payments_account_service.ListPaymentsAccountsResponse, + ]: + r"""Return a callable for the list payments accounts method over gRPC. + + Returns all payments accounts associated with all managers + between the login customer ID and specified serving customer in + the hierarchy, inclusive. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `PaymentsAccountError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListPaymentsAccountsRequest], + ~.ListPaymentsAccountsResponse]: + 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_payments_accounts" not in self._stubs: + self._stubs["list_payments_accounts"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.PaymentsAccountService/ListPaymentsAccounts", + request_serializer=payments_account_service.ListPaymentsAccountsRequest.serialize, + response_deserializer=payments_account_service.ListPaymentsAccountsResponse.deserialize, + ) + ) + return self._stubs["list_payments_accounts"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("PaymentsAccountServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/payments_account_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/payments_account_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..47d562828 --- /dev/null +++ b/google/ads/googleads/v24/services/services/payments_account_service/transports/grpc_asyncio.py @@ -0,0 +1,414 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import payments_account_service +from .base import PaymentsAccountServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.PaymentsAccountService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.PaymentsAccountService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class PaymentsAccountServiceGrpcAsyncIOTransport( + PaymentsAccountServiceTransport +): + """gRPC AsyncIO backend transport for PaymentsAccountService. + + Service to provide payments accounts that can be used to set + up consolidated billing. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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_payments_accounts( + self, + ) -> Callable[ + [payments_account_service.ListPaymentsAccountsRequest], + Awaitable[payments_account_service.ListPaymentsAccountsResponse], + ]: + r"""Return a callable for the list payments accounts method over gRPC. + + Returns all payments accounts associated with all managers + between the login customer ID and specified serving customer in + the hierarchy, inclusive. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `PaymentsAccountError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListPaymentsAccountsRequest], + Awaitable[~.ListPaymentsAccountsResponse]]: + 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_payments_accounts" not in self._stubs: + self._stubs["list_payments_accounts"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.PaymentsAccountService/ListPaymentsAccounts", + request_serializer=payments_account_service.ListPaymentsAccountsRequest.serialize, + response_deserializer=payments_account_service.ListPaymentsAccountsResponse.deserialize, + ) + ) + return self._stubs["list_payments_accounts"] + + 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_payments_accounts: self._wrap_method( + self.list_payments_accounts, + 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" + + +__all__ = ("PaymentsAccountServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/product_link_invitation_service/__init__.py b/google/ads/googleads/v24/services/services/product_link_invitation_service/__init__.py new file mode 100644 index 000000000..b74595d1f --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_invitation_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ProductLinkInvitationServiceClient +from .async_client import ProductLinkInvitationServiceAsyncClient + +__all__ = ( + "ProductLinkInvitationServiceClient", + "ProductLinkInvitationServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/product_link_invitation_service/async_client.py b/google/ads/googleads/v24/services/services/product_link_invitation_service/async_client.py new file mode 100644 index 000000000..1b0694ffa --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_invitation_service/async_client.py @@ -0,0 +1,677 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.enums.types import ( + product_link_invitation_status as gage_product_link_invitation_status, +) +from google.ads.googleads.v24.resources.types import ( + product_link_invitation as gagr_product_link_invitation, +) +from google.ads.googleads.v24.services.types import ( + product_link_invitation_service, +) +from .transports.base import ( + ProductLinkInvitationServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import ProductLinkInvitationServiceClient + +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 ProductLinkInvitationServiceAsyncClient: + """This service allows management of product link invitations + from Google Ads accounts to other accounts. + """ + + _client: ProductLinkInvitationServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ProductLinkInvitationServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + ProductLinkInvitationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + ProductLinkInvitationServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ProductLinkInvitationServiceClient._DEFAULT_UNIVERSE + + customer_path = staticmethod( + ProductLinkInvitationServiceClient.customer_path + ) + parse_customer_path = staticmethod( + ProductLinkInvitationServiceClient.parse_customer_path + ) + product_link_invitation_path = staticmethod( + ProductLinkInvitationServiceClient.product_link_invitation_path + ) + parse_product_link_invitation_path = staticmethod( + ProductLinkInvitationServiceClient.parse_product_link_invitation_path + ) + common_billing_account_path = staticmethod( + ProductLinkInvitationServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ProductLinkInvitationServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ProductLinkInvitationServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ProductLinkInvitationServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ProductLinkInvitationServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ProductLinkInvitationServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ProductLinkInvitationServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ProductLinkInvitationServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ProductLinkInvitationServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ProductLinkInvitationServiceClient.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: + ProductLinkInvitationServiceAsyncClient: The constructed client. + """ + return ProductLinkInvitationServiceClient.from_service_account_info.__func__(ProductLinkInvitationServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ProductLinkInvitationServiceAsyncClient: The constructed client. + """ + return ProductLinkInvitationServiceClient.from_service_account_file.__func__(ProductLinkInvitationServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ProductLinkInvitationServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ProductLinkInvitationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ProductLinkInvitationServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ProductLinkInvitationServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ProductLinkInvitationServiceTransport, + Callable[..., ProductLinkInvitationServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the product link invitation 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,ProductLinkInvitationServiceTransport,Callable[..., ProductLinkInvitationServiceTransport]]]): + 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 ProductLinkInvitationServiceTransport 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 = ProductLinkInvitationServiceClient( + 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.ads.googleads.v24.services.ProductLinkInvitationServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ProductLinkInvitationService", + "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.ads.googleads.v24.services.ProductLinkInvitationService", + "credentialsType": None, + } + ), + ) + + async def create_product_link_invitation( + self, + request: Optional[ + Union[ + product_link_invitation_service.CreateProductLinkInvitationRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + product_link_invitation: Optional[ + gagr_product_link_invitation.ProductLinkInvitation + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> product_link_invitation_service.CreateProductLinkInvitationResponse: + r"""Creates a product link invitation. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.CreateProductLinkInvitationRequest, dict]]): + The request object. Request message for + [ProductLinkInvitationService.CreateProductLinkInvitation][google.ads.googleads.v24.services.ProductLinkInvitationService.CreateProductLinkInvitation]. + customer_id (:class:`str`): + Required. The ID of the customer + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + product_link_invitation (:class:`google.ads.googleads.v24.resources.types.ProductLinkInvitation`): + Required. The product link invitation + to be created. + + This corresponds to the ``product_link_invitation`` 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.ads.googleads.v24.services.types.CreateProductLinkInvitationResponse: + Response message for product link + invitation create. + + """ + # 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 = [customer_id, product_link_invitation] + 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, + product_link_invitation_service.CreateProductLinkInvitationRequest, + ): + request = product_link_invitation_service.CreateProductLinkInvitationRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if product_link_invitation is not None: + request.product_link_invitation = product_link_invitation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.create_product_link_invitation + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def update_product_link_invitation( + self, + request: Optional[ + Union[ + product_link_invitation_service.UpdateProductLinkInvitationRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + product_link_invitation_status: Optional[ + gage_product_link_invitation_status.ProductLinkInvitationStatusEnum.ProductLinkInvitationStatus + ] = None, + resource_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]]] = (), + ) -> product_link_invitation_service.UpdateProductLinkInvitationResponse: + r"""Update a product link invitation. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.UpdateProductLinkInvitationRequest, dict]]): + The request object. Request message for + [ProductLinkInvitationService.UpdateProductLinkInvitation][google.ads.googleads.v24.services.ProductLinkInvitationService.UpdateProductLinkInvitation]. + customer_id (:class:`str`): + Required. The ID of the customer + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + product_link_invitation_status (:class:`google.ads.googleads.v24.enums.types.ProductLinkInvitationStatusEnum.ProductLinkInvitationStatus`): + Required. The product link invitation + to be created. + + This corresponds to the ``product_link_invitation_status`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource_name (:class:`str`): + Required. Resource name of the + product link invitation. + + This corresponds to the ``resource_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.ads.googleads.v24.services.types.UpdateProductLinkInvitationResponse: + Response message for product link + invitation update. + + """ + # 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 = [ + customer_id, + product_link_invitation_status, + resource_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, + product_link_invitation_service.UpdateProductLinkInvitationRequest, + ): + request = product_link_invitation_service.UpdateProductLinkInvitationRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if product_link_invitation_status is not None: + request.product_link_invitation_status = ( + product_link_invitation_status + ) + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_product_link_invitation + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 remove_product_link_invitation( + self, + request: Optional[ + Union[ + product_link_invitation_service.RemoveProductLinkInvitationRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + resource_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]]] = (), + ) -> product_link_invitation_service.RemoveProductLinkInvitationResponse: + r"""Remove a product link invitation. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.RemoveProductLinkInvitationRequest, dict]]): + The request object. Request message for + [ProductLinkInvitationService.RemoveProductLinkInvitation][google.ads.googleads.v24.services.ProductLinkInvitationService.RemoveProductLinkInvitation]. + customer_id (:class:`str`): + Required. The ID of the product link + invitation being removed. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource_name (:class:`str`): + Required. The resource name of the product link + invitation being removed. expected, in this format: + + ``customers/{customer_id}/productLinkInvitations/{product_link_invitation_id}`` + + This corresponds to the ``resource_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.ads.googleads.v24.services.types.RemoveProductLinkInvitationResponse: + Response message for product link + invitation removeal. + + """ + # 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 = [customer_id, resource_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, + product_link_invitation_service.RemoveProductLinkInvitationRequest, + ): + request = product_link_invitation_service.RemoveProductLinkInvitationRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.remove_product_link_invitation + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ProductLinkInvitationServiceAsyncClient": + 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__ = ("ProductLinkInvitationServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/product_link_invitation_service/client.py b/google/ads/googleads/v24/services/services/product_link_invitation_service/client.py new file mode 100644 index 000000000..71e8d1f92 --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_invitation_service/client.py @@ -0,0 +1,1159 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.enums.types import ( + product_link_invitation_status as gage_product_link_invitation_status, +) +from google.ads.googleads.v24.resources.types import ( + product_link_invitation as gagr_product_link_invitation, +) +from google.ads.googleads.v24.services.types import ( + product_link_invitation_service, +) +from .transports.base import ( + ProductLinkInvitationServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ProductLinkInvitationServiceGrpcTransport +from .transports.grpc_asyncio import ( + ProductLinkInvitationServiceGrpcAsyncIOTransport, +) + + +class ProductLinkInvitationServiceClientMeta(type): + """Metaclass for the ProductLinkInvitationService 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[ProductLinkInvitationServiceTransport]] + _transport_registry["grpc"] = ProductLinkInvitationServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + ProductLinkInvitationServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ProductLinkInvitationServiceTransport]: + """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 ProductLinkInvitationServiceClient( + metaclass=ProductLinkInvitationServiceClientMeta +): + """This service allows management of product link invitations + from Google Ads accounts to other accounts. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ProductLinkInvitationServiceClient: 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: + ProductLinkInvitationServiceClient: 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) -> ProductLinkInvitationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ProductLinkInvitationServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def product_link_invitation_path( + customer_id: str, + customer_invitation_id: str, + ) -> str: + """Returns a fully-qualified product_link_invitation string.""" + return "customers/{customer_id}/productLinkInvitations/{customer_invitation_id}".format( + customer_id=customer_id, + customer_invitation_id=customer_invitation_id, + ) + + @staticmethod + def parse_product_link_invitation_path(path: str) -> Dict[str, str]: + """Parses a product_link_invitation path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/productLinkInvitations/(?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 = ( + ProductLinkInvitationServiceClient._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 = ( + ProductLinkInvitationServiceClient._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 + ): + """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 = ( + ProductLinkInvitationServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + ProductLinkInvitationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = ProductLinkInvitationServiceClient._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 = ProductLinkInvitationServiceClient._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): + """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, + ProductLinkInvitationServiceTransport, + Callable[..., ProductLinkInvitationServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the product link invitation 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,ProductLinkInvitationServiceTransport,Callable[..., ProductLinkInvitationServiceTransport]]]): + 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 ProductLinkInvitationServiceTransport 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, + ) = ProductLinkInvitationServiceClient._read_environment_variables() + self._client_cert_source = ( + ProductLinkInvitationServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + ProductLinkInvitationServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ProductLinkInvitationServiceTransport + ) + if transport_provided: + # transport is a ProductLinkInvitationServiceTransport 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( + ProductLinkInvitationServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ProductLinkInvitationServiceClient._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[ProductLinkInvitationServiceTransport], + Callable[..., ProductLinkInvitationServiceTransport], + ] = ( + ProductLinkInvitationServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., ProductLinkInvitationServiceTransport], + 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.ads.googleads.v24.services.ProductLinkInvitationServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ProductLinkInvitationService", + "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.ads.googleads.v24.services.ProductLinkInvitationService", + "credentialsType": None, + } + ), + ) + + def create_product_link_invitation( + self, + request: Optional[ + Union[ + product_link_invitation_service.CreateProductLinkInvitationRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + product_link_invitation: Optional[ + gagr_product_link_invitation.ProductLinkInvitation + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> product_link_invitation_service.CreateProductLinkInvitationResponse: + r"""Creates a product link invitation. + + Args: + request (Union[google.ads.googleads.v24.services.types.CreateProductLinkInvitationRequest, dict]): + The request object. Request message for + [ProductLinkInvitationService.CreateProductLinkInvitation][google.ads.googleads.v24.services.ProductLinkInvitationService.CreateProductLinkInvitation]. + customer_id (str): + Required. The ID of the customer + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + product_link_invitation (google.ads.googleads.v24.resources.types.ProductLinkInvitation): + Required. The product link invitation + to be created. + + This corresponds to the ``product_link_invitation`` 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.ads.googleads.v24.services.types.CreateProductLinkInvitationResponse: + Response message for product link + invitation create. + + """ + # 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 = [customer_id, product_link_invitation] + 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, + product_link_invitation_service.CreateProductLinkInvitationRequest, + ): + request = product_link_invitation_service.CreateProductLinkInvitationRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if product_link_invitation is not None: + request.product_link_invitation = product_link_invitation + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.create_product_link_invitation + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def update_product_link_invitation( + self, + request: Optional[ + Union[ + product_link_invitation_service.UpdateProductLinkInvitationRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + product_link_invitation_status: Optional[ + gage_product_link_invitation_status.ProductLinkInvitationStatusEnum.ProductLinkInvitationStatus + ] = None, + resource_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]]] = (), + ) -> product_link_invitation_service.UpdateProductLinkInvitationResponse: + r"""Update a product link invitation. + + Args: + request (Union[google.ads.googleads.v24.services.types.UpdateProductLinkInvitationRequest, dict]): + The request object. Request message for + [ProductLinkInvitationService.UpdateProductLinkInvitation][google.ads.googleads.v24.services.ProductLinkInvitationService.UpdateProductLinkInvitation]. + customer_id (str): + Required. The ID of the customer + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + product_link_invitation_status (google.ads.googleads.v24.enums.types.ProductLinkInvitationStatusEnum.ProductLinkInvitationStatus): + Required. The product link invitation + to be created. + + This corresponds to the ``product_link_invitation_status`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource_name (str): + Required. Resource name of the + product link invitation. + + This corresponds to the ``resource_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.ads.googleads.v24.services.types.UpdateProductLinkInvitationResponse: + Response message for product link + invitation update. + + """ + # 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 = [ + customer_id, + product_link_invitation_status, + resource_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, + product_link_invitation_service.UpdateProductLinkInvitationRequest, + ): + request = product_link_invitation_service.UpdateProductLinkInvitationRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if product_link_invitation_status is not None: + request.product_link_invitation_status = ( + product_link_invitation_status + ) + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.update_product_link_invitation + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 remove_product_link_invitation( + self, + request: Optional[ + Union[ + product_link_invitation_service.RemoveProductLinkInvitationRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + resource_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]]] = (), + ) -> product_link_invitation_service.RemoveProductLinkInvitationResponse: + r"""Remove a product link invitation. + + Args: + request (Union[google.ads.googleads.v24.services.types.RemoveProductLinkInvitationRequest, dict]): + The request object. Request message for + [ProductLinkInvitationService.RemoveProductLinkInvitation][google.ads.googleads.v24.services.ProductLinkInvitationService.RemoveProductLinkInvitation]. + customer_id (str): + Required. The ID of the product link + invitation being removed. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource_name (str): + Required. The resource name of the product link + invitation being removed. expected, in this format: + + ``customers/{customer_id}/productLinkInvitations/{product_link_invitation_id}`` + + This corresponds to the ``resource_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.ads.googleads.v24.services.types.RemoveProductLinkInvitationResponse: + Response message for product link + invitation removeal. + + """ + # 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 = [customer_id, resource_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, + product_link_invitation_service.RemoveProductLinkInvitationRequest, + ): + request = product_link_invitation_service.RemoveProductLinkInvitationRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.remove_product_link_invitation + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "ProductLinkInvitationServiceClient": + 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() + + +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__ = ("ProductLinkInvitationServiceClient",) diff --git a/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/README.rst b/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/README.rst new file mode 100644 index 000000000..c99237f52 --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ProductLinkInvitationServiceTransport` is the ABC for all transports. +- public child `ProductLinkInvitationServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ProductLinkInvitationServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseProductLinkInvitationServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ProductLinkInvitationServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/__init__.py b/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/__init__.py new file mode 100644 index 000000000..277d8b182 --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ProductLinkInvitationServiceTransport +from .grpc import ProductLinkInvitationServiceGrpcTransport +from .grpc_asyncio import ProductLinkInvitationServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ProductLinkInvitationServiceTransport]] +_transport_registry["grpc"] = ProductLinkInvitationServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + ProductLinkInvitationServiceGrpcAsyncIOTransport +) + +__all__ = ( + "ProductLinkInvitationServiceTransport", + "ProductLinkInvitationServiceGrpcTransport", + "ProductLinkInvitationServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/base.py b/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/base.py new file mode 100644 index 000000000..eaf4e244d --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/base.py @@ -0,0 +1,215 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + product_link_invitation_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 ProductLinkInvitationServiceTransport(abc.ABC): + """Abstract transport class for ProductLinkInvitationService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.create_product_link_invitation: gapic_v1.method.wrap_method( + self.create_product_link_invitation, + default_timeout=None, + client_info=client_info, + ), + self.update_product_link_invitation: gapic_v1.method.wrap_method( + self.update_product_link_invitation, + default_timeout=None, + client_info=client_info, + ), + self.remove_product_link_invitation: gapic_v1.method.wrap_method( + self.remove_product_link_invitation, + 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 create_product_link_invitation( + self, + ) -> Callable[ + [product_link_invitation_service.CreateProductLinkInvitationRequest], + Union[ + product_link_invitation_service.CreateProductLinkInvitationResponse, + Awaitable[ + product_link_invitation_service.CreateProductLinkInvitationResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def update_product_link_invitation( + self, + ) -> Callable[ + [product_link_invitation_service.UpdateProductLinkInvitationRequest], + Union[ + product_link_invitation_service.UpdateProductLinkInvitationResponse, + Awaitable[ + product_link_invitation_service.UpdateProductLinkInvitationResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def remove_product_link_invitation( + self, + ) -> Callable[ + [product_link_invitation_service.RemoveProductLinkInvitationRequest], + Union[ + product_link_invitation_service.RemoveProductLinkInvitationResponse, + Awaitable[ + product_link_invitation_service.RemoveProductLinkInvitationResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ProductLinkInvitationServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/grpc.py b/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/grpc.py new file mode 100644 index 000000000..926bbaec8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/grpc.py @@ -0,0 +1,450 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + product_link_invitation_service, +) +from .base import ProductLinkInvitationServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ProductLinkInvitationService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ProductLinkInvitationService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ProductLinkInvitationServiceGrpcTransport( + ProductLinkInvitationServiceTransport +): + """gRPC backend transport for ProductLinkInvitationService. + + This service allows management of product link invitations + from Google Ads accounts to other accounts. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 create_product_link_invitation( + self, + ) -> Callable[ + [product_link_invitation_service.CreateProductLinkInvitationRequest], + product_link_invitation_service.CreateProductLinkInvitationResponse, + ]: + r"""Return a callable for the create product link invitation method over gRPC. + + Creates a product link invitation. + + Returns: + Callable[[~.CreateProductLinkInvitationRequest], + ~.CreateProductLinkInvitationResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_product_link_invitation" not in self._stubs: + self._stubs["create_product_link_invitation"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ProductLinkInvitationService/CreateProductLinkInvitation", + request_serializer=product_link_invitation_service.CreateProductLinkInvitationRequest.serialize, + response_deserializer=product_link_invitation_service.CreateProductLinkInvitationResponse.deserialize, + ) + ) + return self._stubs["create_product_link_invitation"] + + @property + def update_product_link_invitation( + self, + ) -> Callable[ + [product_link_invitation_service.UpdateProductLinkInvitationRequest], + product_link_invitation_service.UpdateProductLinkInvitationResponse, + ]: + r"""Return a callable for the update product link invitation method over gRPC. + + Update a product link invitation. + + Returns: + Callable[[~.UpdateProductLinkInvitationRequest], + ~.UpdateProductLinkInvitationResponse]: + 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_product_link_invitation" not in self._stubs: + self._stubs["update_product_link_invitation"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ProductLinkInvitationService/UpdateProductLinkInvitation", + request_serializer=product_link_invitation_service.UpdateProductLinkInvitationRequest.serialize, + response_deserializer=product_link_invitation_service.UpdateProductLinkInvitationResponse.deserialize, + ) + ) + return self._stubs["update_product_link_invitation"] + + @property + def remove_product_link_invitation( + self, + ) -> Callable[ + [product_link_invitation_service.RemoveProductLinkInvitationRequest], + product_link_invitation_service.RemoveProductLinkInvitationResponse, + ]: + r"""Return a callable for the remove product link invitation method over gRPC. + + Remove a product link invitation. + + Returns: + Callable[[~.RemoveProductLinkInvitationRequest], + ~.RemoveProductLinkInvitationResponse]: + 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 "remove_product_link_invitation" not in self._stubs: + self._stubs["remove_product_link_invitation"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ProductLinkInvitationService/RemoveProductLinkInvitation", + request_serializer=product_link_invitation_service.RemoveProductLinkInvitationRequest.serialize, + response_deserializer=product_link_invitation_service.RemoveProductLinkInvitationResponse.deserialize, + ) + ) + return self._stubs["remove_product_link_invitation"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ProductLinkInvitationServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..18d0ab14e --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_invitation_service/transports/grpc_asyncio.py @@ -0,0 +1,487 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + product_link_invitation_service, +) +from .base import ProductLinkInvitationServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ProductLinkInvitationService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ProductLinkInvitationService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ProductLinkInvitationServiceGrpcAsyncIOTransport( + ProductLinkInvitationServiceTransport +): + """gRPC AsyncIO backend transport for ProductLinkInvitationService. + + This service allows management of product link invitations + from Google Ads accounts to other accounts. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 create_product_link_invitation( + self, + ) -> Callable[ + [product_link_invitation_service.CreateProductLinkInvitationRequest], + Awaitable[ + product_link_invitation_service.CreateProductLinkInvitationResponse + ], + ]: + r"""Return a callable for the create product link invitation method over gRPC. + + Creates a product link invitation. + + Returns: + Callable[[~.CreateProductLinkInvitationRequest], + Awaitable[~.CreateProductLinkInvitationResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_product_link_invitation" not in self._stubs: + self._stubs["create_product_link_invitation"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ProductLinkInvitationService/CreateProductLinkInvitation", + request_serializer=product_link_invitation_service.CreateProductLinkInvitationRequest.serialize, + response_deserializer=product_link_invitation_service.CreateProductLinkInvitationResponse.deserialize, + ) + ) + return self._stubs["create_product_link_invitation"] + + @property + def update_product_link_invitation( + self, + ) -> Callable[ + [product_link_invitation_service.UpdateProductLinkInvitationRequest], + Awaitable[ + product_link_invitation_service.UpdateProductLinkInvitationResponse + ], + ]: + r"""Return a callable for the update product link invitation method over gRPC. + + Update a product link invitation. + + Returns: + Callable[[~.UpdateProductLinkInvitationRequest], + Awaitable[~.UpdateProductLinkInvitationResponse]]: + 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_product_link_invitation" not in self._stubs: + self._stubs["update_product_link_invitation"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ProductLinkInvitationService/UpdateProductLinkInvitation", + request_serializer=product_link_invitation_service.UpdateProductLinkInvitationRequest.serialize, + response_deserializer=product_link_invitation_service.UpdateProductLinkInvitationResponse.deserialize, + ) + ) + return self._stubs["update_product_link_invitation"] + + @property + def remove_product_link_invitation( + self, + ) -> Callable[ + [product_link_invitation_service.RemoveProductLinkInvitationRequest], + Awaitable[ + product_link_invitation_service.RemoveProductLinkInvitationResponse + ], + ]: + r"""Return a callable for the remove product link invitation method over gRPC. + + Remove a product link invitation. + + Returns: + Callable[[~.RemoveProductLinkInvitationRequest], + Awaitable[~.RemoveProductLinkInvitationResponse]]: + 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 "remove_product_link_invitation" not in self._stubs: + self._stubs["remove_product_link_invitation"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ProductLinkInvitationService/RemoveProductLinkInvitation", + request_serializer=product_link_invitation_service.RemoveProductLinkInvitationRequest.serialize, + response_deserializer=product_link_invitation_service.RemoveProductLinkInvitationResponse.deserialize, + ) + ) + return self._stubs["remove_product_link_invitation"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.create_product_link_invitation: self._wrap_method( + self.create_product_link_invitation, + default_timeout=None, + client_info=client_info, + ), + self.update_product_link_invitation: self._wrap_method( + self.update_product_link_invitation, + default_timeout=None, + client_info=client_info, + ), + self.remove_product_link_invitation: self._wrap_method( + self.remove_product_link_invitation, + 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" + + +__all__ = ("ProductLinkInvitationServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/product_link_service/__init__.py b/google/ads/googleads/v24/services/services/product_link_service/__init__.py new file mode 100644 index 000000000..d07c56214 --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ProductLinkServiceClient +from .async_client import ProductLinkServiceAsyncClient + +__all__ = ( + "ProductLinkServiceClient", + "ProductLinkServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/product_link_service/async_client.py b/google/ads/googleads/v24/services/services/product_link_service/async_client.py new file mode 100644 index 000000000..fdd05ce6c --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_service/async_client.py @@ -0,0 +1,534 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.resources.types import ( + product_link as gagr_product_link, +) +from google.ads.googleads.v24.services.types import product_link_service +from .transports.base import ProductLinkServiceTransport, DEFAULT_CLIENT_INFO +from .client import ProductLinkServiceClient + +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 ProductLinkServiceAsyncClient: + """This service allows management of links between a Google + Ads customer and another product. + """ + + _client: ProductLinkServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ProductLinkServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ProductLinkServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + ProductLinkServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ProductLinkServiceClient._DEFAULT_UNIVERSE + + customer_path = staticmethod(ProductLinkServiceClient.customer_path) + parse_customer_path = staticmethod( + ProductLinkServiceClient.parse_customer_path + ) + product_link_path = staticmethod(ProductLinkServiceClient.product_link_path) + parse_product_link_path = staticmethod( + ProductLinkServiceClient.parse_product_link_path + ) + common_billing_account_path = staticmethod( + ProductLinkServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ProductLinkServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ProductLinkServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ProductLinkServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ProductLinkServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ProductLinkServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ProductLinkServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ProductLinkServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ProductLinkServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ProductLinkServiceClient.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: + ProductLinkServiceAsyncClient: The constructed client. + """ + return ProductLinkServiceClient.from_service_account_info.__func__(ProductLinkServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ProductLinkServiceAsyncClient: The constructed client. + """ + return ProductLinkServiceClient.from_service_account_file.__func__(ProductLinkServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ProductLinkServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ProductLinkServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ProductLinkServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ProductLinkServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ProductLinkServiceTransport, + Callable[..., ProductLinkServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the product link 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,ProductLinkServiceTransport,Callable[..., ProductLinkServiceTransport]]]): + 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 ProductLinkServiceTransport 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 = ProductLinkServiceClient( + 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.ads.googleads.v24.services.ProductLinkServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ProductLinkService", + "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.ads.googleads.v24.services.ProductLinkService", + "credentialsType": None, + } + ), + ) + + async def create_product_link( + self, + request: Optional[ + Union[product_link_service.CreateProductLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + product_link: Optional[gagr_product_link.ProductLink] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> product_link_service.CreateProductLinkResponse: + r"""Creates a product link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.CreateProductLinkRequest, dict]]): + The request object. Request message for + [ProductLinkService.CreateProductLink][google.ads.googleads.v24.services.ProductLinkService.CreateProductLink]. + customer_id (:class:`str`): + Required. The ID of the customer for + which the product link is created. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + product_link (:class:`google.ads.googleads.v24.resources.types.ProductLink`): + Required. The product link to be + created. + + This corresponds to the ``product_link`` 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.ads.googleads.v24.services.types.CreateProductLinkResponse: + Response message for + [ProductLinkService.CreateProductLink][google.ads.googleads.v24.services.ProductLinkService.CreateProductLink]. + + """ + # 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 = [customer_id, product_link] + 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, product_link_service.CreateProductLinkRequest + ): + request = product_link_service.CreateProductLinkRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if product_link is not None: + request.product_link = product_link + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.create_product_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 remove_product_link( + self, + request: Optional[ + Union[product_link_service.RemoveProductLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + resource_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]]] = (), + ) -> product_link_service.RemoveProductLinkResponse: + r"""Removes a product link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.RemoveProductLinkRequest, dict]]): + The request object. Request message for + [ProductLinkService.RemoveProductLink][google.ads.googleads.v24.services.ProductLinkService.RemoveProductLink]. + customer_id (:class:`str`): + Required. The ID of the customer + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource_name (:class:`str`): + Required. Remove operation: A resource name for the + product link to remove is expected, in this format: + + ``customers/{customer_id}/productLinks/{product_link_id}`` + + This corresponds to the ``resource_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.ads.googleads.v24.services.types.RemoveProductLinkResponse: + Response message for product link + removal. + + """ + # 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 = [customer_id, resource_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, product_link_service.RemoveProductLinkRequest + ): + request = product_link_service.RemoveProductLinkRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.remove_product_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ProductLinkServiceAsyncClient": + 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__ = ("ProductLinkServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/product_link_service/client.py b/google/ads/googleads/v24/services/services/product_link_service/client.py new file mode 100644 index 000000000..7e62214d4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_service/client.py @@ -0,0 +1,1000 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.resources.types import ( + product_link as gagr_product_link, +) +from google.ads.googleads.v24.services.types import product_link_service +from .transports.base import ProductLinkServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import ProductLinkServiceGrpcTransport +from .transports.grpc_asyncio import ProductLinkServiceGrpcAsyncIOTransport + + +class ProductLinkServiceClientMeta(type): + """Metaclass for the ProductLinkService 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[ProductLinkServiceTransport]] + _transport_registry["grpc"] = ProductLinkServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ProductLinkServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ProductLinkServiceTransport]: + """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 ProductLinkServiceClient(metaclass=ProductLinkServiceClientMeta): + """This service allows management of links between a Google + Ads customer and another product. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ProductLinkServiceClient: 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: + ProductLinkServiceClient: 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) -> ProductLinkServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ProductLinkServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def customer_path( + customer_id: str, + ) -> str: + """Returns a fully-qualified customer string.""" + return "customers/{customer_id}".format( + customer_id=customer_id, + ) + + @staticmethod + def parse_customer_path(path: str) -> Dict[str, str]: + """Parses a customer path into its component segments.""" + m = re.match(r"^customers/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def product_link_path( + customer_id: str, + product_link_id: str, + ) -> str: + """Returns a fully-qualified product_link string.""" + return "customers/{customer_id}/productLinks/{product_link_id}".format( + customer_id=customer_id, + product_link_id=product_link_id, + ) + + @staticmethod + def parse_product_link_path(path: str) -> Dict[str, str]: + """Parses a product_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/productLinks/(?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 = ProductLinkServiceClient._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 = ProductLinkServiceClient._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 + ): + """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 = ProductLinkServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ProductLinkServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + ProductLinkServiceClient._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 = ProductLinkServiceClient._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): + """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, + ProductLinkServiceTransport, + Callable[..., ProductLinkServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the product link 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,ProductLinkServiceTransport,Callable[..., ProductLinkServiceTransport]]]): + 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 ProductLinkServiceTransport 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, + ) = ProductLinkServiceClient._read_environment_variables() + self._client_cert_source = ( + ProductLinkServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ProductLinkServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ProductLinkServiceTransport) + if transport_provided: + # transport is a ProductLinkServiceTransport 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(ProductLinkServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ProductLinkServiceClient._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[ProductLinkServiceTransport], + Callable[..., ProductLinkServiceTransport], + ] = ( + ProductLinkServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., ProductLinkServiceTransport], 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.ads.googleads.v24.services.ProductLinkServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ProductLinkService", + "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.ads.googleads.v24.services.ProductLinkService", + "credentialsType": None, + } + ), + ) + + def create_product_link( + self, + request: Optional[ + Union[product_link_service.CreateProductLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + product_link: Optional[gagr_product_link.ProductLink] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> product_link_service.CreateProductLinkResponse: + r"""Creates a product link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.CreateProductLinkRequest, dict]): + The request object. Request message for + [ProductLinkService.CreateProductLink][google.ads.googleads.v24.services.ProductLinkService.CreateProductLink]. + customer_id (str): + Required. The ID of the customer for + which the product link is created. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + product_link (google.ads.googleads.v24.resources.types.ProductLink): + Required. The product link to be + created. + + This corresponds to the ``product_link`` 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.ads.googleads.v24.services.types.CreateProductLinkResponse: + Response message for + [ProductLinkService.CreateProductLink][google.ads.googleads.v24.services.ProductLinkService.CreateProductLink]. + + """ + # 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 = [customer_id, product_link] + 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, product_link_service.CreateProductLinkRequest + ): + request = product_link_service.CreateProductLinkRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if product_link is not None: + request.product_link = product_link + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.create_product_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 remove_product_link( + self, + request: Optional[ + Union[product_link_service.RemoveProductLinkRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + resource_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]]] = (), + ) -> product_link_service.RemoveProductLinkResponse: + r"""Removes a product link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.RemoveProductLinkRequest, dict]): + The request object. Request message for + [ProductLinkService.RemoveProductLink][google.ads.googleads.v24.services.ProductLinkService.RemoveProductLink]. + customer_id (str): + Required. The ID of the customer + being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource_name (str): + Required. Remove operation: A resource name for the + product link to remove is expected, in this format: + + ``customers/{customer_id}/productLinks/{product_link_id}`` + + This corresponds to the ``resource_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.ads.googleads.v24.services.types.RemoveProductLinkResponse: + Response message for product link + removal. + + """ + # 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 = [customer_id, resource_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, product_link_service.RemoveProductLinkRequest + ): + request = product_link_service.RemoveProductLinkRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.remove_product_link + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "ProductLinkServiceClient": + 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() + + +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__ = ("ProductLinkServiceClient",) diff --git a/google/ads/googleads/v24/services/services/product_link_service/transports/README.rst b/google/ads/googleads/v24/services/services/product_link_service/transports/README.rst new file mode 100644 index 000000000..bb69ea70d --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ProductLinkServiceTransport` is the ABC for all transports. +- public child `ProductLinkServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ProductLinkServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseProductLinkServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ProductLinkServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/product_link_service/transports/__init__.py b/google/ads/googleads/v24/services/services/product_link_service/transports/__init__.py new file mode 100644 index 000000000..887f6ec08 --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ProductLinkServiceTransport +from .grpc import ProductLinkServiceGrpcTransport +from .grpc_asyncio import ProductLinkServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ProductLinkServiceTransport]] +_transport_registry["grpc"] = ProductLinkServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ProductLinkServiceGrpcAsyncIOTransport + +__all__ = ( + "ProductLinkServiceTransport", + "ProductLinkServiceGrpcTransport", + "ProductLinkServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/product_link_service/transports/base.py b/google/ads/googleads/v24/services/services/product_link_service/transports/base.py new file mode 100644 index 000000000..ce8ef1655 --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_service/transports/base.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import product_link_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 ProductLinkServiceTransport(abc.ABC): + """Abstract transport class for ProductLinkService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.create_product_link: gapic_v1.method.wrap_method( + self.create_product_link, + default_timeout=None, + client_info=client_info, + ), + self.remove_product_link: gapic_v1.method.wrap_method( + self.remove_product_link, + 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 create_product_link( + self, + ) -> Callable[ + [product_link_service.CreateProductLinkRequest], + Union[ + product_link_service.CreateProductLinkResponse, + Awaitable[product_link_service.CreateProductLinkResponse], + ], + ]: + raise NotImplementedError() + + @property + def remove_product_link( + self, + ) -> Callable[ + [product_link_service.RemoveProductLinkRequest], + Union[ + product_link_service.RemoveProductLinkResponse, + Awaitable[product_link_service.RemoveProductLinkResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ProductLinkServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/product_link_service/transports/grpc.py b/google/ads/googleads/v24/services/services/product_link_service/transports/grpc.py new file mode 100644 index 000000000..453087c20 --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_service/transports/grpc.py @@ -0,0 +1,425 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import product_link_service +from .base import ProductLinkServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ProductLinkService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ProductLinkService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ProductLinkServiceGrpcTransport(ProductLinkServiceTransport): + """gRPC backend transport for ProductLinkService. + + This service allows management of links between a Google + Ads customer and another product. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 create_product_link( + self, + ) -> Callable[ + [product_link_service.CreateProductLinkRequest], + product_link_service.CreateProductLinkResponse, + ]: + r"""Return a callable for the create product link method over gRPC. + + Creates a product link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.CreateProductLinkRequest], + ~.CreateProductLinkResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_product_link" not in self._stubs: + self._stubs["create_product_link"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ProductLinkService/CreateProductLink", + request_serializer=product_link_service.CreateProductLinkRequest.serialize, + response_deserializer=product_link_service.CreateProductLinkResponse.deserialize, + ) + ) + return self._stubs["create_product_link"] + + @property + def remove_product_link( + self, + ) -> Callable[ + [product_link_service.RemoveProductLinkRequest], + product_link_service.RemoveProductLinkResponse, + ]: + r"""Return a callable for the remove product link method over gRPC. + + Removes a product link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.RemoveProductLinkRequest], + ~.RemoveProductLinkResponse]: + 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 "remove_product_link" not in self._stubs: + self._stubs["remove_product_link"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ProductLinkService/RemoveProductLink", + request_serializer=product_link_service.RemoveProductLinkRequest.serialize, + response_deserializer=product_link_service.RemoveProductLinkResponse.deserialize, + ) + ) + return self._stubs["remove_product_link"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ProductLinkServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/product_link_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/product_link_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..b23770caa --- /dev/null +++ b/google/ads/googleads/v24/services/services/product_link_service/transports/grpc_asyncio.py @@ -0,0 +1,451 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import product_link_service +from .base import ProductLinkServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ProductLinkService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ProductLinkService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ProductLinkServiceGrpcAsyncIOTransport(ProductLinkServiceTransport): + """gRPC AsyncIO backend transport for ProductLinkService. + + This service allows management of links between a Google + Ads customer and another product. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 create_product_link( + self, + ) -> Callable[ + [product_link_service.CreateProductLinkRequest], + Awaitable[product_link_service.CreateProductLinkResponse], + ]: + r"""Return a callable for the create product link method over gRPC. + + Creates a product link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.CreateProductLinkRequest], + Awaitable[~.CreateProductLinkResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_product_link" not in self._stubs: + self._stubs["create_product_link"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ProductLinkService/CreateProductLink", + request_serializer=product_link_service.CreateProductLinkRequest.serialize, + response_deserializer=product_link_service.CreateProductLinkResponse.deserialize, + ) + ) + return self._stubs["create_product_link"] + + @property + def remove_product_link( + self, + ) -> Callable[ + [product_link_service.RemoveProductLinkRequest], + Awaitable[product_link_service.RemoveProductLinkResponse], + ]: + r"""Return a callable for the remove product link method over gRPC. + + Removes a product link. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.RemoveProductLinkRequest], + Awaitable[~.RemoveProductLinkResponse]]: + 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 "remove_product_link" not in self._stubs: + self._stubs["remove_product_link"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ProductLinkService/RemoveProductLink", + request_serializer=product_link_service.RemoveProductLinkRequest.serialize, + response_deserializer=product_link_service.RemoveProductLinkResponse.deserialize, + ) + ) + return self._stubs["remove_product_link"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.create_product_link: self._wrap_method( + self.create_product_link, + default_timeout=None, + client_info=client_info, + ), + self.remove_product_link: self._wrap_method( + self.remove_product_link, + 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" + + +__all__ = ("ProductLinkServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/reach_plan_service/__init__.py b/google/ads/googleads/v24/services/services/reach_plan_service/__init__.py new file mode 100644 index 000000000..b78cf7051 --- /dev/null +++ b/google/ads/googleads/v24/services/services/reach_plan_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ReachPlanServiceClient +from .async_client import ReachPlanServiceAsyncClient + +__all__ = ( + "ReachPlanServiceClient", + "ReachPlanServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/reach_plan_service/async_client.py b/google/ads/googleads/v24/services/services/reach_plan_service/async_client.py new file mode 100644 index 000000000..1cce0b842 --- /dev/null +++ b/google/ads/googleads/v24/services/services/reach_plan_service/async_client.py @@ -0,0 +1,850 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import reach_plan_service +from .transports.base import ReachPlanServiceTransport, DEFAULT_CLIENT_INFO +from .client import ReachPlanServiceClient + +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 ReachPlanServiceAsyncClient: + """Reach Plan Service gives users information about audience + size that can be reached through advertisement on YouTube. In + particular, GenerateReachForecast provides estimated number of + people of specified demographics that can be reached by an ad in + a given market by a campaign of certain duration with a defined + budget. + """ + + _client: ReachPlanServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ReachPlanServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ReachPlanServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + ReachPlanServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ReachPlanServiceClient._DEFAULT_UNIVERSE + + common_billing_account_path = staticmethod( + ReachPlanServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ReachPlanServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(ReachPlanServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + ReachPlanServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ReachPlanServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ReachPlanServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ReachPlanServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ReachPlanServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ReachPlanServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ReachPlanServiceClient.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: + ReachPlanServiceAsyncClient: The constructed client. + """ + return ReachPlanServiceClient.from_service_account_info.__func__(ReachPlanServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ReachPlanServiceAsyncClient: The constructed client. + """ + return ReachPlanServiceClient.from_service_account_file.__func__(ReachPlanServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ReachPlanServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ReachPlanServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ReachPlanServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ReachPlanServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ReachPlanServiceTransport, + Callable[..., ReachPlanServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the reach plan 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,ReachPlanServiceTransport,Callable[..., ReachPlanServiceTransport]]]): + 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 ReachPlanServiceTransport 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 = ReachPlanServiceClient( + 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.ads.googleads.v24.services.ReachPlanServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ReachPlanService", + "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.ads.googleads.v24.services.ReachPlanService", + "credentialsType": None, + } + ), + ) + + async def generate_conversion_rates( + self, + request: Optional[ + Union[reach_plan_service.GenerateConversionRatesRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reach_plan_service.GenerateConversionRatesResponse: + r"""Returns a collection of conversion rate suggestions for + supported plannable products. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateConversionRatesRequest, dict]]): + The request object. Request message for + [ReachPlanService.GenerateConversionRates][google.ads.googleads.v24.services.ReachPlanService.GenerateConversionRates]. + customer_id (:class:`str`): + Required. The ID of the customer. A + conversion rate based on the historical + data of this customer may be suggested. + + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.GenerateConversionRatesResponse: + Response message for + [ReachPlanService.GenerateConversionRates][google.ads.googleads.v24.services.ReachPlanService.GenerateConversionRates], + containing conversion rate suggestions for supported + plannable products. + + """ + # 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 = [customer_id] + 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, reach_plan_service.GenerateConversionRatesRequest + ): + request = reach_plan_service.GenerateConversionRatesRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_conversion_rates + ] + + # 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_plannable_locations( + self, + request: Optional[ + Union[reach_plan_service.ListPlannableLocationsRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reach_plan_service.ListPlannableLocationsResponse: + r"""Returns the list of plannable locations (for example, + countries). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListPlannableLocationsRequest, dict]]): + The request object. Request message for + [ReachPlanService.ListPlannableLocations][google.ads.googleads.v24.services.ReachPlanService.ListPlannableLocations]. + 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.googleads.v24.services.types.ListPlannableLocationsResponse: + The list of plannable locations. + """ + # 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, reach_plan_service.ListPlannableLocationsRequest + ): + request = reach_plan_service.ListPlannableLocationsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_plannable_locations + ] + + # 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_plannable_products( + self, + request: Optional[ + Union[reach_plan_service.ListPlannableProductsRequest, dict] + ] = None, + *, + plannable_location_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reach_plan_service.ListPlannableProductsResponse: + r"""Returns the list of per-location plannable YouTube ad formats + with allowed targeting. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListPlannableProductsRequest, dict]]): + The request object. Request to list available products in + a given location. + plannable_location_id (:class:`str`): + Required. The ID of the selected location for planning. + To list the available plannable location IDs use + [ReachPlanService.ListPlannableLocations][google.ads.googleads.v24.services.ReachPlanService.ListPlannableLocations]. + + This corresponds to the ``plannable_location_id`` 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.ads.googleads.v24.services.types.ListPlannableProductsResponse: + A response with all available + products. + + """ + # 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 = [plannable_location_id] + 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, reach_plan_service.ListPlannableProductsRequest + ): + request = reach_plan_service.ListPlannableProductsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if plannable_location_id is not None: + request.plannable_location_id = plannable_location_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_plannable_products + ] + + # 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 generate_reach_forecast( + self, + request: Optional[ + Union[reach_plan_service.GenerateReachForecastRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + campaign_duration: Optional[reach_plan_service.CampaignDuration] = None, + planned_products: Optional[ + MutableSequence[reach_plan_service.PlannedProduct] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reach_plan_service.GenerateReachForecastResponse: + r"""Generates a reach forecast for a given targeting / product mix. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `ReachPlanError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateReachForecastRequest, dict]]): + The request object. Request message for + [ReachPlanService.GenerateReachForecast][google.ads.googleads.v24.services.ReachPlanService.GenerateReachForecast]. + customer_id (:class:`str`): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + campaign_duration (:class:`google.ads.googleads.v24.services.types.CampaignDuration`): + Required. Campaign duration. + This corresponds to the ``campaign_duration`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + planned_products (:class:`MutableSequence[google.ads.googleads.v24.services.types.PlannedProduct]`): + Required. The products to be + forecast. The max number of allowed + planned products is 15. + + This corresponds to the ``planned_products`` 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.ads.googleads.v24.services.types.GenerateReachForecastResponse: + Response message containing the + generated reach curve. + + """ + # 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 = [customer_id, campaign_duration, planned_products] + 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, reach_plan_service.GenerateReachForecastRequest + ): + request = reach_plan_service.GenerateReachForecastRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if campaign_duration is not None: + request.campaign_duration = campaign_duration + if planned_products: + request.planned_products.extend(planned_products) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_reach_forecast + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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_plannable_user_lists( + self, + request: Optional[ + Union[reach_plan_service.ListPlannableUserListsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reach_plan_service.ListPlannableUserListsResponse: + r"""Returns the list of plannable user lists with their plannable + status. User lists may not be plannable for a number of reasons, + including: + + - They are less than 10 days old. + - They have a membership lifespan that is less than 30 days + - They have less than 10,000 or more than 700,000 users. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `ReachPlanError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListPlannableUserListsRequest, dict]]): + The request object. Request message for + [ReachPlanService.ListPlannableUserLists][google.ads.googleads.v24.services.ReachPlanService.ListPlannableUserLists] + that lists the available user lists for a customer. + customer_id (:class:`str`): + Required. The ID of the customer. + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.ListPlannableUserListsResponse: + A response with all available user + lists with their plannable status. + + """ + # 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 = [customer_id] + 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, reach_plan_service.ListPlannableUserListsRequest + ): + request = reach_plan_service.ListPlannableUserListsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_plannable_user_lists + ] + + # 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_plannable_user_interests( + self, + request: Optional[ + Union[reach_plan_service.ListPlannableUserInterestsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reach_plan_service.ListPlannableUserInterestsResponse: + r"""Returns the list of plannable user interests. A plannable user + interest is one that can be targeted in a reach forecast using + [ReachPlanService.GenerateReachForecast][google.ads.googleads.v24.services.ReachPlanService.GenerateReachForecast]. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `ListOperationError <>`__ `QuotaError <>`__ + `RequestError <>`__ `StringLengthError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ListPlannableUserInterestsRequest, dict]]): + The request object. Request message for + [ReachPlanService.ListPlannableUserInterests][google.ads.googleads.v24.services.ReachPlanService.ListPlannableUserInterests]. + customer_id (:class:`str`): + Required. The ID of the customer. + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.ListPlannableUserInterestsResponse: + Response message for + [ReachPlanService.ListPlannableUserInterests][google.ads.googleads.v24.services.ReachPlanService.ListPlannableUserInterests]. + + """ + # 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 = [customer_id] + 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, reach_plan_service.ListPlannableUserInterestsRequest + ): + request = reach_plan_service.ListPlannableUserInterestsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_plannable_user_interests + ] + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ReachPlanServiceAsyncClient": + 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__ = ("ReachPlanServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/reach_plan_service/client.py b/google/ads/googleads/v24/services/services/reach_plan_service/client.py new file mode 100644 index 000000000..4b3b9ff86 --- /dev/null +++ b/google/ads/googleads/v24/services/services/reach_plan_service/client.py @@ -0,0 +1,1298 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import reach_plan_service +from .transports.base import ReachPlanServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import ReachPlanServiceGrpcTransport +from .transports.grpc_asyncio import ReachPlanServiceGrpcAsyncIOTransport + + +class ReachPlanServiceClientMeta(type): + """Metaclass for the ReachPlanService 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[ReachPlanServiceTransport]] + _transport_registry["grpc"] = ReachPlanServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ReachPlanServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ReachPlanServiceTransport]: + """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 ReachPlanServiceClient(metaclass=ReachPlanServiceClientMeta): + """Reach Plan Service gives users information about audience + size that can be reached through advertisement on YouTube. In + particular, GenerateReachForecast provides estimated number of + people of specified demographics that can be reached by an ad in + a given market by a campaign of certain duration with a defined + budget. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ReachPlanServiceClient: 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: + ReachPlanServiceClient: 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) -> ReachPlanServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ReachPlanServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @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 = ReachPlanServiceClient._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 = ReachPlanServiceClient._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 + ): + """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 = ReachPlanServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ReachPlanServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + ReachPlanServiceClient._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 = ReachPlanServiceClient._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): + """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, + ReachPlanServiceTransport, + Callable[..., ReachPlanServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the reach plan 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,ReachPlanServiceTransport,Callable[..., ReachPlanServiceTransport]]]): + 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 ReachPlanServiceTransport 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, + ) = ReachPlanServiceClient._read_environment_variables() + self._client_cert_source = ( + ReachPlanServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ReachPlanServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ReachPlanServiceTransport) + if transport_provided: + # transport is a ReachPlanServiceTransport 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(ReachPlanServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ReachPlanServiceClient._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[ReachPlanServiceTransport], + Callable[..., ReachPlanServiceTransport], + ] = ( + ReachPlanServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., ReachPlanServiceTransport], 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.ads.googleads.v24.services.ReachPlanServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ReachPlanService", + "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.ads.googleads.v24.services.ReachPlanService", + "credentialsType": None, + } + ), + ) + + def generate_conversion_rates( + self, + request: Optional[ + Union[reach_plan_service.GenerateConversionRatesRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reach_plan_service.GenerateConversionRatesResponse: + r"""Returns a collection of conversion rate suggestions for + supported plannable products. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateConversionRatesRequest, dict]): + The request object. Request message for + [ReachPlanService.GenerateConversionRates][google.ads.googleads.v24.services.ReachPlanService.GenerateConversionRates]. + customer_id (str): + Required. The ID of the customer. A + conversion rate based on the historical + data of this customer may be suggested. + + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.GenerateConversionRatesResponse: + Response message for + [ReachPlanService.GenerateConversionRates][google.ads.googleads.v24.services.ReachPlanService.GenerateConversionRates], + containing conversion rate suggestions for supported + plannable products. + + """ + # 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 = [customer_id] + 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, reach_plan_service.GenerateConversionRatesRequest + ): + request = reach_plan_service.GenerateConversionRatesRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_conversion_rates + ] + + # 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_plannable_locations( + self, + request: Optional[ + Union[reach_plan_service.ListPlannableLocationsRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reach_plan_service.ListPlannableLocationsResponse: + r"""Returns the list of plannable locations (for example, + countries). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListPlannableLocationsRequest, dict]): + The request object. Request message for + [ReachPlanService.ListPlannableLocations][google.ads.googleads.v24.services.ReachPlanService.ListPlannableLocations]. + 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.googleads.v24.services.types.ListPlannableLocationsResponse: + The list of plannable locations. + """ + # 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, reach_plan_service.ListPlannableLocationsRequest + ): + request = reach_plan_service.ListPlannableLocationsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_plannable_locations + ] + + # 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_plannable_products( + self, + request: Optional[ + Union[reach_plan_service.ListPlannableProductsRequest, dict] + ] = None, + *, + plannable_location_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reach_plan_service.ListPlannableProductsResponse: + r"""Returns the list of per-location plannable YouTube ad formats + with allowed targeting. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListPlannableProductsRequest, dict]): + The request object. Request to list available products in + a given location. + plannable_location_id (str): + Required. The ID of the selected location for planning. + To list the available plannable location IDs use + [ReachPlanService.ListPlannableLocations][google.ads.googleads.v24.services.ReachPlanService.ListPlannableLocations]. + + This corresponds to the ``plannable_location_id`` 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.ads.googleads.v24.services.types.ListPlannableProductsResponse: + A response with all available + products. + + """ + # 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 = [plannable_location_id] + 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, reach_plan_service.ListPlannableProductsRequest + ): + request = reach_plan_service.ListPlannableProductsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if plannable_location_id is not None: + request.plannable_location_id = plannable_location_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_plannable_products + ] + + # 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 generate_reach_forecast( + self, + request: Optional[ + Union[reach_plan_service.GenerateReachForecastRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + campaign_duration: Optional[reach_plan_service.CampaignDuration] = None, + planned_products: Optional[ + MutableSequence[reach_plan_service.PlannedProduct] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reach_plan_service.GenerateReachForecastResponse: + r"""Generates a reach forecast for a given targeting / product mix. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `ReachPlanError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateReachForecastRequest, dict]): + The request object. Request message for + [ReachPlanService.GenerateReachForecast][google.ads.googleads.v24.services.ReachPlanService.GenerateReachForecast]. + customer_id (str): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + campaign_duration (google.ads.googleads.v24.services.types.CampaignDuration): + Required. Campaign duration. + This corresponds to the ``campaign_duration`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + planned_products (MutableSequence[google.ads.googleads.v24.services.types.PlannedProduct]): + Required. The products to be + forecast. The max number of allowed + planned products is 15. + + This corresponds to the ``planned_products`` 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.ads.googleads.v24.services.types.GenerateReachForecastResponse: + Response message containing the + generated reach curve. + + """ + # 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 = [customer_id, campaign_duration, planned_products] + 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, reach_plan_service.GenerateReachForecastRequest + ): + request = reach_plan_service.GenerateReachForecastRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if campaign_duration is not None: + request.campaign_duration = campaign_duration + if planned_products is not None: + request.planned_products = planned_products + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_reach_forecast + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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_plannable_user_lists( + self, + request: Optional[ + Union[reach_plan_service.ListPlannableUserListsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reach_plan_service.ListPlannableUserListsResponse: + r"""Returns the list of plannable user lists with their plannable + status. User lists may not be plannable for a number of reasons, + including: + + - They are less than 10 days old. + - They have a membership lifespan that is less than 30 days + - They have less than 10,000 or more than 700,000 users. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `ReachPlanError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListPlannableUserListsRequest, dict]): + The request object. Request message for + [ReachPlanService.ListPlannableUserLists][google.ads.googleads.v24.services.ReachPlanService.ListPlannableUserLists] + that lists the available user lists for a customer. + customer_id (str): + Required. The ID of the customer. + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.ListPlannableUserListsResponse: + A response with all available user + lists with their plannable status. + + """ + # 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 = [customer_id] + 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, reach_plan_service.ListPlannableUserListsRequest + ): + request = reach_plan_service.ListPlannableUserListsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_plannable_user_lists + ] + + # 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_plannable_user_interests( + self, + request: Optional[ + Union[reach_plan_service.ListPlannableUserInterestsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reach_plan_service.ListPlannableUserInterestsResponse: + r"""Returns the list of plannable user interests. A plannable user + interest is one that can be targeted in a reach forecast using + [ReachPlanService.GenerateReachForecast][google.ads.googleads.v24.services.ReachPlanService.GenerateReachForecast]. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `ListOperationError <>`__ `QuotaError <>`__ + `RequestError <>`__ `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ListPlannableUserInterestsRequest, dict]): + The request object. Request message for + [ReachPlanService.ListPlannableUserInterests][google.ads.googleads.v24.services.ReachPlanService.ListPlannableUserInterests]. + customer_id (str): + Required. The ID of the customer. + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.ListPlannableUserInterestsResponse: + Response message for + [ReachPlanService.ListPlannableUserInterests][google.ads.googleads.v24.services.ReachPlanService.ListPlannableUserInterests]. + + """ + # 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 = [customer_id] + 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, reach_plan_service.ListPlannableUserInterestsRequest + ): + request = reach_plan_service.ListPlannableUserInterestsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_plannable_user_interests + ] + + # 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) -> "ReachPlanServiceClient": + 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() + + +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__ = ("ReachPlanServiceClient",) diff --git a/google/ads/googleads/v24/services/services/reach_plan_service/transports/README.rst b/google/ads/googleads/v24/services/services/reach_plan_service/transports/README.rst new file mode 100644 index 000000000..c082010f5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/reach_plan_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ReachPlanServiceTransport` is the ABC for all transports. +- public child `ReachPlanServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ReachPlanServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseReachPlanServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ReachPlanServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/reach_plan_service/transports/__init__.py b/google/ads/googleads/v24/services/services/reach_plan_service/transports/__init__.py new file mode 100644 index 000000000..a8315b7ae --- /dev/null +++ b/google/ads/googleads/v24/services/services/reach_plan_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ReachPlanServiceTransport +from .grpc import ReachPlanServiceGrpcTransport +from .grpc_asyncio import ReachPlanServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ReachPlanServiceTransport]] +_transport_registry["grpc"] = ReachPlanServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ReachPlanServiceGrpcAsyncIOTransport + +__all__ = ( + "ReachPlanServiceTransport", + "ReachPlanServiceGrpcTransport", + "ReachPlanServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/reach_plan_service/transports/base.py b/google/ads/googleads/v24/services/services/reach_plan_service/transports/base.py new file mode 100644 index 000000000..f6628ad05 --- /dev/null +++ b/google/ads/googleads/v24/services/services/reach_plan_service/transports/base.py @@ -0,0 +1,258 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import reach_plan_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 ReachPlanServiceTransport(abc.ABC): + """Abstract transport class for ReachPlanService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.generate_conversion_rates: gapic_v1.method.wrap_method( + self.generate_conversion_rates, + default_timeout=None, + client_info=client_info, + ), + self.list_plannable_locations: gapic_v1.method.wrap_method( + self.list_plannable_locations, + default_timeout=None, + client_info=client_info, + ), + self.list_plannable_products: gapic_v1.method.wrap_method( + self.list_plannable_products, + default_timeout=None, + client_info=client_info, + ), + self.generate_reach_forecast: gapic_v1.method.wrap_method( + self.generate_reach_forecast, + default_timeout=None, + client_info=client_info, + ), + self.list_plannable_user_lists: gapic_v1.method.wrap_method( + self.list_plannable_user_lists, + default_timeout=None, + client_info=client_info, + ), + self.list_plannable_user_interests: gapic_v1.method.wrap_method( + self.list_plannable_user_interests, + 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 generate_conversion_rates( + self, + ) -> Callable[ + [reach_plan_service.GenerateConversionRatesRequest], + Union[ + reach_plan_service.GenerateConversionRatesResponse, + Awaitable[reach_plan_service.GenerateConversionRatesResponse], + ], + ]: + raise NotImplementedError() + + @property + def list_plannable_locations( + self, + ) -> Callable[ + [reach_plan_service.ListPlannableLocationsRequest], + Union[ + reach_plan_service.ListPlannableLocationsResponse, + Awaitable[reach_plan_service.ListPlannableLocationsResponse], + ], + ]: + raise NotImplementedError() + + @property + def list_plannable_products( + self, + ) -> Callable[ + [reach_plan_service.ListPlannableProductsRequest], + Union[ + reach_plan_service.ListPlannableProductsResponse, + Awaitable[reach_plan_service.ListPlannableProductsResponse], + ], + ]: + raise NotImplementedError() + + @property + def generate_reach_forecast( + self, + ) -> Callable[ + [reach_plan_service.GenerateReachForecastRequest], + Union[ + reach_plan_service.GenerateReachForecastResponse, + Awaitable[reach_plan_service.GenerateReachForecastResponse], + ], + ]: + raise NotImplementedError() + + @property + def list_plannable_user_lists( + self, + ) -> Callable[ + [reach_plan_service.ListPlannableUserListsRequest], + Union[ + reach_plan_service.ListPlannableUserListsResponse, + Awaitable[reach_plan_service.ListPlannableUserListsResponse], + ], + ]: + raise NotImplementedError() + + @property + def list_plannable_user_interests( + self, + ) -> Callable[ + [reach_plan_service.ListPlannableUserInterestsRequest], + Union[ + reach_plan_service.ListPlannableUserInterestsResponse, + Awaitable[reach_plan_service.ListPlannableUserInterestsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ReachPlanServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/reach_plan_service/transports/grpc.py b/google/ads/googleads/v24/services/services/reach_plan_service/transports/grpc.py new file mode 100644 index 000000000..1e2617ba1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/reach_plan_service/transports/grpc.py @@ -0,0 +1,581 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import reach_plan_service +from .base import ReachPlanServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ReachPlanService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ReachPlanService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ReachPlanServiceGrpcTransport(ReachPlanServiceTransport): + """gRPC backend transport for ReachPlanService. + + Reach Plan Service gives users information about audience + size that can be reached through advertisement on YouTube. In + particular, GenerateReachForecast provides estimated number of + people of specified demographics that can be reached by an ad in + a given market by a campaign of certain duration with a defined + budget. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 generate_conversion_rates( + self, + ) -> Callable[ + [reach_plan_service.GenerateConversionRatesRequest], + reach_plan_service.GenerateConversionRatesResponse, + ]: + r"""Return a callable for the generate conversion rates method over gRPC. + + Returns a collection of conversion rate suggestions for + supported plannable products. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateConversionRatesRequest], + ~.GenerateConversionRatesResponse]: + 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 "generate_conversion_rates" not in self._stubs: + self._stubs["generate_conversion_rates"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReachPlanService/GenerateConversionRates", + request_serializer=reach_plan_service.GenerateConversionRatesRequest.serialize, + response_deserializer=reach_plan_service.GenerateConversionRatesResponse.deserialize, + ) + ) + return self._stubs["generate_conversion_rates"] + + @property + def list_plannable_locations( + self, + ) -> Callable[ + [reach_plan_service.ListPlannableLocationsRequest], + reach_plan_service.ListPlannableLocationsResponse, + ]: + r"""Return a callable for the list plannable locations method over gRPC. + + Returns the list of plannable locations (for example, + countries). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListPlannableLocationsRequest], + ~.ListPlannableLocationsResponse]: + 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_plannable_locations" not in self._stubs: + self._stubs["list_plannable_locations"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReachPlanService/ListPlannableLocations", + request_serializer=reach_plan_service.ListPlannableLocationsRequest.serialize, + response_deserializer=reach_plan_service.ListPlannableLocationsResponse.deserialize, + ) + ) + return self._stubs["list_plannable_locations"] + + @property + def list_plannable_products( + self, + ) -> Callable[ + [reach_plan_service.ListPlannableProductsRequest], + reach_plan_service.ListPlannableProductsResponse, + ]: + r"""Return a callable for the list plannable products method over gRPC. + + Returns the list of per-location plannable YouTube ad formats + with allowed targeting. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListPlannableProductsRequest], + ~.ListPlannableProductsResponse]: + 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_plannable_products" not in self._stubs: + self._stubs["list_plannable_products"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReachPlanService/ListPlannableProducts", + request_serializer=reach_plan_service.ListPlannableProductsRequest.serialize, + response_deserializer=reach_plan_service.ListPlannableProductsResponse.deserialize, + ) + ) + return self._stubs["list_plannable_products"] + + @property + def generate_reach_forecast( + self, + ) -> Callable[ + [reach_plan_service.GenerateReachForecastRequest], + reach_plan_service.GenerateReachForecastResponse, + ]: + r"""Return a callable for the generate reach forecast method over gRPC. + + Generates a reach forecast for a given targeting / product mix. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `ReachPlanError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateReachForecastRequest], + ~.GenerateReachForecastResponse]: + 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 "generate_reach_forecast" not in self._stubs: + self._stubs["generate_reach_forecast"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReachPlanService/GenerateReachForecast", + request_serializer=reach_plan_service.GenerateReachForecastRequest.serialize, + response_deserializer=reach_plan_service.GenerateReachForecastResponse.deserialize, + ) + ) + return self._stubs["generate_reach_forecast"] + + @property + def list_plannable_user_lists( + self, + ) -> Callable[ + [reach_plan_service.ListPlannableUserListsRequest], + reach_plan_service.ListPlannableUserListsResponse, + ]: + r"""Return a callable for the list plannable user lists method over gRPC. + + Returns the list of plannable user lists with their plannable + status. User lists may not be plannable for a number of reasons, + including: + + - They are less than 10 days old. + - They have a membership lifespan that is less than 30 days + - They have less than 10,000 or more than 700,000 users. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `ReachPlanError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListPlannableUserListsRequest], + ~.ListPlannableUserListsResponse]: + 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_plannable_user_lists" not in self._stubs: + self._stubs["list_plannable_user_lists"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReachPlanService/ListPlannableUserLists", + request_serializer=reach_plan_service.ListPlannableUserListsRequest.serialize, + response_deserializer=reach_plan_service.ListPlannableUserListsResponse.deserialize, + ) + ) + return self._stubs["list_plannable_user_lists"] + + @property + def list_plannable_user_interests( + self, + ) -> Callable[ + [reach_plan_service.ListPlannableUserInterestsRequest], + reach_plan_service.ListPlannableUserInterestsResponse, + ]: + r"""Return a callable for the list plannable user interests method over gRPC. + + Returns the list of plannable user interests. A plannable user + interest is one that can be targeted in a reach forecast using + [ReachPlanService.GenerateReachForecast][google.ads.googleads.v24.services.ReachPlanService.GenerateReachForecast]. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `ListOperationError <>`__ `QuotaError <>`__ + `RequestError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.ListPlannableUserInterestsRequest], + ~.ListPlannableUserInterestsResponse]: + 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_plannable_user_interests" not in self._stubs: + self._stubs["list_plannable_user_interests"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReachPlanService/ListPlannableUserInterests", + request_serializer=reach_plan_service.ListPlannableUserInterestsRequest.serialize, + response_deserializer=reach_plan_service.ListPlannableUserInterestsResponse.deserialize, + ) + ) + return self._stubs["list_plannable_user_interests"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ReachPlanServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/reach_plan_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/reach_plan_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..b5f5ab4e8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/reach_plan_service/transports/grpc_asyncio.py @@ -0,0 +1,627 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import reach_plan_service +from .base import ReachPlanServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ReachPlanService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ReachPlanService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ReachPlanServiceGrpcAsyncIOTransport(ReachPlanServiceTransport): + """gRPC AsyncIO backend transport for ReachPlanService. + + Reach Plan Service gives users information about audience + size that can be reached through advertisement on YouTube. In + particular, GenerateReachForecast provides estimated number of + people of specified demographics that can be reached by an ad in + a given market by a campaign of certain duration with a defined + budget. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 generate_conversion_rates( + self, + ) -> Callable[ + [reach_plan_service.GenerateConversionRatesRequest], + Awaitable[reach_plan_service.GenerateConversionRatesResponse], + ]: + r"""Return a callable for the generate conversion rates method over gRPC. + + Returns a collection of conversion rate suggestions for + supported plannable products. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateConversionRatesRequest], + Awaitable[~.GenerateConversionRatesResponse]]: + 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 "generate_conversion_rates" not in self._stubs: + self._stubs["generate_conversion_rates"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReachPlanService/GenerateConversionRates", + request_serializer=reach_plan_service.GenerateConversionRatesRequest.serialize, + response_deserializer=reach_plan_service.GenerateConversionRatesResponse.deserialize, + ) + ) + return self._stubs["generate_conversion_rates"] + + @property + def list_plannable_locations( + self, + ) -> Callable[ + [reach_plan_service.ListPlannableLocationsRequest], + Awaitable[reach_plan_service.ListPlannableLocationsResponse], + ]: + r"""Return a callable for the list plannable locations method over gRPC. + + Returns the list of plannable locations (for example, + countries). + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListPlannableLocationsRequest], + Awaitable[~.ListPlannableLocationsResponse]]: + 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_plannable_locations" not in self._stubs: + self._stubs["list_plannable_locations"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReachPlanService/ListPlannableLocations", + request_serializer=reach_plan_service.ListPlannableLocationsRequest.serialize, + response_deserializer=reach_plan_service.ListPlannableLocationsResponse.deserialize, + ) + ) + return self._stubs["list_plannable_locations"] + + @property + def list_plannable_products( + self, + ) -> Callable[ + [reach_plan_service.ListPlannableProductsRequest], + Awaitable[reach_plan_service.ListPlannableProductsResponse], + ]: + r"""Return a callable for the list plannable products method over gRPC. + + Returns the list of per-location plannable YouTube ad formats + with allowed targeting. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListPlannableProductsRequest], + Awaitable[~.ListPlannableProductsResponse]]: + 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_plannable_products" not in self._stubs: + self._stubs["list_plannable_products"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReachPlanService/ListPlannableProducts", + request_serializer=reach_plan_service.ListPlannableProductsRequest.serialize, + response_deserializer=reach_plan_service.ListPlannableProductsResponse.deserialize, + ) + ) + return self._stubs["list_plannable_products"] + + @property + def generate_reach_forecast( + self, + ) -> Callable[ + [reach_plan_service.GenerateReachForecastRequest], + Awaitable[reach_plan_service.GenerateReachForecastResponse], + ]: + r"""Return a callable for the generate reach forecast method over gRPC. + + Generates a reach forecast for a given targeting / product mix. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `ReachPlanError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateReachForecastRequest], + Awaitable[~.GenerateReachForecastResponse]]: + 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 "generate_reach_forecast" not in self._stubs: + self._stubs["generate_reach_forecast"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReachPlanService/GenerateReachForecast", + request_serializer=reach_plan_service.GenerateReachForecastRequest.serialize, + response_deserializer=reach_plan_service.GenerateReachForecastResponse.deserialize, + ) + ) + return self._stubs["generate_reach_forecast"] + + @property + def list_plannable_user_lists( + self, + ) -> Callable[ + [reach_plan_service.ListPlannableUserListsRequest], + Awaitable[reach_plan_service.ListPlannableUserListsResponse], + ]: + r"""Return a callable for the list plannable user lists method over gRPC. + + Returns the list of plannable user lists with their plannable + status. User lists may not be plannable for a number of reasons, + including: + + - They are less than 10 days old. + - They have a membership lifespan that is less than 30 days + - They have less than 10,000 or more than 700,000 users. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RangeError <>`__ + `ReachPlanError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.ListPlannableUserListsRequest], + Awaitable[~.ListPlannableUserListsResponse]]: + 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_plannable_user_lists" not in self._stubs: + self._stubs["list_plannable_user_lists"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReachPlanService/ListPlannableUserLists", + request_serializer=reach_plan_service.ListPlannableUserListsRequest.serialize, + response_deserializer=reach_plan_service.ListPlannableUserListsResponse.deserialize, + ) + ) + return self._stubs["list_plannable_user_lists"] + + @property + def list_plannable_user_interests( + self, + ) -> Callable[ + [reach_plan_service.ListPlannableUserInterestsRequest], + Awaitable[reach_plan_service.ListPlannableUserInterestsResponse], + ]: + r"""Return a callable for the list plannable user interests method over gRPC. + + Returns the list of plannable user interests. A plannable user + interest is one that can be targeted in a reach forecast using + [ReachPlanService.GenerateReachForecast][google.ads.googleads.v24.services.ReachPlanService.GenerateReachForecast]. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `FieldError <>`__ `HeaderError <>`__ + `InternalError <>`__ `ListOperationError <>`__ `QuotaError <>`__ + `RequestError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.ListPlannableUserInterestsRequest], + Awaitable[~.ListPlannableUserInterestsResponse]]: + 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_plannable_user_interests" not in self._stubs: + self._stubs["list_plannable_user_interests"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReachPlanService/ListPlannableUserInterests", + request_serializer=reach_plan_service.ListPlannableUserInterestsRequest.serialize, + response_deserializer=reach_plan_service.ListPlannableUserInterestsResponse.deserialize, + ) + ) + return self._stubs["list_plannable_user_interests"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.generate_conversion_rates: self._wrap_method( + self.generate_conversion_rates, + default_timeout=None, + client_info=client_info, + ), + self.list_plannable_locations: self._wrap_method( + self.list_plannable_locations, + default_timeout=None, + client_info=client_info, + ), + self.list_plannable_products: self._wrap_method( + self.list_plannable_products, + default_timeout=None, + client_info=client_info, + ), + self.generate_reach_forecast: self._wrap_method( + self.generate_reach_forecast, + default_timeout=None, + client_info=client_info, + ), + self.list_plannable_user_lists: self._wrap_method( + self.list_plannable_user_lists, + default_timeout=None, + client_info=client_info, + ), + self.list_plannable_user_interests: self._wrap_method( + self.list_plannable_user_interests, + 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" + + +__all__ = ("ReachPlanServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/recommendation_service/__init__.py b/google/ads/googleads/v24/services/services/recommendation_service/__init__.py new file mode 100644 index 000000000..4ddd61f41 --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import RecommendationServiceClient +from .async_client import RecommendationServiceAsyncClient + +__all__ = ( + "RecommendationServiceClient", + "RecommendationServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/recommendation_service/async_client.py b/google/ads/googleads/v24/services/services/recommendation_service/async_client.py new file mode 100644 index 000000000..3c9184ee9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_service/async_client.py @@ -0,0 +1,713 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.enums.types import ( + advertising_channel_type as gage_advertising_channel_type, +) +from google.ads.googleads.v24.enums.types import recommendation_type +from google.ads.googleads.v24.services.types import recommendation_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import RecommendationServiceTransport, DEFAULT_CLIENT_INFO +from .client import RecommendationServiceClient + +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 RecommendationServiceAsyncClient: + """Service to manage recommendations.""" + + _client: RecommendationServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = RecommendationServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = RecommendationServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + RecommendationServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = RecommendationServiceClient._DEFAULT_UNIVERSE + + ad_path = staticmethod(RecommendationServiceClient.ad_path) + parse_ad_path = staticmethod(RecommendationServiceClient.parse_ad_path) + ad_group_path = staticmethod(RecommendationServiceClient.ad_group_path) + parse_ad_group_path = staticmethod( + RecommendationServiceClient.parse_ad_group_path + ) + asset_path = staticmethod(RecommendationServiceClient.asset_path) + parse_asset_path = staticmethod( + RecommendationServiceClient.parse_asset_path + ) + campaign_path = staticmethod(RecommendationServiceClient.campaign_path) + parse_campaign_path = staticmethod( + RecommendationServiceClient.parse_campaign_path + ) + campaign_budget_path = staticmethod( + RecommendationServiceClient.campaign_budget_path + ) + parse_campaign_budget_path = staticmethod( + RecommendationServiceClient.parse_campaign_budget_path + ) + conversion_action_path = staticmethod( + RecommendationServiceClient.conversion_action_path + ) + parse_conversion_action_path = staticmethod( + RecommendationServiceClient.parse_conversion_action_path + ) + recommendation_path = staticmethod( + RecommendationServiceClient.recommendation_path + ) + parse_recommendation_path = staticmethod( + RecommendationServiceClient.parse_recommendation_path + ) + common_billing_account_path = staticmethod( + RecommendationServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + RecommendationServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + RecommendationServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + RecommendationServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + RecommendationServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + RecommendationServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + RecommendationServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + RecommendationServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + RecommendationServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + RecommendationServiceClient.parse_common_location_path + ) + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + RecommendationServiceAsyncClient: The constructed client. + """ + return RecommendationServiceClient.from_service_account_info.__func__(RecommendationServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + RecommendationServiceAsyncClient: The constructed client. + """ + return RecommendationServiceClient.from_service_account_file.__func__(RecommendationServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return RecommendationServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> RecommendationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + RecommendationServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = RecommendationServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + RecommendationServiceTransport, + Callable[..., RecommendationServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the recommendation service async client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,RecommendationServiceTransport,Callable[..., RecommendationServiceTransport]]]): + 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 RecommendationServiceTransport 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 = RecommendationServiceClient( + 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.ads.googleads.v24.services.RecommendationServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.RecommendationService", + "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.ads.googleads.v24.services.RecommendationService", + "credentialsType": None, + } + ), + ) + + async def apply_recommendation( + self, + request: Optional[ + Union[recommendation_service.ApplyRecommendationRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[recommendation_service.ApplyRecommendationOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> recommendation_service.ApplyRecommendationResponse: + r"""Applies given recommendations with corresponding apply + parameters. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RecommendationError <>`__ `RequestError <>`__ + `UrlFieldError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.ApplyRecommendationRequest, dict]]): + The request object. Request message for + [RecommendationService.ApplyRecommendation][google.ads.googleads.v24.services.RecommendationService.ApplyRecommendation]. + customer_id (:class:`str`): + Required. The ID of the customer with + the recommendation. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.ApplyRecommendationOperation]`): + Required. The list of operations to apply + recommendations. If partial_failure=false all + recommendations should be of the same type There is a + limit of 100 operations per request. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.ApplyRecommendationResponse: + Response message for + [RecommendationService.ApplyRecommendation][google.ads.googleads.v24.services.RecommendationService.ApplyRecommendation]. + + """ + # 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 = [customer_id, operations] + 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, recommendation_service.ApplyRecommendationRequest + ): + request = recommendation_service.ApplyRecommendationRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.apply_recommendation + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 dismiss_recommendation( + self, + request: Optional[ + Union[recommendation_service.DismissRecommendationRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + recommendation_service.DismissRecommendationRequest.DismissRecommendationOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> recommendation_service.DismissRecommendationResponse: + r"""Dismisses given recommendations. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ + `RecommendationError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.DismissRecommendationRequest, dict]]): + The request object. Request message for + [RecommendationService.DismissRecommendation][google.ads.googleads.v24.services.RecommendationService.DismissRecommendation]. + customer_id (:class:`str`): + Required. The ID of the customer with + the recommendation. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.DismissRecommendationRequest.DismissRecommendationOperation]`): + Required. The list of operations to dismiss + recommendations. If partial_failure=false all + recommendations should be of the same type There is a + limit of 100 operations per request. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.DismissRecommendationResponse: + Response message for + [RecommendationService.DismissRecommendation][google.ads.googleads.v24.services.RecommendationService.DismissRecommendation]. + + """ + # 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 = [customer_id, operations] + 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, recommendation_service.DismissRecommendationRequest + ): + request = recommendation_service.DismissRecommendationRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.dismiss_recommendation + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_recommendations( + self, + request: Optional[ + Union[recommendation_service.GenerateRecommendationsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + recommendation_types: Optional[ + MutableSequence[ + recommendation_type.RecommendationTypeEnum.RecommendationType + ] + ] = None, + advertising_channel_type: Optional[ + gage_advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> recommendation_service.GenerateRecommendationsResponse: + r"""Generates Recommendations based off the requested + recommendation_types. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ + `RecommendationError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateRecommendationsRequest, dict]]): + The request object. Request message for + [RecommendationService.GenerateRecommendations][google.ads.googleads.v24.services.RecommendationService.GenerateRecommendations]. + customer_id (:class:`str`): + Required. The ID of the customer + generating recommendations. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + recommendation_types (:class:`MutableSequence[google.ads.googleads.v24.enums.types.RecommendationTypeEnum.RecommendationType]`): + Required. List of eligible recommendation_types to + generate. If the uploaded criteria isn't sufficient to + make a recommendation, or the campaign is already in the + recommended state, no recommendation will be returned + for that type. Generally, a recommendation is returned + if all required fields for that recommendation_type are + uploaded, but there are cases where this is still not + sufficient. + + The following recommendation_types are supported for + recommendation generation: CAMPAIGN_BUDGET, KEYWORD, + MAXIMIZE_CLICKS_OPT_IN, MAXIMIZE_CONVERSIONS_OPT_IN, + MAXIMIZE_CONVERSION_VALUE_OPT_IN, SET_TARGET_CPA, + SET_TARGET_ROAS, SITELINK_ASSET, TARGET_CPA_OPT_IN, + TARGET_ROAS_OPT_IN + + This corresponds to the ``recommendation_types`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + advertising_channel_type (:class:`google.ads.googleads.v24.enums.types.AdvertisingChannelTypeEnum.AdvertisingChannelType`): + Required. Advertising channel type of the campaign. The + following advertising_channel_types are supported for + recommendation generation: PERFORMANCE_MAX and SEARCH + + This corresponds to the ``advertising_channel_type`` 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.ads.googleads.v24.services.types.GenerateRecommendationsResponse: + Response message for + [RecommendationService.GenerateRecommendations][google.ads.googleads.v24.services.RecommendationService.GenerateRecommendations]. + + """ + # 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 = [ + customer_id, + recommendation_types, + advertising_channel_type, + ] + 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, recommendation_service.GenerateRecommendationsRequest + ): + request = recommendation_service.GenerateRecommendationsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if advertising_channel_type is not None: + request.advertising_channel_type = advertising_channel_type + if recommendation_types: + request.recommendation_types.extend(recommendation_types) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_recommendations + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "RecommendationServiceAsyncClient": + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + +if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER + DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ + + +__all__ = ("RecommendationServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/recommendation_service/client.py b/google/ads/googleads/v24/services/services/recommendation_service/client.py new file mode 100644 index 000000000..e67a9d624 --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_service/client.py @@ -0,0 +1,1279 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.enums.types import ( + advertising_channel_type as gage_advertising_channel_type, +) +from google.ads.googleads.v24.enums.types import recommendation_type +from google.ads.googleads.v24.services.types import recommendation_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import RecommendationServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import RecommendationServiceGrpcTransport +from .transports.grpc_asyncio import RecommendationServiceGrpcAsyncIOTransport + + +class RecommendationServiceClientMeta(type): + """Metaclass for the RecommendationService client. + + This provides class-level methods for building and retrieving + support objects (e.g. transport) without polluting the client instance + objects. + """ + + _transport_registry = ( + OrderedDict() + ) # type: Dict[str, Type[RecommendationServiceTransport]] + _transport_registry["grpc"] = RecommendationServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + RecommendationServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[RecommendationServiceTransport]: + """Returns an appropriate transport class. + + Args: + label: The name of the desired transport. If none is + provided, then the first transport in the registry is used. + + Returns: + The transport class to use. + """ + # If a specific transport is requested, return that one. + if label: + return cls._transport_registry[label] + + # No transport is requested; return the default (that is, the first one + # in the dictionary). + return next(iter(cls._transport_registry.values())) + + +class RecommendationServiceClient(metaclass=RecommendationServiceClientMeta): + """Service to manage recommendations.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + RecommendationServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info( + info + ) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + RecommendationServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file( + filename + ) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + from_service_account_json = from_service_account_file + + @property + def transport(self) -> RecommendationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + RecommendationServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ad_path( + customer_id: str, + ad_id: str, + ) -> str: + """Returns a fully-qualified ad string.""" + return "customers/{customer_id}/ads/{ad_id}".format( + customer_id=customer_id, + ad_id=ad_id, + ) + + @staticmethod + def parse_ad_path(path: str) -> Dict[str, str]: + """Parses a ad path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/ads/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_path( + customer_id: str, + ad_group_id: str, + ) -> str: + """Returns a fully-qualified ad_group string.""" + return "customers/{customer_id}/adGroups/{ad_group_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ) + + @staticmethod + def parse_ad_group_path(path: str) -> Dict[str, str]: + """Parses a ad_group path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroups/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def asset_path( + customer_id: str, + asset_id: str, + ) -> str: + """Returns a fully-qualified asset string.""" + return "customers/{customer_id}/assets/{asset_id}".format( + customer_id=customer_id, + asset_id=asset_id, + ) + + @staticmethod + def parse_asset_path(path: str) -> Dict[str, str]: + """Parses a asset path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/assets/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_budget_path( + customer_id: str, + campaign_budget_id: str, + ) -> str: + """Returns a fully-qualified campaign_budget string.""" + return "customers/{customer_id}/campaignBudgets/{campaign_budget_id}".format( + customer_id=customer_id, + campaign_budget_id=campaign_budget_id, + ) + + @staticmethod + def parse_campaign_budget_path(path: str) -> Dict[str, str]: + """Parses a campaign_budget path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignBudgets/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def conversion_action_path( + customer_id: str, + conversion_action_id: str, + ) -> str: + """Returns a fully-qualified conversion_action string.""" + return "customers/{customer_id}/conversionActions/{conversion_action_id}".format( + customer_id=customer_id, + conversion_action_id=conversion_action_id, + ) + + @staticmethod + def parse_conversion_action_path(path: str) -> Dict[str, str]: + """Parses a conversion_action path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/conversionActions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def recommendation_path( + customer_id: str, + recommendation_id: str, + ) -> str: + """Returns a fully-qualified recommendation string.""" + return "customers/{customer_id}/recommendations/{recommendation_id}".format( + customer_id=customer_id, + recommendation_id=recommendation_id, + ) + + @staticmethod + def parse_recommendation_path(path: str) -> Dict[str, str]: + """Parses a recommendation path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/recommendations/(?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 = ( + RecommendationServiceClient._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 = ( + RecommendationServiceClient._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 + ): + """Return the API endpoint used by the client. + + Args: + api_override (str): The API endpoint override. If specified, this is always + the return value of this function and the other arguments are not used. + client_cert_source (bytes): The client certificate source used by the client. + universe_domain (str): The universe domain used by the client. + use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters. + Possible values are "always", "auto", or "never". + + Returns: + str: The API endpoint to be used by the client. + """ + if api_override is not None: + api_endpoint = api_override + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + _default_universe = RecommendationServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = RecommendationServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + RecommendationServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=universe_domain + ) + ) + return api_endpoint + + @staticmethod + def _get_universe_domain( + client_universe_domain: Optional[str], + universe_domain_env: Optional[str], + ) -> str: + """Return the universe domain used by the client. + + Args: + client_universe_domain (Optional[str]): The universe domain configured via the client options. + universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable. + + Returns: + str: The universe domain to be used by the client. + + Raises: + ValueError: If the universe domain is an empty string. + """ + universe_domain = RecommendationServiceClient._DEFAULT_UNIVERSE + if client_universe_domain is not None: + universe_domain = client_universe_domain + elif universe_domain_env is not None: + universe_domain = universe_domain_env + if len(universe_domain.strip()) == 0: + raise ValueError("Universe Domain cannot be an empty string.") + return universe_domain + + 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): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used by the client instance. + """ + return self._universe_domain + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + RecommendationServiceTransport, + Callable[..., RecommendationServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the recommendation service client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,RecommendationServiceTransport,Callable[..., RecommendationServiceTransport]]]): + 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 RecommendationServiceTransport 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, + ) = RecommendationServiceClient._read_environment_variables() + self._client_cert_source = ( + RecommendationServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + RecommendationServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, RecommendationServiceTransport + ) + if transport_provided: + # transport is a RecommendationServiceTransport instance. + if ( + credentials + or self._client_options.credentials_file + or api_key_value + ): + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if self._client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = cast(RecommendationServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or RecommendationServiceClient._get_api_endpoint( + self._client_options.api_endpoint, + self._client_cert_source, + self._universe_domain, + self._use_mtls_endpoint, + ) + ) + + if not transport_provided: + import google.auth._default # type: ignore + + if api_key_value and hasattr( + google.auth._default, "get_api_key_credentials" + ): + credentials = google.auth._default.get_api_key_credentials( + api_key_value + ) + + transport_init: Union[ + Type[RecommendationServiceTransport], + Callable[..., RecommendationServiceTransport], + ] = ( + RecommendationServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., RecommendationServiceTransport], 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.ads.googleads.v24.services.RecommendationServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.RecommendationService", + "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.ads.googleads.v24.services.RecommendationService", + "credentialsType": None, + } + ), + ) + + def apply_recommendation( + self, + request: Optional[ + Union[recommendation_service.ApplyRecommendationRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[recommendation_service.ApplyRecommendationOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> recommendation_service.ApplyRecommendationResponse: + r"""Applies given recommendations with corresponding apply + parameters. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RecommendationError <>`__ `RequestError <>`__ + `UrlFieldError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.ApplyRecommendationRequest, dict]): + The request object. Request message for + [RecommendationService.ApplyRecommendation][google.ads.googleads.v24.services.RecommendationService.ApplyRecommendation]. + customer_id (str): + Required. The ID of the customer with + the recommendation. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.ApplyRecommendationOperation]): + Required. The list of operations to apply + recommendations. If partial_failure=false all + recommendations should be of the same type There is a + limit of 100 operations per request. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.ApplyRecommendationResponse: + Response message for + [RecommendationService.ApplyRecommendation][google.ads.googleads.v24.services.RecommendationService.ApplyRecommendation]. + + """ + # 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 = [customer_id, operations] + 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, recommendation_service.ApplyRecommendationRequest + ): + request = recommendation_service.ApplyRecommendationRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.apply_recommendation + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 dismiss_recommendation( + self, + request: Optional[ + Union[recommendation_service.DismissRecommendationRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + recommendation_service.DismissRecommendationRequest.DismissRecommendationOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> recommendation_service.DismissRecommendationResponse: + r"""Dismisses given recommendations. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ + `RecommendationError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.DismissRecommendationRequest, dict]): + The request object. Request message for + [RecommendationService.DismissRecommendation][google.ads.googleads.v24.services.RecommendationService.DismissRecommendation]. + customer_id (str): + Required. The ID of the customer with + the recommendation. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.DismissRecommendationRequest.DismissRecommendationOperation]): + Required. The list of operations to dismiss + recommendations. If partial_failure=false all + recommendations should be of the same type There is a + limit of 100 operations per request. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.DismissRecommendationResponse: + Response message for + [RecommendationService.DismissRecommendation][google.ads.googleads.v24.services.RecommendationService.DismissRecommendation]. + + """ + # 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 = [customer_id, operations] + 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, recommendation_service.DismissRecommendationRequest + ): + request = recommendation_service.DismissRecommendationRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.dismiss_recommendation + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 generate_recommendations( + self, + request: Optional[ + Union[recommendation_service.GenerateRecommendationsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + recommendation_types: Optional[ + MutableSequence[ + recommendation_type.RecommendationTypeEnum.RecommendationType + ] + ] = None, + advertising_channel_type: Optional[ + gage_advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> recommendation_service.GenerateRecommendationsResponse: + r"""Generates Recommendations based off the requested + recommendation_types. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ + `RecommendationError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateRecommendationsRequest, dict]): + The request object. Request message for + [RecommendationService.GenerateRecommendations][google.ads.googleads.v24.services.RecommendationService.GenerateRecommendations]. + customer_id (str): + Required. The ID of the customer + generating recommendations. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + recommendation_types (MutableSequence[google.ads.googleads.v24.enums.types.RecommendationTypeEnum.RecommendationType]): + Required. List of eligible recommendation_types to + generate. If the uploaded criteria isn't sufficient to + make a recommendation, or the campaign is already in the + recommended state, no recommendation will be returned + for that type. Generally, a recommendation is returned + if all required fields for that recommendation_type are + uploaded, but there are cases where this is still not + sufficient. + + The following recommendation_types are supported for + recommendation generation: CAMPAIGN_BUDGET, KEYWORD, + MAXIMIZE_CLICKS_OPT_IN, MAXIMIZE_CONVERSIONS_OPT_IN, + MAXIMIZE_CONVERSION_VALUE_OPT_IN, SET_TARGET_CPA, + SET_TARGET_ROAS, SITELINK_ASSET, TARGET_CPA_OPT_IN, + TARGET_ROAS_OPT_IN + + This corresponds to the ``recommendation_types`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + advertising_channel_type (google.ads.googleads.v24.enums.types.AdvertisingChannelTypeEnum.AdvertisingChannelType): + Required. Advertising channel type of the campaign. The + following advertising_channel_types are supported for + recommendation generation: PERFORMANCE_MAX and SEARCH + + This corresponds to the ``advertising_channel_type`` 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.ads.googleads.v24.services.types.GenerateRecommendationsResponse: + Response message for + [RecommendationService.GenerateRecommendations][google.ads.googleads.v24.services.RecommendationService.GenerateRecommendations]. + + """ + # 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 = [ + customer_id, + recommendation_types, + advertising_channel_type, + ] + 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, recommendation_service.GenerateRecommendationsRequest + ): + request = recommendation_service.GenerateRecommendationsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if recommendation_types is not None: + request.recommendation_types = recommendation_types + if advertising_channel_type is not None: + request.advertising_channel_type = advertising_channel_type + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_recommendations + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def __enter__(self) -> "RecommendationServiceClient": + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + + +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__ = ("RecommendationServiceClient",) diff --git a/google/ads/googleads/v24/services/services/recommendation_service/transports/README.rst b/google/ads/googleads/v24/services/services/recommendation_service/transports/README.rst new file mode 100644 index 000000000..07e52e089 --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`RecommendationServiceTransport` is the ABC for all transports. +- public child `RecommendationServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `RecommendationServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseRecommendationServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `RecommendationServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/recommendation_service/transports/__init__.py b/google/ads/googleads/v24/services/services/recommendation_service/transports/__init__.py new file mode 100644 index 000000000..76dbceff4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import RecommendationServiceTransport +from .grpc import RecommendationServiceGrpcTransport +from .grpc_asyncio import RecommendationServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[RecommendationServiceTransport]] +_transport_registry["grpc"] = RecommendationServiceGrpcTransport +_transport_registry["grpc_asyncio"] = RecommendationServiceGrpcAsyncIOTransport + +__all__ = ( + "RecommendationServiceTransport", + "RecommendationServiceGrpcTransport", + "RecommendationServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/recommendation_service/transports/base.py b/google/ads/googleads/v24/services/services/recommendation_service/transports/base.py new file mode 100644 index 000000000..9def00eef --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_service/transports/base.py @@ -0,0 +1,207 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import recommendation_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 RecommendationServiceTransport(abc.ABC): + """Abstract transport class for RecommendationService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.apply_recommendation: gapic_v1.method.wrap_method( + self.apply_recommendation, + default_timeout=None, + client_info=client_info, + ), + self.dismiss_recommendation: gapic_v1.method.wrap_method( + self.dismiss_recommendation, + default_timeout=None, + client_info=client_info, + ), + self.generate_recommendations: gapic_v1.method.wrap_method( + self.generate_recommendations, + 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 apply_recommendation( + self, + ) -> Callable[ + [recommendation_service.ApplyRecommendationRequest], + Union[ + recommendation_service.ApplyRecommendationResponse, + Awaitable[recommendation_service.ApplyRecommendationResponse], + ], + ]: + raise NotImplementedError() + + @property + def dismiss_recommendation( + self, + ) -> Callable[ + [recommendation_service.DismissRecommendationRequest], + Union[ + recommendation_service.DismissRecommendationResponse, + Awaitable[recommendation_service.DismissRecommendationResponse], + ], + ]: + raise NotImplementedError() + + @property + def generate_recommendations( + self, + ) -> Callable[ + [recommendation_service.GenerateRecommendationsRequest], + Union[ + recommendation_service.GenerateRecommendationsResponse, + Awaitable[recommendation_service.GenerateRecommendationsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("RecommendationServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/recommendation_service/transports/grpc.py b/google/ads/googleads/v24/services/services/recommendation_service/transports/grpc.py new file mode 100644 index 000000000..144d445b1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_service/transports/grpc.py @@ -0,0 +1,463 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import recommendation_service +from .base import RecommendationServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.RecommendationService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.RecommendationService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class RecommendationServiceGrpcTransport(RecommendationServiceTransport): + """gRPC backend transport for RecommendationService. + + Service to manage recommendations. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _stubs: Dict[str, Callable] + + def __init__( + self, + *, + host: str = "googleads.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: 'googleads.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. + + 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 = "googleads.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 apply_recommendation( + self, + ) -> Callable[ + [recommendation_service.ApplyRecommendationRequest], + recommendation_service.ApplyRecommendationResponse, + ]: + r"""Return a callable for the apply recommendation method over gRPC. + + Applies given recommendations with corresponding apply + parameters. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RecommendationError <>`__ `RequestError <>`__ + `UrlFieldError <>`__ + + Returns: + Callable[[~.ApplyRecommendationRequest], + ~.ApplyRecommendationResponse]: + 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 "apply_recommendation" not in self._stubs: + self._stubs["apply_recommendation"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.RecommendationService/ApplyRecommendation", + request_serializer=recommendation_service.ApplyRecommendationRequest.serialize, + response_deserializer=recommendation_service.ApplyRecommendationResponse.deserialize, + ) + ) + return self._stubs["apply_recommendation"] + + @property + def dismiss_recommendation( + self, + ) -> Callable[ + [recommendation_service.DismissRecommendationRequest], + recommendation_service.DismissRecommendationResponse, + ]: + r"""Return a callable for the dismiss recommendation method over gRPC. + + Dismisses given recommendations. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ + `RecommendationError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.DismissRecommendationRequest], + ~.DismissRecommendationResponse]: + 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 "dismiss_recommendation" not in self._stubs: + self._stubs["dismiss_recommendation"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.RecommendationService/DismissRecommendation", + request_serializer=recommendation_service.DismissRecommendationRequest.serialize, + response_deserializer=recommendation_service.DismissRecommendationResponse.deserialize, + ) + ) + return self._stubs["dismiss_recommendation"] + + @property + def generate_recommendations( + self, + ) -> Callable[ + [recommendation_service.GenerateRecommendationsRequest], + recommendation_service.GenerateRecommendationsResponse, + ]: + r"""Return a callable for the generate recommendations method over gRPC. + + Generates Recommendations based off the requested + recommendation_types. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ + `RecommendationError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateRecommendationsRequest], + ~.GenerateRecommendationsResponse]: + 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 "generate_recommendations" not in self._stubs: + self._stubs["generate_recommendations"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.RecommendationService/GenerateRecommendations", + request_serializer=recommendation_service.GenerateRecommendationsRequest.serialize, + response_deserializer=recommendation_service.GenerateRecommendationsResponse.deserialize, + ) + ) + return self._stubs["generate_recommendations"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("RecommendationServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/recommendation_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/recommendation_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..d4d24f053 --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_service/transports/grpc_asyncio.py @@ -0,0 +1,494 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import recommendation_service +from .base import RecommendationServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.RecommendationService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.RecommendationService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class RecommendationServiceGrpcAsyncIOTransport(RecommendationServiceTransport): + """gRPC AsyncIO backend transport for RecommendationService. + + Service to manage recommendations. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _grpc_channel: aio.Channel + _stubs: Dict[str, Callable] = {} + + @classmethod + def create_channel( + cls, + host: str = "googleads.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 = "googleads.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: 'googleads.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. + + 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 apply_recommendation( + self, + ) -> Callable[ + [recommendation_service.ApplyRecommendationRequest], + Awaitable[recommendation_service.ApplyRecommendationResponse], + ]: + r"""Return a callable for the apply recommendation method over gRPC. + + Applies given recommendations with corresponding apply + parameters. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RecommendationError <>`__ `RequestError <>`__ + `UrlFieldError <>`__ + + Returns: + Callable[[~.ApplyRecommendationRequest], + Awaitable[~.ApplyRecommendationResponse]]: + 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 "apply_recommendation" not in self._stubs: + self._stubs["apply_recommendation"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.RecommendationService/ApplyRecommendation", + request_serializer=recommendation_service.ApplyRecommendationRequest.serialize, + response_deserializer=recommendation_service.ApplyRecommendationResponse.deserialize, + ) + ) + return self._stubs["apply_recommendation"] + + @property + def dismiss_recommendation( + self, + ) -> Callable[ + [recommendation_service.DismissRecommendationRequest], + Awaitable[recommendation_service.DismissRecommendationResponse], + ]: + r"""Return a callable for the dismiss recommendation method over gRPC. + + Dismisses given recommendations. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ + `RecommendationError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.DismissRecommendationRequest], + Awaitable[~.DismissRecommendationResponse]]: + 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 "dismiss_recommendation" not in self._stubs: + self._stubs["dismiss_recommendation"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.RecommendationService/DismissRecommendation", + request_serializer=recommendation_service.DismissRecommendationRequest.serialize, + response_deserializer=recommendation_service.DismissRecommendationResponse.deserialize, + ) + ) + return self._stubs["dismiss_recommendation"] + + @property + def generate_recommendations( + self, + ) -> Callable[ + [recommendation_service.GenerateRecommendationsRequest], + Awaitable[recommendation_service.GenerateRecommendationsResponse], + ]: + r"""Return a callable for the generate recommendations method over gRPC. + + Generates Recommendations based off the requested + recommendation_types. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ + `RecommendationError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GenerateRecommendationsRequest], + Awaitable[~.GenerateRecommendationsResponse]]: + 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 "generate_recommendations" not in self._stubs: + self._stubs["generate_recommendations"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.RecommendationService/GenerateRecommendations", + request_serializer=recommendation_service.GenerateRecommendationsRequest.serialize, + response_deserializer=recommendation_service.GenerateRecommendationsResponse.deserialize, + ) + ) + return self._stubs["generate_recommendations"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.apply_recommendation: self._wrap_method( + self.apply_recommendation, + default_timeout=None, + client_info=client_info, + ), + self.dismiss_recommendation: self._wrap_method( + self.dismiss_recommendation, + default_timeout=None, + client_info=client_info, + ), + self.generate_recommendations: self._wrap_method( + self.generate_recommendations, + 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" + + +__all__ = ("RecommendationServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/recommendation_subscription_service/__init__.py b/google/ads/googleads/v24/services/services/recommendation_subscription_service/__init__.py new file mode 100644 index 000000000..da009d507 --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_subscription_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import RecommendationSubscriptionServiceClient +from .async_client import RecommendationSubscriptionServiceAsyncClient + +__all__ = ( + "RecommendationSubscriptionServiceClient", + "RecommendationSubscriptionServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/recommendation_subscription_service/async_client.py b/google/ads/googleads/v24/services/services/recommendation_subscription_service/async_client.py new file mode 100644 index 000000000..1fabb53d1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_subscription_service/async_client.py @@ -0,0 +1,447 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + recommendation_subscription_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + RecommendationSubscriptionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import RecommendationSubscriptionServiceClient + +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 RecommendationSubscriptionServiceAsyncClient: + """Service to manage recommendation subscriptions.""" + + _client: RecommendationSubscriptionServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = RecommendationSubscriptionServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + RecommendationSubscriptionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + RecommendationSubscriptionServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ( + RecommendationSubscriptionServiceClient._DEFAULT_UNIVERSE + ) + + recommendation_subscription_path = staticmethod( + RecommendationSubscriptionServiceClient.recommendation_subscription_path + ) + parse_recommendation_subscription_path = staticmethod( + RecommendationSubscriptionServiceClient.parse_recommendation_subscription_path + ) + common_billing_account_path = staticmethod( + RecommendationSubscriptionServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + RecommendationSubscriptionServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + RecommendationSubscriptionServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + RecommendationSubscriptionServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + RecommendationSubscriptionServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + RecommendationSubscriptionServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + RecommendationSubscriptionServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + RecommendationSubscriptionServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + RecommendationSubscriptionServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + RecommendationSubscriptionServiceClient.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: + RecommendationSubscriptionServiceAsyncClient: The constructed client. + """ + return RecommendationSubscriptionServiceClient.from_service_account_info.__func__(RecommendationSubscriptionServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + RecommendationSubscriptionServiceAsyncClient: The constructed client. + """ + return RecommendationSubscriptionServiceClient.from_service_account_file.__func__(RecommendationSubscriptionServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return RecommendationSubscriptionServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> RecommendationSubscriptionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + RecommendationSubscriptionServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + RecommendationSubscriptionServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + RecommendationSubscriptionServiceTransport, + Callable[..., RecommendationSubscriptionServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the recommendation subscription 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,RecommendationSubscriptionServiceTransport,Callable[..., RecommendationSubscriptionServiceTransport]]]): + 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 RecommendationSubscriptionServiceTransport 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 = RecommendationSubscriptionServiceClient( + 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.ads.googleads.v24.services.RecommendationSubscriptionServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.RecommendationSubscriptionService", + "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.ads.googleads.v24.services.RecommendationSubscriptionService", + "credentialsType": None, + } + ), + ) + + async def mutate_recommendation_subscription( + self, + request: Optional[ + Union[ + recommendation_subscription_service.MutateRecommendationSubscriptionRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + recommendation_subscription_service.RecommendationSubscriptionOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + recommendation_subscription_service.MutateRecommendationSubscriptionResponse + ): + r"""Mutates given subscription with corresponding apply parameters. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RecommendationError <>`__ + `RecommendationSubscriptionError <>`__ `RequestError <>`__ + `UrlFieldError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateRecommendationSubscriptionRequest, dict]]): + The request object. Request message for + [RecommendationSubscriptionService.MutateRecommendationSubscription][google.ads.googleads.v24.services.RecommendationSubscriptionService.MutateRecommendationSubscription] + customer_id (:class:`str`): + Required. The ID of the subscribing + customer. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.RecommendationSubscriptionOperation]`): + Required. The list of create or + update operations. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateRecommendationSubscriptionResponse: + Response message for + [RecommendationSubscriptionService.MutateRecommendationSubscription][google.ads.googleads.v24.services.RecommendationSubscriptionService.MutateRecommendationSubscription] + + """ + # 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 = [customer_id, operations] + 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, + recommendation_subscription_service.MutateRecommendationSubscriptionRequest, + ): + request = recommendation_subscription_service.MutateRecommendationSubscriptionRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_recommendation_subscription + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__( + self, + ) -> "RecommendationSubscriptionServiceAsyncClient": + 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__ = ("RecommendationSubscriptionServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/recommendation_subscription_service/client.py b/google/ads/googleads/v24/services/services/recommendation_subscription_service/client.py new file mode 100644 index 000000000..2902c8b81 --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_subscription_service/client.py @@ -0,0 +1,930 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + recommendation_subscription_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + RecommendationSubscriptionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import RecommendationSubscriptionServiceGrpcTransport +from .transports.grpc_asyncio import ( + RecommendationSubscriptionServiceGrpcAsyncIOTransport, +) + + +class RecommendationSubscriptionServiceClientMeta(type): + """Metaclass for the RecommendationSubscriptionService 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[RecommendationSubscriptionServiceTransport]] + _transport_registry["grpc"] = RecommendationSubscriptionServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + RecommendationSubscriptionServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[RecommendationSubscriptionServiceTransport]: + """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 RecommendationSubscriptionServiceClient( + metaclass=RecommendationSubscriptionServiceClientMeta +): + """Service to manage recommendation subscriptions.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + RecommendationSubscriptionServiceClient: 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: + RecommendationSubscriptionServiceClient: 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) -> RecommendationSubscriptionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + RecommendationSubscriptionServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def recommendation_subscription_path( + customer_id: str, + recommendation_type: str, + ) -> str: + """Returns a fully-qualified recommendation_subscription string.""" + return "customers/{customer_id}/recommendationSubscriptions/{recommendation_type}".format( + customer_id=customer_id, + recommendation_type=recommendation_type, + ) + + @staticmethod + def parse_recommendation_subscription_path(path: str) -> Dict[str, str]: + """Parses a recommendation_subscription path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/recommendationSubscriptions/(?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 = ( + RecommendationSubscriptionServiceClient._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 = ( + RecommendationSubscriptionServiceClient._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 + ): + """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 = ( + RecommendationSubscriptionServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + RecommendationSubscriptionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = RecommendationSubscriptionServiceClient._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 = ( + RecommendationSubscriptionServiceClient._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): + """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, + RecommendationSubscriptionServiceTransport, + Callable[..., RecommendationSubscriptionServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the recommendation subscription 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,RecommendationSubscriptionServiceTransport,Callable[..., RecommendationSubscriptionServiceTransport]]]): + 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 RecommendationSubscriptionServiceTransport 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, + ) = ( + RecommendationSubscriptionServiceClient._read_environment_variables() + ) + self._client_cert_source = ( + RecommendationSubscriptionServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + RecommendationSubscriptionServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, RecommendationSubscriptionServiceTransport + ) + if transport_provided: + # transport is a RecommendationSubscriptionServiceTransport 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( + RecommendationSubscriptionServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or RecommendationSubscriptionServiceClient._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[RecommendationSubscriptionServiceTransport], + Callable[..., RecommendationSubscriptionServiceTransport], + ] = ( + RecommendationSubscriptionServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., RecommendationSubscriptionServiceTransport], + 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.ads.googleads.v24.services.RecommendationSubscriptionServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.RecommendationSubscriptionService", + "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.ads.googleads.v24.services.RecommendationSubscriptionService", + "credentialsType": None, + } + ), + ) + + def mutate_recommendation_subscription( + self, + request: Optional[ + Union[ + recommendation_subscription_service.MutateRecommendationSubscriptionRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + recommendation_subscription_service.RecommendationSubscriptionOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + recommendation_subscription_service.MutateRecommendationSubscriptionResponse + ): + r"""Mutates given subscription with corresponding apply parameters. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RecommendationError <>`__ + `RecommendationSubscriptionError <>`__ `RequestError <>`__ + `UrlFieldError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateRecommendationSubscriptionRequest, dict]): + The request object. Request message for + [RecommendationSubscriptionService.MutateRecommendationSubscription][google.ads.googleads.v24.services.RecommendationSubscriptionService.MutateRecommendationSubscription] + customer_id (str): + Required. The ID of the subscribing + customer. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.RecommendationSubscriptionOperation]): + Required. The list of create or + update operations. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateRecommendationSubscriptionResponse: + Response message for + [RecommendationSubscriptionService.MutateRecommendationSubscription][google.ads.googleads.v24.services.RecommendationSubscriptionService.MutateRecommendationSubscription] + + """ + # 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 = [customer_id, operations] + 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, + recommendation_subscription_service.MutateRecommendationSubscriptionRequest, + ): + request = recommendation_subscription_service.MutateRecommendationSubscriptionRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_recommendation_subscription + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "RecommendationSubscriptionServiceClient": + 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() + + +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__ = ("RecommendationSubscriptionServiceClient",) diff --git a/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/README.rst b/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/README.rst new file mode 100644 index 000000000..80945eadc --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`RecommendationSubscriptionServiceTransport` is the ABC for all transports. +- public child `RecommendationSubscriptionServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `RecommendationSubscriptionServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseRecommendationSubscriptionServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `RecommendationSubscriptionServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/__init__.py b/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/__init__.py new file mode 100644 index 000000000..37b22c914 --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import RecommendationSubscriptionServiceTransport +from .grpc import RecommendationSubscriptionServiceGrpcTransport +from .grpc_asyncio import RecommendationSubscriptionServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[RecommendationSubscriptionServiceTransport]] +_transport_registry["grpc"] = RecommendationSubscriptionServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + RecommendationSubscriptionServiceGrpcAsyncIOTransport +) + +__all__ = ( + "RecommendationSubscriptionServiceTransport", + "RecommendationSubscriptionServiceGrpcTransport", + "RecommendationSubscriptionServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/base.py b/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/base.py new file mode 100644 index 000000000..e24fe87e3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + recommendation_subscription_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 RecommendationSubscriptionServiceTransport(abc.ABC): + """Abstract transport class for RecommendationSubscriptionService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_recommendation_subscription: gapic_v1.method.wrap_method( + self.mutate_recommendation_subscription, + 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 mutate_recommendation_subscription( + self, + ) -> Callable[ + [ + recommendation_subscription_service.MutateRecommendationSubscriptionRequest + ], + Union[ + recommendation_subscription_service.MutateRecommendationSubscriptionResponse, + Awaitable[ + recommendation_subscription_service.MutateRecommendationSubscriptionResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("RecommendationSubscriptionServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/grpc.py b/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/grpc.py new file mode 100644 index 000000000..912368103 --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/grpc.py @@ -0,0 +1,400 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + recommendation_subscription_service, +) +from .base import ( + RecommendationSubscriptionServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.RecommendationSubscriptionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.RecommendationSubscriptionService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class RecommendationSubscriptionServiceGrpcTransport( + RecommendationSubscriptionServiceTransport +): + """gRPC backend transport for RecommendationSubscriptionService. + + Service to manage recommendation subscriptions. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_recommendation_subscription( + self, + ) -> Callable[ + [ + recommendation_subscription_service.MutateRecommendationSubscriptionRequest + ], + recommendation_subscription_service.MutateRecommendationSubscriptionResponse, + ]: + r"""Return a callable for the mutate recommendation + subscription method over gRPC. + + Mutates given subscription with corresponding apply parameters. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RecommendationError <>`__ + `RecommendationSubscriptionError <>`__ `RequestError <>`__ + `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateRecommendationSubscriptionRequest], + ~.MutateRecommendationSubscriptionResponse]: + 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 "mutate_recommendation_subscription" not in self._stubs: + self._stubs["mutate_recommendation_subscription"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.RecommendationSubscriptionService/MutateRecommendationSubscription", + request_serializer=recommendation_subscription_service.MutateRecommendationSubscriptionRequest.serialize, + response_deserializer=recommendation_subscription_service.MutateRecommendationSubscriptionResponse.deserialize, + ) + ) + return self._stubs["mutate_recommendation_subscription"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("RecommendationSubscriptionServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..c40c5792f --- /dev/null +++ b/google/ads/googleads/v24/services/services/recommendation_subscription_service/transports/grpc_asyncio.py @@ -0,0 +1,423 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + recommendation_subscription_service, +) +from .base import ( + RecommendationSubscriptionServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.RecommendationSubscriptionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.RecommendationSubscriptionService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class RecommendationSubscriptionServiceGrpcAsyncIOTransport( + RecommendationSubscriptionServiceTransport +): + """gRPC AsyncIO backend transport for RecommendationSubscriptionService. + + Service to manage recommendation subscriptions. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_recommendation_subscription( + self, + ) -> Callable[ + [ + recommendation_subscription_service.MutateRecommendationSubscriptionRequest + ], + Awaitable[ + recommendation_subscription_service.MutateRecommendationSubscriptionResponse + ], + ]: + r"""Return a callable for the mutate recommendation + subscription method over gRPC. + + Mutates given subscription with corresponding apply parameters. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `FieldError <>`__ + `HeaderError <>`__ `InternalError <>`__ `MutateError <>`__ + `QuotaError <>`__ `RecommendationError <>`__ + `RecommendationSubscriptionError <>`__ `RequestError <>`__ + `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateRecommendationSubscriptionRequest], + Awaitable[~.MutateRecommendationSubscriptionResponse]]: + 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 "mutate_recommendation_subscription" not in self._stubs: + self._stubs["mutate_recommendation_subscription"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.RecommendationSubscriptionService/MutateRecommendationSubscription", + request_serializer=recommendation_subscription_service.MutateRecommendationSubscriptionRequest.serialize, + response_deserializer=recommendation_subscription_service.MutateRecommendationSubscriptionResponse.deserialize, + ) + ) + return self._stubs["mutate_recommendation_subscription"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_recommendation_subscription: self._wrap_method( + self.mutate_recommendation_subscription, + 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" + + +__all__ = ("RecommendationSubscriptionServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/remarketing_action_service/__init__.py b/google/ads/googleads/v24/services/services/remarketing_action_service/__init__.py new file mode 100644 index 000000000..1d524f227 --- /dev/null +++ b/google/ads/googleads/v24/services/services/remarketing_action_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import RemarketingActionServiceClient +from .async_client import RemarketingActionServiceAsyncClient + +__all__ = ( + "RemarketingActionServiceClient", + "RemarketingActionServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/remarketing_action_service/async_client.py b/google/ads/googleads/v24/services/services/remarketing_action_service/async_client.py new file mode 100644 index 000000000..6dfe9d91a --- /dev/null +++ b/google/ads/googleads/v24/services/services/remarketing_action_service/async_client.py @@ -0,0 +1,436 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import remarketing_action_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + RemarketingActionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import RemarketingActionServiceClient + +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 RemarketingActionServiceAsyncClient: + """Service to manage remarketing actions.""" + + _client: RemarketingActionServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = RemarketingActionServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = RemarketingActionServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + RemarketingActionServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = RemarketingActionServiceClient._DEFAULT_UNIVERSE + + remarketing_action_path = staticmethod( + RemarketingActionServiceClient.remarketing_action_path + ) + parse_remarketing_action_path = staticmethod( + RemarketingActionServiceClient.parse_remarketing_action_path + ) + common_billing_account_path = staticmethod( + RemarketingActionServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + RemarketingActionServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + RemarketingActionServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + RemarketingActionServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + RemarketingActionServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + RemarketingActionServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + RemarketingActionServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + RemarketingActionServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + RemarketingActionServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + RemarketingActionServiceClient.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: + RemarketingActionServiceAsyncClient: The constructed client. + """ + return RemarketingActionServiceClient.from_service_account_info.__func__(RemarketingActionServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + RemarketingActionServiceAsyncClient: The constructed client. + """ + return RemarketingActionServiceClient.from_service_account_file.__func__(RemarketingActionServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return RemarketingActionServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> RemarketingActionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + RemarketingActionServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = RemarketingActionServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + RemarketingActionServiceTransport, + Callable[..., RemarketingActionServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the remarketing action 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,RemarketingActionServiceTransport,Callable[..., RemarketingActionServiceTransport]]]): + 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 RemarketingActionServiceTransport 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 = RemarketingActionServiceClient( + 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.ads.googleads.v24.services.RemarketingActionServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.RemarketingActionService", + "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.ads.googleads.v24.services.RemarketingActionService", + "credentialsType": None, + } + ), + ) + + async def mutate_remarketing_actions( + self, + request: Optional[ + Union[ + remarketing_action_service.MutateRemarketingActionsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + remarketing_action_service.RemarketingActionOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> remarketing_action_service.MutateRemarketingActionsResponse: + r"""Creates or updates remarketing actions. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionActionError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateRemarketingActionsRequest, dict]]): + The request object. Request message for + [RemarketingActionService.MutateRemarketingActions][google.ads.googleads.v24.services.RemarketingActionService.MutateRemarketingActions]. + customer_id (:class:`str`): + Required. The ID of the customer + whose remarketing actions are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.RemarketingActionOperation]`): + Required. The list of operations to + perform on individual remarketing + actions. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateRemarketingActionsResponse: + Response message for remarketing + action mutate. + + """ + # 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 = [customer_id, operations] + 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, remarketing_action_service.MutateRemarketingActionsRequest + ): + request = ( + remarketing_action_service.MutateRemarketingActionsRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_remarketing_actions + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "RemarketingActionServiceAsyncClient": + 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__ = ("RemarketingActionServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/remarketing_action_service/client.py b/google/ads/googleads/v24/services/services/remarketing_action_service/client.py new file mode 100644 index 000000000..97789cb7d --- /dev/null +++ b/google/ads/googleads/v24/services/services/remarketing_action_service/client.py @@ -0,0 +1,914 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import remarketing_action_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + RemarketingActionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import RemarketingActionServiceGrpcTransport +from .transports.grpc_asyncio import ( + RemarketingActionServiceGrpcAsyncIOTransport, +) + + +class RemarketingActionServiceClientMeta(type): + """Metaclass for the RemarketingActionService 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[RemarketingActionServiceTransport]] + _transport_registry["grpc"] = RemarketingActionServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + RemarketingActionServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[RemarketingActionServiceTransport]: + """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 RemarketingActionServiceClient( + metaclass=RemarketingActionServiceClientMeta +): + """Service to manage remarketing actions.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + RemarketingActionServiceClient: 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: + RemarketingActionServiceClient: 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) -> RemarketingActionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + RemarketingActionServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def remarketing_action_path( + customer_id: str, + remarketing_action_id: str, + ) -> str: + """Returns a fully-qualified remarketing_action string.""" + return "customers/{customer_id}/remarketingActions/{remarketing_action_id}".format( + customer_id=customer_id, + remarketing_action_id=remarketing_action_id, + ) + + @staticmethod + def parse_remarketing_action_path(path: str) -> Dict[str, str]: + """Parses a remarketing_action path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/remarketingActions/(?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 = ( + RemarketingActionServiceClient._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 = ( + RemarketingActionServiceClient._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 + ): + """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 = RemarketingActionServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = RemarketingActionServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = RemarketingActionServiceClient._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 = RemarketingActionServiceClient._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): + """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, + RemarketingActionServiceTransport, + Callable[..., RemarketingActionServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the remarketing action 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,RemarketingActionServiceTransport,Callable[..., RemarketingActionServiceTransport]]]): + 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 RemarketingActionServiceTransport 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, + ) = RemarketingActionServiceClient._read_environment_variables() + self._client_cert_source = ( + RemarketingActionServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + RemarketingActionServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, RemarketingActionServiceTransport + ) + if transport_provided: + # transport is a RemarketingActionServiceTransport 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(RemarketingActionServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or RemarketingActionServiceClient._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[RemarketingActionServiceTransport], + Callable[..., RemarketingActionServiceTransport], + ] = ( + RemarketingActionServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., RemarketingActionServiceTransport], 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.ads.googleads.v24.services.RemarketingActionServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.RemarketingActionService", + "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.ads.googleads.v24.services.RemarketingActionService", + "credentialsType": None, + } + ), + ) + + def mutate_remarketing_actions( + self, + request: Optional[ + Union[ + remarketing_action_service.MutateRemarketingActionsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + remarketing_action_service.RemarketingActionOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> remarketing_action_service.MutateRemarketingActionsResponse: + r"""Creates or updates remarketing actions. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionActionError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateRemarketingActionsRequest, dict]): + The request object. Request message for + [RemarketingActionService.MutateRemarketingActions][google.ads.googleads.v24.services.RemarketingActionService.MutateRemarketingActions]. + customer_id (str): + Required. The ID of the customer + whose remarketing actions are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.RemarketingActionOperation]): + Required. The list of operations to + perform on individual remarketing + actions. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateRemarketingActionsResponse: + Response message for remarketing + action mutate. + + """ + # 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 = [customer_id, operations] + 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, remarketing_action_service.MutateRemarketingActionsRequest + ): + request = ( + remarketing_action_service.MutateRemarketingActionsRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_remarketing_actions + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "RemarketingActionServiceClient": + 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() + + +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__ = ("RemarketingActionServiceClient",) diff --git a/google/ads/googleads/v24/services/services/remarketing_action_service/transports/README.rst b/google/ads/googleads/v24/services/services/remarketing_action_service/transports/README.rst new file mode 100644 index 000000000..3b8454253 --- /dev/null +++ b/google/ads/googleads/v24/services/services/remarketing_action_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`RemarketingActionServiceTransport` is the ABC for all transports. +- public child `RemarketingActionServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `RemarketingActionServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseRemarketingActionServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `RemarketingActionServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/remarketing_action_service/transports/__init__.py b/google/ads/googleads/v24/services/services/remarketing_action_service/transports/__init__.py new file mode 100644 index 000000000..cd8b7a6a5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/remarketing_action_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import RemarketingActionServiceTransport +from .grpc import RemarketingActionServiceGrpcTransport +from .grpc_asyncio import RemarketingActionServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[RemarketingActionServiceTransport]] +_transport_registry["grpc"] = RemarketingActionServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + RemarketingActionServiceGrpcAsyncIOTransport +) + +__all__ = ( + "RemarketingActionServiceTransport", + "RemarketingActionServiceGrpcTransport", + "RemarketingActionServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/remarketing_action_service/transports/base.py b/google/ads/googleads/v24/services/services/remarketing_action_service/transports/base.py new file mode 100644 index 000000000..244b19e4e --- /dev/null +++ b/google/ads/googleads/v24/services/services/remarketing_action_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import remarketing_action_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 RemarketingActionServiceTransport(abc.ABC): + """Abstract transport class for RemarketingActionService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_remarketing_actions: gapic_v1.method.wrap_method( + self.mutate_remarketing_actions, + 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 mutate_remarketing_actions( + self, + ) -> Callable[ + [remarketing_action_service.MutateRemarketingActionsRequest], + Union[ + remarketing_action_service.MutateRemarketingActionsResponse, + Awaitable[ + remarketing_action_service.MutateRemarketingActionsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("RemarketingActionServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/remarketing_action_service/transports/grpc.py b/google/ads/googleads/v24/services/services/remarketing_action_service/transports/grpc.py new file mode 100644 index 000000000..6dfae93ba --- /dev/null +++ b/google/ads/googleads/v24/services/services/remarketing_action_service/transports/grpc.py @@ -0,0 +1,389 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import remarketing_action_service +from .base import RemarketingActionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.RemarketingActionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.RemarketingActionService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class RemarketingActionServiceGrpcTransport(RemarketingActionServiceTransport): + """gRPC backend transport for RemarketingActionService. + + Service to manage remarketing actions. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_remarketing_actions( + self, + ) -> Callable[ + [remarketing_action_service.MutateRemarketingActionsRequest], + remarketing_action_service.MutateRemarketingActionsResponse, + ]: + r"""Return a callable for the mutate remarketing actions method over gRPC. + + Creates or updates remarketing actions. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionActionError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateRemarketingActionsRequest], + ~.MutateRemarketingActionsResponse]: + 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 "mutate_remarketing_actions" not in self._stubs: + self._stubs["mutate_remarketing_actions"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.RemarketingActionService/MutateRemarketingActions", + request_serializer=remarketing_action_service.MutateRemarketingActionsRequest.serialize, + response_deserializer=remarketing_action_service.MutateRemarketingActionsResponse.deserialize, + ) + ) + return self._stubs["mutate_remarketing_actions"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("RemarketingActionServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/remarketing_action_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/remarketing_action_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..56dad5d70 --- /dev/null +++ b/google/ads/googleads/v24/services/services/remarketing_action_service/transports/grpc_asyncio.py @@ -0,0 +1,412 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import remarketing_action_service +from .base import RemarketingActionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.RemarketingActionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.RemarketingActionService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class RemarketingActionServiceGrpcAsyncIOTransport( + RemarketingActionServiceTransport +): + """gRPC AsyncIO backend transport for RemarketingActionService. + + Service to manage remarketing actions. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_remarketing_actions( + self, + ) -> Callable[ + [remarketing_action_service.MutateRemarketingActionsRequest], + Awaitable[remarketing_action_service.MutateRemarketingActionsResponse], + ]: + r"""Return a callable for the mutate remarketing actions method over gRPC. + + Creates or updates remarketing actions. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `ConversionActionError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateRemarketingActionsRequest], + Awaitable[~.MutateRemarketingActionsResponse]]: + 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 "mutate_remarketing_actions" not in self._stubs: + self._stubs["mutate_remarketing_actions"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.RemarketingActionService/MutateRemarketingActions", + request_serializer=remarketing_action_service.MutateRemarketingActionsRequest.serialize, + response_deserializer=remarketing_action_service.MutateRemarketingActionsResponse.deserialize, + ) + ) + return self._stubs["mutate_remarketing_actions"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_remarketing_actions: self._wrap_method( + self.mutate_remarketing_actions, + 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" + + +__all__ = ("RemarketingActionServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/reservation_service/__init__.py b/google/ads/googleads/v24/services/services/reservation_service/__init__.py new file mode 100644 index 000000000..08b898ebb --- /dev/null +++ b/google/ads/googleads/v24/services/services/reservation_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ReservationServiceClient +from .async_client import ReservationServiceAsyncClient + +__all__ = ( + "ReservationServiceClient", + "ReservationServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/reservation_service/async_client.py b/google/ads/googleads/v24/services/services/reservation_service/async_client.py new file mode 100644 index 000000000..6eecd82ac --- /dev/null +++ b/google/ads/googleads/v24/services/services/reservation_service/async_client.py @@ -0,0 +1,489 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import reservation_service +from .transports.base import ReservationServiceTransport, DEFAULT_CLIENT_INFO +from .client import ReservationServiceClient + +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 ReservationServiceAsyncClient: + """Service for reservation related operations. + This service is not publicly available. + """ + + _client: ReservationServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ReservationServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ReservationServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + ReservationServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ReservationServiceClient._DEFAULT_UNIVERSE + + common_billing_account_path = staticmethod( + ReservationServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ReservationServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ReservationServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ReservationServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ReservationServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ReservationServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ReservationServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ReservationServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ReservationServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ReservationServiceClient.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: + ReservationServiceAsyncClient: The constructed client. + """ + return ReservationServiceClient.from_service_account_info.__func__(ReservationServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ReservationServiceAsyncClient: The constructed client. + """ + return ReservationServiceClient.from_service_account_file.__func__(ReservationServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ReservationServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ReservationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ReservationServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ReservationServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ReservationServiceTransport, + Callable[..., ReservationServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the reservation 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,ReservationServiceTransport,Callable[..., ReservationServiceTransport]]]): + 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 ReservationServiceTransport 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 = ReservationServiceClient( + 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.ads.googleads.v24.services.ReservationServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ReservationService", + "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.ads.googleads.v24.services.ReservationService", + "credentialsType": None, + } + ), + ) + + async def quote_campaigns( + self, + request: Optional[ + Union[reservation_service.QuoteCampaignsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reservation_service.QuoteCampaignsResponse: + r"""Proposes quotes for booking campaigns. + This request can have a latency of 30 seconds. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.QuoteCampaignsRequest, dict]]): + The request object. Request message for + [ReservationService.QuoteCampaigns][google.ads.googleads.v24.services.ReservationService.QuoteCampaigns]. + customer_id (:class:`str`): + Required. The ID of the customer + making the request. + + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.QuoteCampaignsResponse: + Response message for + [ReservationService.QuoteCampaigns][google.ads.googleads.v24.services.ReservationService.QuoteCampaigns]. + + """ + # 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 = [customer_id] + 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, reservation_service.QuoteCampaignsRequest): + request = reservation_service.QuoteCampaignsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.quote_campaigns + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 book_campaigns( + self, + request: Optional[ + Union[reservation_service.BookCampaignsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reservation_service.BookCampaignsResponse: + r"""Books the requested campaigns. + This request can have a latency of 30 seconds. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.BookCampaignsRequest, dict]]): + The request object. Request message for + [ReservationService.BookCampaigns][google.ads.googleads.v24.services.ReservationService.BookCampaigns]. + customer_id (:class:`str`): + Required. The ID of the customer + making the request. + + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.BookCampaignsResponse: + Response message for + [ReservationService.BookCampaigns][google.ads.googleads.v24.services.ReservationService.BookCampaigns]. + + """ + # 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 = [customer_id] + 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, reservation_service.BookCampaignsRequest): + request = reservation_service.BookCampaignsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.book_campaigns + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ReservationServiceAsyncClient": + 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__ = ("ReservationServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/reservation_service/client.py b/google/ads/googleads/v24/services/services/reservation_service/client.py new file mode 100644 index 000000000..88f48c4d6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/reservation_service/client.py @@ -0,0 +1,924 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import reservation_service +from .transports.base import ReservationServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import ReservationServiceGrpcTransport +from .transports.grpc_asyncio import ReservationServiceGrpcAsyncIOTransport + + +class ReservationServiceClientMeta(type): + """Metaclass for the ReservationService 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[ReservationServiceTransport]] + _transport_registry["grpc"] = ReservationServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ReservationServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ReservationServiceTransport]: + """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 ReservationServiceClient(metaclass=ReservationServiceClientMeta): + """Service for reservation related operations. + This service is not publicly available. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ReservationServiceClient: 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: + ReservationServiceClient: 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) -> ReservationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ReservationServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @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 = ReservationServiceClient._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 = ReservationServiceClient._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 + ): + """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 = ReservationServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ReservationServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + ReservationServiceClient._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 = ReservationServiceClient._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): + """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, + ReservationServiceTransport, + Callable[..., ReservationServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the reservation 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,ReservationServiceTransport,Callable[..., ReservationServiceTransport]]]): + 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 ReservationServiceTransport 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, + ) = ReservationServiceClient._read_environment_variables() + self._client_cert_source = ( + ReservationServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ReservationServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ReservationServiceTransport) + if transport_provided: + # transport is a ReservationServiceTransport 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(ReservationServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ReservationServiceClient._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[ReservationServiceTransport], + Callable[..., ReservationServiceTransport], + ] = ( + ReservationServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., ReservationServiceTransport], 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.ads.googleads.v24.services.ReservationServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ReservationService", + "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.ads.googleads.v24.services.ReservationService", + "credentialsType": None, + } + ), + ) + + def quote_campaigns( + self, + request: Optional[ + Union[reservation_service.QuoteCampaignsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reservation_service.QuoteCampaignsResponse: + r"""Proposes quotes for booking campaigns. + This request can have a latency of 30 seconds. + + Args: + request (Union[google.ads.googleads.v24.services.types.QuoteCampaignsRequest, dict]): + The request object. Request message for + [ReservationService.QuoteCampaigns][google.ads.googleads.v24.services.ReservationService.QuoteCampaigns]. + customer_id (str): + Required. The ID of the customer + making the request. + + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.QuoteCampaignsResponse: + Response message for + [ReservationService.QuoteCampaigns][google.ads.googleads.v24.services.ReservationService.QuoteCampaigns]. + + """ + # 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 = [customer_id] + 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, reservation_service.QuoteCampaignsRequest): + request = reservation_service.QuoteCampaignsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.quote_campaigns] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 book_campaigns( + self, + request: Optional[ + Union[reservation_service.BookCampaignsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reservation_service.BookCampaignsResponse: + r"""Books the requested campaigns. + This request can have a latency of 30 seconds. + + Args: + request (Union[google.ads.googleads.v24.services.types.BookCampaignsRequest, dict]): + The request object. Request message for + [ReservationService.BookCampaigns][google.ads.googleads.v24.services.ReservationService.BookCampaigns]. + customer_id (str): + Required. The ID of the customer + making the request. + + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.BookCampaignsResponse: + Response message for + [ReservationService.BookCampaigns][google.ads.googleads.v24.services.ReservationService.BookCampaigns]. + + """ + # 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 = [customer_id] + 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, reservation_service.BookCampaignsRequest): + request = reservation_service.BookCampaignsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.book_campaigns] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "ReservationServiceClient": + 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() + + +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__ = ("ReservationServiceClient",) diff --git a/google/ads/googleads/v24/services/services/reservation_service/transports/README.rst b/google/ads/googleads/v24/services/services/reservation_service/transports/README.rst new file mode 100644 index 000000000..b69ca178e --- /dev/null +++ b/google/ads/googleads/v24/services/services/reservation_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ReservationServiceTransport` is the ABC for all transports. +- public child `ReservationServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ReservationServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseReservationServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ReservationServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/reservation_service/transports/__init__.py b/google/ads/googleads/v24/services/services/reservation_service/transports/__init__.py new file mode 100644 index 000000000..11395b903 --- /dev/null +++ b/google/ads/googleads/v24/services/services/reservation_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ReservationServiceTransport +from .grpc import ReservationServiceGrpcTransport +from .grpc_asyncio import ReservationServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ReservationServiceTransport]] +_transport_registry["grpc"] = ReservationServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ReservationServiceGrpcAsyncIOTransport + +__all__ = ( + "ReservationServiceTransport", + "ReservationServiceGrpcTransport", + "ReservationServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/reservation_service/transports/base.py b/google/ads/googleads/v24/services/services/reservation_service/transports/base.py new file mode 100644 index 000000000..a99f6884b --- /dev/null +++ b/google/ads/googleads/v24/services/services/reservation_service/transports/base.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import reservation_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 ReservationServiceTransport(abc.ABC): + """Abstract transport class for ReservationService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.quote_campaigns: gapic_v1.method.wrap_method( + self.quote_campaigns, + default_timeout=None, + client_info=client_info, + ), + self.book_campaigns: gapic_v1.method.wrap_method( + self.book_campaigns, + 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 quote_campaigns( + self, + ) -> Callable[ + [reservation_service.QuoteCampaignsRequest], + Union[ + reservation_service.QuoteCampaignsResponse, + Awaitable[reservation_service.QuoteCampaignsResponse], + ], + ]: + raise NotImplementedError() + + @property + def book_campaigns( + self, + ) -> Callable[ + [reservation_service.BookCampaignsRequest], + Union[ + reservation_service.BookCampaignsResponse, + Awaitable[reservation_service.BookCampaignsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ReservationServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/reservation_service/transports/grpc.py b/google/ads/googleads/v24/services/services/reservation_service/transports/grpc.py new file mode 100644 index 000000000..121be789b --- /dev/null +++ b/google/ads/googleads/v24/services/services/reservation_service/transports/grpc.py @@ -0,0 +1,413 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import reservation_service +from .base import ReservationServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ReservationService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ReservationService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ReservationServiceGrpcTransport(ReservationServiceTransport): + """gRPC backend transport for ReservationService. + + Service for reservation related operations. + This service is not publicly available. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 quote_campaigns( + self, + ) -> Callable[ + [reservation_service.QuoteCampaignsRequest], + reservation_service.QuoteCampaignsResponse, + ]: + r"""Return a callable for the quote campaigns method over gRPC. + + Proposes quotes for booking campaigns. + This request can have a latency of 30 seconds. + + Returns: + Callable[[~.QuoteCampaignsRequest], + ~.QuoteCampaignsResponse]: + 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 "quote_campaigns" not in self._stubs: + self._stubs["quote_campaigns"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReservationService/QuoteCampaigns", + request_serializer=reservation_service.QuoteCampaignsRequest.serialize, + response_deserializer=reservation_service.QuoteCampaignsResponse.deserialize, + ) + return self._stubs["quote_campaigns"] + + @property + def book_campaigns( + self, + ) -> Callable[ + [reservation_service.BookCampaignsRequest], + reservation_service.BookCampaignsResponse, + ]: + r"""Return a callable for the book campaigns method over gRPC. + + Books the requested campaigns. + This request can have a latency of 30 seconds. + + Returns: + Callable[[~.BookCampaignsRequest], + ~.BookCampaignsResponse]: + 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 "book_campaigns" not in self._stubs: + self._stubs["book_campaigns"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReservationService/BookCampaigns", + request_serializer=reservation_service.BookCampaignsRequest.serialize, + response_deserializer=reservation_service.BookCampaignsResponse.deserialize, + ) + return self._stubs["book_campaigns"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ReservationServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/reservation_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/reservation_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..a5e6b3e8d --- /dev/null +++ b/google/ads/googleads/v24/services/services/reservation_service/transports/grpc_asyncio.py @@ -0,0 +1,439 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import reservation_service +from .base import ReservationServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ReservationService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ReservationService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ReservationServiceGrpcAsyncIOTransport(ReservationServiceTransport): + """gRPC AsyncIO backend transport for ReservationService. + + Service for reservation related operations. + This service is not publicly available. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 quote_campaigns( + self, + ) -> Callable[ + [reservation_service.QuoteCampaignsRequest], + Awaitable[reservation_service.QuoteCampaignsResponse], + ]: + r"""Return a callable for the quote campaigns method over gRPC. + + Proposes quotes for booking campaigns. + This request can have a latency of 30 seconds. + + Returns: + Callable[[~.QuoteCampaignsRequest], + Awaitable[~.QuoteCampaignsResponse]]: + 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 "quote_campaigns" not in self._stubs: + self._stubs["quote_campaigns"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReservationService/QuoteCampaigns", + request_serializer=reservation_service.QuoteCampaignsRequest.serialize, + response_deserializer=reservation_service.QuoteCampaignsResponse.deserialize, + ) + return self._stubs["quote_campaigns"] + + @property + def book_campaigns( + self, + ) -> Callable[ + [reservation_service.BookCampaignsRequest], + Awaitable[reservation_service.BookCampaignsResponse], + ]: + r"""Return a callable for the book campaigns method over gRPC. + + Books the requested campaigns. + This request can have a latency of 30 seconds. + + Returns: + Callable[[~.BookCampaignsRequest], + Awaitable[~.BookCampaignsResponse]]: + 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 "book_campaigns" not in self._stubs: + self._stubs["book_campaigns"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ReservationService/BookCampaigns", + request_serializer=reservation_service.BookCampaignsRequest.serialize, + response_deserializer=reservation_service.BookCampaignsResponse.deserialize, + ) + return self._stubs["book_campaigns"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.quote_campaigns: self._wrap_method( + self.quote_campaigns, + default_timeout=None, + client_info=client_info, + ), + self.book_campaigns: self._wrap_method( + self.book_campaigns, + 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" + + +__all__ = ("ReservationServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/shareable_preview_service/__init__.py b/google/ads/googleads/v24/services/services/shareable_preview_service/__init__.py new file mode 100644 index 000000000..32d2569df --- /dev/null +++ b/google/ads/googleads/v24/services/services/shareable_preview_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ShareablePreviewServiceClient +from .async_client import ShareablePreviewServiceAsyncClient + +__all__ = ( + "ShareablePreviewServiceClient", + "ShareablePreviewServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/shareable_preview_service/async_client.py b/google/ads/googleads/v24/services/services/shareable_preview_service/async_client.py new file mode 100644 index 000000000..025763113 --- /dev/null +++ b/google/ads/googleads/v24/services/services/shareable_preview_service/async_client.py @@ -0,0 +1,407 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import shareable_preview_service +from .transports.base import ( + ShareablePreviewServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import ShareablePreviewServiceClient + +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 ShareablePreviewServiceAsyncClient: + """Service to generate Shareable Previews.""" + + _client: ShareablePreviewServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ShareablePreviewServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ShareablePreviewServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + ShareablePreviewServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ShareablePreviewServiceClient._DEFAULT_UNIVERSE + + common_billing_account_path = staticmethod( + ShareablePreviewServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ShareablePreviewServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ShareablePreviewServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ShareablePreviewServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ShareablePreviewServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ShareablePreviewServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ShareablePreviewServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ShareablePreviewServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ShareablePreviewServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ShareablePreviewServiceClient.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: + ShareablePreviewServiceAsyncClient: The constructed client. + """ + return ShareablePreviewServiceClient.from_service_account_info.__func__(ShareablePreviewServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ShareablePreviewServiceAsyncClient: The constructed client. + """ + return ShareablePreviewServiceClient.from_service_account_file.__func__(ShareablePreviewServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ShareablePreviewServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ShareablePreviewServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ShareablePreviewServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ShareablePreviewServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ShareablePreviewServiceTransport, + Callable[..., ShareablePreviewServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the shareable preview 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,ShareablePreviewServiceTransport,Callable[..., ShareablePreviewServiceTransport]]]): + 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 ShareablePreviewServiceTransport 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 = ShareablePreviewServiceClient( + 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.ads.googleads.v24.services.ShareablePreviewServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ShareablePreviewService", + "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.ads.googleads.v24.services.ShareablePreviewService", + "credentialsType": None, + } + ), + ) + + async def generate_shareable_previews( + self, + request: Optional[ + Union[ + shareable_preview_service.GenerateShareablePreviewsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> shareable_preview_service.GenerateShareablePreviewsResponse: + r"""Returns the requested Shareable Preview. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GenerateShareablePreviewsRequest, dict]]): + The request object. Request message for + [ShareablePreviewService.GenerateShareablePreviews][google.ads.googleads.v24.services.ShareablePreviewService.GenerateShareablePreviews]. + customer_id (:class:`str`): + Required. The customer creating the + shareable previews request. + + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.GenerateShareablePreviewsResponse: + Response message for + [ShareablePreviewService.GenerateShareablePreviews][google.ads.googleads.v24.services.ShareablePreviewService.GenerateShareablePreviews]. + + """ + # 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 = [customer_id] + 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, shareable_preview_service.GenerateShareablePreviewsRequest + ): + request = ( + shareable_preview_service.GenerateShareablePreviewsRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.generate_shareable_previews + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ShareablePreviewServiceAsyncClient": + 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__ = ("ShareablePreviewServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/shareable_preview_service/client.py b/google/ads/googleads/v24/services/services/shareable_preview_service/client.py new file mode 100644 index 000000000..f4288ae36 --- /dev/null +++ b/google/ads/googleads/v24/services/services/shareable_preview_service/client.py @@ -0,0 +1,861 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import shareable_preview_service +from .transports.base import ( + ShareablePreviewServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ShareablePreviewServiceGrpcTransport +from .transports.grpc_asyncio import ShareablePreviewServiceGrpcAsyncIOTransport + + +class ShareablePreviewServiceClientMeta(type): + """Metaclass for the ShareablePreviewService 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[ShareablePreviewServiceTransport]] + _transport_registry["grpc"] = ShareablePreviewServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + ShareablePreviewServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ShareablePreviewServiceTransport]: + """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 ShareablePreviewServiceClient( + metaclass=ShareablePreviewServiceClientMeta +): + """Service to generate Shareable Previews.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ShareablePreviewServiceClient: 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: + ShareablePreviewServiceClient: 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) -> ShareablePreviewServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ShareablePreviewServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @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 = ( + ShareablePreviewServiceClient._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 = ( + ShareablePreviewServiceClient._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 + ): + """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 = ShareablePreviewServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ShareablePreviewServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + ShareablePreviewServiceClient._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 = ShareablePreviewServiceClient._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): + """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, + ShareablePreviewServiceTransport, + Callable[..., ShareablePreviewServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the shareable preview 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,ShareablePreviewServiceTransport,Callable[..., ShareablePreviewServiceTransport]]]): + 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 ShareablePreviewServiceTransport 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, + ) = ShareablePreviewServiceClient._read_environment_variables() + self._client_cert_source = ( + ShareablePreviewServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + ShareablePreviewServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ShareablePreviewServiceTransport + ) + if transport_provided: + # transport is a ShareablePreviewServiceTransport 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(ShareablePreviewServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ShareablePreviewServiceClient._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[ShareablePreviewServiceTransport], + Callable[..., ShareablePreviewServiceTransport], + ] = ( + ShareablePreviewServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., ShareablePreviewServiceTransport], 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.ads.googleads.v24.services.ShareablePreviewServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ShareablePreviewService", + "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.ads.googleads.v24.services.ShareablePreviewService", + "credentialsType": None, + } + ), + ) + + def generate_shareable_previews( + self, + request: Optional[ + Union[ + shareable_preview_service.GenerateShareablePreviewsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> shareable_preview_service.GenerateShareablePreviewsResponse: + r"""Returns the requested Shareable Preview. + + Args: + request (Union[google.ads.googleads.v24.services.types.GenerateShareablePreviewsRequest, dict]): + The request object. Request message for + [ShareablePreviewService.GenerateShareablePreviews][google.ads.googleads.v24.services.ShareablePreviewService.GenerateShareablePreviews]. + customer_id (str): + Required. The customer creating the + shareable previews request. + + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.GenerateShareablePreviewsResponse: + Response message for + [ShareablePreviewService.GenerateShareablePreviews][google.ads.googleads.v24.services.ShareablePreviewService.GenerateShareablePreviews]. + + """ + # 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 = [customer_id] + 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, shareable_preview_service.GenerateShareablePreviewsRequest + ): + request = ( + shareable_preview_service.GenerateShareablePreviewsRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_shareable_previews + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "ShareablePreviewServiceClient": + 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() + + +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__ = ("ShareablePreviewServiceClient",) diff --git a/google/ads/googleads/v24/services/services/shareable_preview_service/transports/README.rst b/google/ads/googleads/v24/services/services/shareable_preview_service/transports/README.rst new file mode 100644 index 000000000..b41dc6a02 --- /dev/null +++ b/google/ads/googleads/v24/services/services/shareable_preview_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ShareablePreviewServiceTransport` is the ABC for all transports. +- public child `ShareablePreviewServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ShareablePreviewServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseShareablePreviewServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ShareablePreviewServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/shareable_preview_service/transports/__init__.py b/google/ads/googleads/v24/services/services/shareable_preview_service/transports/__init__.py new file mode 100644 index 000000000..9b99734b7 --- /dev/null +++ b/google/ads/googleads/v24/services/services/shareable_preview_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ShareablePreviewServiceTransport +from .grpc import ShareablePreviewServiceGrpcTransport +from .grpc_asyncio import ShareablePreviewServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ShareablePreviewServiceTransport]] +_transport_registry["grpc"] = ShareablePreviewServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + ShareablePreviewServiceGrpcAsyncIOTransport +) + +__all__ = ( + "ShareablePreviewServiceTransport", + "ShareablePreviewServiceGrpcTransport", + "ShareablePreviewServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/shareable_preview_service/transports/base.py b/google/ads/googleads/v24/services/services/shareable_preview_service/transports/base.py new file mode 100644 index 000000000..2292ec3f0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/shareable_preview_service/transports/base.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import shareable_preview_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 ShareablePreviewServiceTransport(abc.ABC): + """Abstract transport class for ShareablePreviewService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.generate_shareable_previews: gapic_v1.method.wrap_method( + self.generate_shareable_previews, + 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 generate_shareable_previews( + self, + ) -> Callable[ + [shareable_preview_service.GenerateShareablePreviewsRequest], + Union[ + shareable_preview_service.GenerateShareablePreviewsResponse, + Awaitable[ + shareable_preview_service.GenerateShareablePreviewsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ShareablePreviewServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/shareable_preview_service/transports/grpc.py b/google/ads/googleads/v24/services/services/shareable_preview_service/transports/grpc.py new file mode 100644 index 000000000..eb91196a3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/shareable_preview_service/transports/grpc.py @@ -0,0 +1,383 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import shareable_preview_service +from .base import ShareablePreviewServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ShareablePreviewService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ShareablePreviewService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ShareablePreviewServiceGrpcTransport(ShareablePreviewServiceTransport): + """gRPC backend transport for ShareablePreviewService. + + Service to generate Shareable Previews. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 generate_shareable_previews( + self, + ) -> Callable[ + [shareable_preview_service.GenerateShareablePreviewsRequest], + shareable_preview_service.GenerateShareablePreviewsResponse, + ]: + r"""Return a callable for the generate shareable previews method over gRPC. + + Returns the requested Shareable Preview. + + Returns: + Callable[[~.GenerateShareablePreviewsRequest], + ~.GenerateShareablePreviewsResponse]: + 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 "generate_shareable_previews" not in self._stubs: + self._stubs["generate_shareable_previews"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ShareablePreviewService/GenerateShareablePreviews", + request_serializer=shareable_preview_service.GenerateShareablePreviewsRequest.serialize, + response_deserializer=shareable_preview_service.GenerateShareablePreviewsResponse.deserialize, + ) + ) + return self._stubs["generate_shareable_previews"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ShareablePreviewServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/shareable_preview_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/shareable_preview_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..e2f02ef10 --- /dev/null +++ b/google/ads/googleads/v24/services/services/shareable_preview_service/transports/grpc_asyncio.py @@ -0,0 +1,406 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import shareable_preview_service +from .base import ShareablePreviewServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.ShareablePreviewService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ShareablePreviewService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ShareablePreviewServiceGrpcAsyncIOTransport( + ShareablePreviewServiceTransport +): + """gRPC AsyncIO backend transport for ShareablePreviewService. + + Service to generate Shareable Previews. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 generate_shareable_previews( + self, + ) -> Callable[ + [shareable_preview_service.GenerateShareablePreviewsRequest], + Awaitable[shareable_preview_service.GenerateShareablePreviewsResponse], + ]: + r"""Return a callable for the generate shareable previews method over gRPC. + + Returns the requested Shareable Preview. + + Returns: + Callable[[~.GenerateShareablePreviewsRequest], + Awaitable[~.GenerateShareablePreviewsResponse]]: + 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 "generate_shareable_previews" not in self._stubs: + self._stubs["generate_shareable_previews"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ShareablePreviewService/GenerateShareablePreviews", + request_serializer=shareable_preview_service.GenerateShareablePreviewsRequest.serialize, + response_deserializer=shareable_preview_service.GenerateShareablePreviewsResponse.deserialize, + ) + ) + return self._stubs["generate_shareable_previews"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.generate_shareable_previews: self._wrap_method( + self.generate_shareable_previews, + 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" + + +__all__ = ("ShareablePreviewServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/shared_criterion_service/__init__.py b/google/ads/googleads/v24/services/services/shared_criterion_service/__init__.py new file mode 100644 index 000000000..4b964f6d0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_criterion_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import SharedCriterionServiceClient +from .async_client import SharedCriterionServiceAsyncClient + +__all__ = ( + "SharedCriterionServiceClient", + "SharedCriterionServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/shared_criterion_service/async_client.py b/google/ads/googleads/v24/services/services/shared_criterion_service/async_client.py new file mode 100644 index 000000000..75023dd1b --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_criterion_service/async_client.py @@ -0,0 +1,444 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import shared_criterion_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + SharedCriterionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import SharedCriterionServiceClient + +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 SharedCriterionServiceAsyncClient: + """Service to manage shared criteria.""" + + _client: SharedCriterionServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = SharedCriterionServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = SharedCriterionServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + SharedCriterionServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = SharedCriterionServiceClient._DEFAULT_UNIVERSE + + mobile_app_category_constant_path = staticmethod( + SharedCriterionServiceClient.mobile_app_category_constant_path + ) + parse_mobile_app_category_constant_path = staticmethod( + SharedCriterionServiceClient.parse_mobile_app_category_constant_path + ) + shared_criterion_path = staticmethod( + SharedCriterionServiceClient.shared_criterion_path + ) + parse_shared_criterion_path = staticmethod( + SharedCriterionServiceClient.parse_shared_criterion_path + ) + shared_set_path = staticmethod(SharedCriterionServiceClient.shared_set_path) + parse_shared_set_path = staticmethod( + SharedCriterionServiceClient.parse_shared_set_path + ) + common_billing_account_path = staticmethod( + SharedCriterionServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + SharedCriterionServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + SharedCriterionServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + SharedCriterionServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + SharedCriterionServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + SharedCriterionServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + SharedCriterionServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + SharedCriterionServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + SharedCriterionServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + SharedCriterionServiceClient.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: + SharedCriterionServiceAsyncClient: The constructed client. + """ + return SharedCriterionServiceClient.from_service_account_info.__func__(SharedCriterionServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + SharedCriterionServiceAsyncClient: The constructed client. + """ + return SharedCriterionServiceClient.from_service_account_file.__func__(SharedCriterionServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return SharedCriterionServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> SharedCriterionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + SharedCriterionServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = SharedCriterionServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + SharedCriterionServiceTransport, + Callable[..., SharedCriterionServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the shared criterion 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,SharedCriterionServiceTransport,Callable[..., SharedCriterionServiceTransport]]]): + 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 SharedCriterionServiceTransport 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 = SharedCriterionServiceClient( + 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.ads.googleads.v24.services.SharedCriterionServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.SharedCriterionService", + "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.ads.googleads.v24.services.SharedCriterionService", + "credentialsType": None, + } + ), + ) + + async def mutate_shared_criteria( + self, + request: Optional[ + Union[shared_criterion_service.MutateSharedCriteriaRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[shared_criterion_service.SharedCriterionOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> shared_criterion_service.MutateSharedCriteriaResponse: + r"""Creates or removes shared criteria. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CriterionError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ `FieldError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NotEmptyError <>`__ `NullError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateSharedCriteriaRequest, dict]]): + The request object. Request message for + [SharedCriterionService.MutateSharedCriteria][google.ads.googleads.v24.services.SharedCriterionService.MutateSharedCriteria]. + customer_id (:class:`str`): + Required. The ID of the customer + whose shared criteria are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.SharedCriterionOperation]`): + Required. The list of operations to + perform on individual shared criteria. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateSharedCriteriaResponse: + Response message for a shared + criterion mutate. + + """ + # 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 = [customer_id, operations] + 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, shared_criterion_service.MutateSharedCriteriaRequest + ): + request = shared_criterion_service.MutateSharedCriteriaRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_shared_criteria + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "SharedCriterionServiceAsyncClient": + 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__ = ("SharedCriterionServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/shared_criterion_service/client.py b/google/ads/googleads/v24/services/services/shared_criterion_service/client.py new file mode 100644 index 000000000..85a4659b1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_criterion_service/client.py @@ -0,0 +1,950 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import shared_criterion_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + SharedCriterionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import SharedCriterionServiceGrpcTransport +from .transports.grpc_asyncio import SharedCriterionServiceGrpcAsyncIOTransport + + +class SharedCriterionServiceClientMeta(type): + """Metaclass for the SharedCriterionService 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[SharedCriterionServiceTransport]] + _transport_registry["grpc"] = SharedCriterionServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + SharedCriterionServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[SharedCriterionServiceTransport]: + """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 SharedCriterionServiceClient(metaclass=SharedCriterionServiceClientMeta): + """Service to manage shared criteria.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + SharedCriterionServiceClient: 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: + SharedCriterionServiceClient: 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) -> SharedCriterionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + SharedCriterionServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def mobile_app_category_constant_path( + mobile_app_category_id: str, + ) -> str: + """Returns a fully-qualified mobile_app_category_constant string.""" + return "mobileAppCategoryConstants/{mobile_app_category_id}".format( + mobile_app_category_id=mobile_app_category_id, + ) + + @staticmethod + def parse_mobile_app_category_constant_path(path: str) -> Dict[str, str]: + """Parses a mobile_app_category_constant path into its component segments.""" + m = re.match( + r"^mobileAppCategoryConstants/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def shared_criterion_path( + customer_id: str, + shared_set_id: str, + criterion_id: str, + ) -> str: + """Returns a fully-qualified shared_criterion string.""" + return "customers/{customer_id}/sharedCriteria/{shared_set_id}~{criterion_id}".format( + customer_id=customer_id, + shared_set_id=shared_set_id, + criterion_id=criterion_id, + ) + + @staticmethod + def parse_shared_criterion_path(path: str) -> Dict[str, str]: + """Parses a shared_criterion path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/sharedCriteria/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def shared_set_path( + customer_id: str, + shared_set_id: str, + ) -> str: + """Returns a fully-qualified shared_set string.""" + return "customers/{customer_id}/sharedSets/{shared_set_id}".format( + customer_id=customer_id, + shared_set_id=shared_set_id, + ) + + @staticmethod + def parse_shared_set_path(path: str) -> Dict[str, str]: + """Parses a shared_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/sharedSets/(?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 = ( + SharedCriterionServiceClient._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 = ( + SharedCriterionServiceClient._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 + ): + """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 = SharedCriterionServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = SharedCriterionServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + SharedCriterionServiceClient._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 = SharedCriterionServiceClient._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): + """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, + SharedCriterionServiceTransport, + Callable[..., SharedCriterionServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the shared criterion 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,SharedCriterionServiceTransport,Callable[..., SharedCriterionServiceTransport]]]): + 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 SharedCriterionServiceTransport 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, + ) = SharedCriterionServiceClient._read_environment_variables() + self._client_cert_source = ( + SharedCriterionServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + SharedCriterionServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, SharedCriterionServiceTransport + ) + if transport_provided: + # transport is a SharedCriterionServiceTransport 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(SharedCriterionServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or SharedCriterionServiceClient._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[SharedCriterionServiceTransport], + Callable[..., SharedCriterionServiceTransport], + ] = ( + SharedCriterionServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., SharedCriterionServiceTransport], 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.ads.googleads.v24.services.SharedCriterionServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.SharedCriterionService", + "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.ads.googleads.v24.services.SharedCriterionService", + "credentialsType": None, + } + ), + ) + + def mutate_shared_criteria( + self, + request: Optional[ + Union[shared_criterion_service.MutateSharedCriteriaRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[shared_criterion_service.SharedCriterionOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> shared_criterion_service.MutateSharedCriteriaResponse: + r"""Creates or removes shared criteria. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CriterionError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ `FieldError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NotEmptyError <>`__ `NullError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateSharedCriteriaRequest, dict]): + The request object. Request message for + [SharedCriterionService.MutateSharedCriteria][google.ads.googleads.v24.services.SharedCriterionService.MutateSharedCriteria]. + customer_id (str): + Required. The ID of the customer + whose shared criteria are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.SharedCriterionOperation]): + Required. The list of operations to + perform on individual shared criteria. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateSharedCriteriaResponse: + Response message for a shared + criterion mutate. + + """ + # 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 = [customer_id, operations] + 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, shared_criterion_service.MutateSharedCriteriaRequest + ): + request = shared_criterion_service.MutateSharedCriteriaRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_shared_criteria + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "SharedCriterionServiceClient": + 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() + + +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__ = ("SharedCriterionServiceClient",) diff --git a/google/ads/googleads/v24/services/services/shared_criterion_service/transports/README.rst b/google/ads/googleads/v24/services/services/shared_criterion_service/transports/README.rst new file mode 100644 index 000000000..9eb150bf2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_criterion_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`SharedCriterionServiceTransport` is the ABC for all transports. +- public child `SharedCriterionServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `SharedCriterionServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseSharedCriterionServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `SharedCriterionServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/shared_criterion_service/transports/__init__.py b/google/ads/googleads/v24/services/services/shared_criterion_service/transports/__init__.py new file mode 100644 index 000000000..cf688100b --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_criterion_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import SharedCriterionServiceTransport +from .grpc import SharedCriterionServiceGrpcTransport +from .grpc_asyncio import SharedCriterionServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[SharedCriterionServiceTransport]] +_transport_registry["grpc"] = SharedCriterionServiceGrpcTransport +_transport_registry["grpc_asyncio"] = SharedCriterionServiceGrpcAsyncIOTransport + +__all__ = ( + "SharedCriterionServiceTransport", + "SharedCriterionServiceGrpcTransport", + "SharedCriterionServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/shared_criterion_service/transports/base.py b/google/ads/googleads/v24/services/services/shared_criterion_service/transports/base.py new file mode 100644 index 000000000..8d78a90bc --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_criterion_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import shared_criterion_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 SharedCriterionServiceTransport(abc.ABC): + """Abstract transport class for SharedCriterionService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_shared_criteria: gapic_v1.method.wrap_method( + self.mutate_shared_criteria, + 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 mutate_shared_criteria( + self, + ) -> Callable[ + [shared_criterion_service.MutateSharedCriteriaRequest], + Union[ + shared_criterion_service.MutateSharedCriteriaResponse, + Awaitable[shared_criterion_service.MutateSharedCriteriaResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("SharedCriterionServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/shared_criterion_service/transports/grpc.py b/google/ads/googleads/v24/services/services/shared_criterion_service/transports/grpc.py new file mode 100644 index 000000000..9ac6bc1aa --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_criterion_service/transports/grpc.py @@ -0,0 +1,394 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import shared_criterion_service +from .base import SharedCriterionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.SharedCriterionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.SharedCriterionService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class SharedCriterionServiceGrpcTransport(SharedCriterionServiceTransport): + """gRPC backend transport for SharedCriterionService. + + Service to manage shared criteria. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_shared_criteria( + self, + ) -> Callable[ + [shared_criterion_service.MutateSharedCriteriaRequest], + shared_criterion_service.MutateSharedCriteriaResponse, + ]: + r"""Return a callable for the mutate shared criteria method over gRPC. + + Creates or removes shared criteria. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CriterionError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ `FieldError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NotEmptyError <>`__ `NullError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Returns: + Callable[[~.MutateSharedCriteriaRequest], + ~.MutateSharedCriteriaResponse]: + 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 "mutate_shared_criteria" not in self._stubs: + self._stubs["mutate_shared_criteria"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.SharedCriterionService/MutateSharedCriteria", + request_serializer=shared_criterion_service.MutateSharedCriteriaRequest.serialize, + response_deserializer=shared_criterion_service.MutateSharedCriteriaResponse.deserialize, + ) + ) + return self._stubs["mutate_shared_criteria"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("SharedCriterionServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/shared_criterion_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/shared_criterion_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..dc92a291b --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_criterion_service/transports/grpc_asyncio.py @@ -0,0 +1,417 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import shared_criterion_service +from .base import SharedCriterionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.SharedCriterionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.SharedCriterionService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class SharedCriterionServiceGrpcAsyncIOTransport( + SharedCriterionServiceTransport +): + """gRPC AsyncIO backend transport for SharedCriterionService. + + Service to manage shared criteria. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_shared_criteria( + self, + ) -> Callable[ + [shared_criterion_service.MutateSharedCriteriaRequest], + Awaitable[shared_criterion_service.MutateSharedCriteriaResponse], + ]: + r"""Return a callable for the mutate shared criteria method over gRPC. + + Creates or removes shared criteria. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CriterionError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ `FieldError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NotEmptyError <>`__ `NullError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `ResourceCountLimitExceededError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Returns: + Callable[[~.MutateSharedCriteriaRequest], + Awaitable[~.MutateSharedCriteriaResponse]]: + 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 "mutate_shared_criteria" not in self._stubs: + self._stubs["mutate_shared_criteria"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.SharedCriterionService/MutateSharedCriteria", + request_serializer=shared_criterion_service.MutateSharedCriteriaRequest.serialize, + response_deserializer=shared_criterion_service.MutateSharedCriteriaResponse.deserialize, + ) + ) + return self._stubs["mutate_shared_criteria"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_shared_criteria: self._wrap_method( + self.mutate_shared_criteria, + 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" + + +__all__ = ("SharedCriterionServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/shared_set_service/__init__.py b/google/ads/googleads/v24/services/services/shared_set_service/__init__.py new file mode 100644 index 000000000..4c4c9f2af --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_set_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import SharedSetServiceClient +from .async_client import SharedSetServiceAsyncClient + +__all__ = ( + "SharedSetServiceClient", + "SharedSetServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/shared_set_service/async_client.py b/google/ads/googleads/v24/services/services/shared_set_service/async_client.py new file mode 100644 index 000000000..2f79db2ec --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_set_service/async_client.py @@ -0,0 +1,423 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import shared_set_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import SharedSetServiceTransport, DEFAULT_CLIENT_INFO +from .client import SharedSetServiceClient + +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 SharedSetServiceAsyncClient: + """Service to manage shared sets.""" + + _client: SharedSetServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = SharedSetServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = SharedSetServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + SharedSetServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = SharedSetServiceClient._DEFAULT_UNIVERSE + + shared_set_path = staticmethod(SharedSetServiceClient.shared_set_path) + parse_shared_set_path = staticmethod( + SharedSetServiceClient.parse_shared_set_path + ) + common_billing_account_path = staticmethod( + SharedSetServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + SharedSetServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(SharedSetServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + SharedSetServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + SharedSetServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + SharedSetServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + SharedSetServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + SharedSetServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + SharedSetServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + SharedSetServiceClient.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: + SharedSetServiceAsyncClient: The constructed client. + """ + return SharedSetServiceClient.from_service_account_info.__func__(SharedSetServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + SharedSetServiceAsyncClient: The constructed client. + """ + return SharedSetServiceClient.from_service_account_file.__func__(SharedSetServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return SharedSetServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> SharedSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + SharedSetServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = SharedSetServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + SharedSetServiceTransport, + Callable[..., SharedSetServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the shared set 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,SharedSetServiceTransport,Callable[..., SharedSetServiceTransport]]]): + 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 SharedSetServiceTransport 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 = SharedSetServiceClient( + 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.ads.googleads.v24.services.SharedSetServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.SharedSetService", + "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.ads.googleads.v24.services.SharedSetService", + "credentialsType": None, + } + ), + ) + + async def mutate_shared_sets( + self, + request: Optional[ + Union[shared_set_service.MutateSharedSetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[shared_set_service.SharedSetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> shared_set_service.MutateSharedSetsResponse: + r"""Creates, updates, or removes shared sets. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SharedSetError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateSharedSetsRequest, dict]]): + The request object. Request message for + [SharedSetService.MutateSharedSets][google.ads.googleads.v24.services.SharedSetService.MutateSharedSets]. + customer_id (:class:`str`): + Required. The ID of the customer + whose shared sets are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.SharedSetOperation]`): + Required. The list of operations to + perform on individual shared sets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateSharedSetsResponse: + Response message for a shared set + mutate. + + """ + # 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 = [customer_id, operations] + 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, shared_set_service.MutateSharedSetsRequest): + request = shared_set_service.MutateSharedSetsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_shared_sets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "SharedSetServiceAsyncClient": + 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__ = ("SharedSetServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/shared_set_service/client.py b/google/ads/googleads/v24/services/services/shared_set_service/client.py new file mode 100644 index 000000000..0000e654f --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_set_service/client.py @@ -0,0 +1,891 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import shared_set_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import SharedSetServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import SharedSetServiceGrpcTransport +from .transports.grpc_asyncio import SharedSetServiceGrpcAsyncIOTransport + + +class SharedSetServiceClientMeta(type): + """Metaclass for the SharedSetService 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[SharedSetServiceTransport]] + _transport_registry["grpc"] = SharedSetServiceGrpcTransport + _transport_registry["grpc_asyncio"] = SharedSetServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[SharedSetServiceTransport]: + """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 SharedSetServiceClient(metaclass=SharedSetServiceClientMeta): + """Service to manage shared sets.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + SharedSetServiceClient: 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: + SharedSetServiceClient: 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) -> SharedSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + SharedSetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def shared_set_path( + customer_id: str, + shared_set_id: str, + ) -> str: + """Returns a fully-qualified shared_set string.""" + return "customers/{customer_id}/sharedSets/{shared_set_id}".format( + customer_id=customer_id, + shared_set_id=shared_set_id, + ) + + @staticmethod + def parse_shared_set_path(path: str) -> Dict[str, str]: + """Parses a shared_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/sharedSets/(?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 = SharedSetServiceClient._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 = SharedSetServiceClient._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 + ): + """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 = SharedSetServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = SharedSetServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + SharedSetServiceClient._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 = SharedSetServiceClient._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): + """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, + SharedSetServiceTransport, + Callable[..., SharedSetServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the shared set 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,SharedSetServiceTransport,Callable[..., SharedSetServiceTransport]]]): + 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 SharedSetServiceTransport 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, + ) = SharedSetServiceClient._read_environment_variables() + self._client_cert_source = ( + SharedSetServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = SharedSetServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, SharedSetServiceTransport) + if transport_provided: + # transport is a SharedSetServiceTransport 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(SharedSetServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or SharedSetServiceClient._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[SharedSetServiceTransport], + Callable[..., SharedSetServiceTransport], + ] = ( + SharedSetServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., SharedSetServiceTransport], 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.ads.googleads.v24.services.SharedSetServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.SharedSetService", + "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.ads.googleads.v24.services.SharedSetService", + "credentialsType": None, + } + ), + ) + + def mutate_shared_sets( + self, + request: Optional[ + Union[shared_set_service.MutateSharedSetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[shared_set_service.SharedSetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> shared_set_service.MutateSharedSetsResponse: + r"""Creates, updates, or removes shared sets. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SharedSetError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateSharedSetsRequest, dict]): + The request object. Request message for + [SharedSetService.MutateSharedSets][google.ads.googleads.v24.services.SharedSetService.MutateSharedSets]. + customer_id (str): + Required. The ID of the customer + whose shared sets are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.SharedSetOperation]): + Required. The list of operations to + perform on individual shared sets. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateSharedSetsResponse: + Response message for a shared set + mutate. + + """ + # 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 = [customer_id, operations] + 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, shared_set_service.MutateSharedSetsRequest): + request = shared_set_service.MutateSharedSetsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_shared_sets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "SharedSetServiceClient": + 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() + + +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__ = ("SharedSetServiceClient",) diff --git a/google/ads/googleads/v24/services/services/shared_set_service/transports/README.rst b/google/ads/googleads/v24/services/services/shared_set_service/transports/README.rst new file mode 100644 index 000000000..c59ede86d --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_set_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`SharedSetServiceTransport` is the ABC for all transports. +- public child `SharedSetServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `SharedSetServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseSharedSetServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `SharedSetServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/shared_set_service/transports/__init__.py b/google/ads/googleads/v24/services/services/shared_set_service/transports/__init__.py new file mode 100644 index 000000000..08f61035e --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_set_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import SharedSetServiceTransport +from .grpc import SharedSetServiceGrpcTransport +from .grpc_asyncio import SharedSetServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[SharedSetServiceTransport]] +_transport_registry["grpc"] = SharedSetServiceGrpcTransport +_transport_registry["grpc_asyncio"] = SharedSetServiceGrpcAsyncIOTransport + +__all__ = ( + "SharedSetServiceTransport", + "SharedSetServiceGrpcTransport", + "SharedSetServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/shared_set_service/transports/base.py b/google/ads/googleads/v24/services/services/shared_set_service/transports/base.py new file mode 100644 index 000000000..48f5bd6c0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_set_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import shared_set_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 SharedSetServiceTransport(abc.ABC): + """Abstract transport class for SharedSetService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_shared_sets: gapic_v1.method.wrap_method( + self.mutate_shared_sets, + 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 mutate_shared_sets( + self, + ) -> Callable[ + [shared_set_service.MutateSharedSetsRequest], + Union[ + shared_set_service.MutateSharedSetsResponse, + Awaitable[shared_set_service.MutateSharedSetsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("SharedSetServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/shared_set_service/transports/grpc.py b/google/ads/googleads/v24/services/services/shared_set_service/transports/grpc.py new file mode 100644 index 000000000..f49fcb984 --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_set_service/transports/grpc.py @@ -0,0 +1,395 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import shared_set_service +from .base import SharedSetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.SharedSetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.SharedSetService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class SharedSetServiceGrpcTransport(SharedSetServiceTransport): + """gRPC backend transport for SharedSetService. + + Service to manage shared sets. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_shared_sets( + self, + ) -> Callable[ + [shared_set_service.MutateSharedSetsRequest], + shared_set_service.MutateSharedSetsResponse, + ]: + r"""Return a callable for the mutate shared sets method over gRPC. + + Creates, updates, or removes shared sets. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SharedSetError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Returns: + Callable[[~.MutateSharedSetsRequest], + ~.MutateSharedSetsResponse]: + 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 "mutate_shared_sets" not in self._stubs: + self._stubs["mutate_shared_sets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.SharedSetService/MutateSharedSets", + request_serializer=shared_set_service.MutateSharedSetsRequest.serialize, + response_deserializer=shared_set_service.MutateSharedSetsResponse.deserialize, + ) + ) + return self._stubs["mutate_shared_sets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("SharedSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/shared_set_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/shared_set_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..887165bb0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/shared_set_service/transports/grpc_asyncio.py @@ -0,0 +1,416 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import shared_set_service +from .base import SharedSetServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.SharedSetService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.SharedSetService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class SharedSetServiceGrpcAsyncIOTransport(SharedSetServiceTransport): + """gRPC AsyncIO backend transport for SharedSetService. + + Service to manage shared sets. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_shared_sets( + self, + ) -> Callable[ + [shared_set_service.MutateSharedSetsRequest], + Awaitable[shared_set_service.MutateSharedSetsResponse], + ]: + r"""Return a callable for the mutate shared sets method over gRPC. + + Creates, updates, or removes shared sets. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SharedSetError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Returns: + Callable[[~.MutateSharedSetsRequest], + Awaitable[~.MutateSharedSetsResponse]]: + 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 "mutate_shared_sets" not in self._stubs: + self._stubs["mutate_shared_sets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.SharedSetService/MutateSharedSets", + request_serializer=shared_set_service.MutateSharedSetsRequest.serialize, + response_deserializer=shared_set_service.MutateSharedSetsResponse.deserialize, + ) + ) + return self._stubs["mutate_shared_sets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_shared_sets: self._wrap_method( + self.mutate_shared_sets, + 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" + + +__all__ = ("SharedSetServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/smart_campaign_setting_service/__init__.py b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/__init__.py new file mode 100644 index 000000000..f9ef38289 --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import SmartCampaignSettingServiceClient +from .async_client import SmartCampaignSettingServiceAsyncClient + +__all__ = ( + "SmartCampaignSettingServiceClient", + "SmartCampaignSettingServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/smart_campaign_setting_service/async_client.py b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/async_client.py new file mode 100644 index 000000000..a15220266 --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/async_client.py @@ -0,0 +1,538 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + smart_campaign_setting_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + SmartCampaignSettingServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import SmartCampaignSettingServiceClient + +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 SmartCampaignSettingServiceAsyncClient: + """Service to manage Smart campaign settings.""" + + _client: SmartCampaignSettingServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = SmartCampaignSettingServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + SmartCampaignSettingServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + SmartCampaignSettingServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = SmartCampaignSettingServiceClient._DEFAULT_UNIVERSE + + campaign_path = staticmethod( + SmartCampaignSettingServiceClient.campaign_path + ) + parse_campaign_path = staticmethod( + SmartCampaignSettingServiceClient.parse_campaign_path + ) + smart_campaign_setting_path = staticmethod( + SmartCampaignSettingServiceClient.smart_campaign_setting_path + ) + parse_smart_campaign_setting_path = staticmethod( + SmartCampaignSettingServiceClient.parse_smart_campaign_setting_path + ) + common_billing_account_path = staticmethod( + SmartCampaignSettingServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + SmartCampaignSettingServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + SmartCampaignSettingServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + SmartCampaignSettingServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + SmartCampaignSettingServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + SmartCampaignSettingServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + SmartCampaignSettingServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + SmartCampaignSettingServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + SmartCampaignSettingServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + SmartCampaignSettingServiceClient.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: + SmartCampaignSettingServiceAsyncClient: The constructed client. + """ + return SmartCampaignSettingServiceClient.from_service_account_info.__func__(SmartCampaignSettingServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + SmartCampaignSettingServiceAsyncClient: The constructed client. + """ + return SmartCampaignSettingServiceClient.from_service_account_file.__func__(SmartCampaignSettingServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return SmartCampaignSettingServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> SmartCampaignSettingServiceTransport: + """Returns the transport used by the client instance. + + Returns: + SmartCampaignSettingServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = SmartCampaignSettingServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + SmartCampaignSettingServiceTransport, + Callable[..., SmartCampaignSettingServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the smart campaign setting 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,SmartCampaignSettingServiceTransport,Callable[..., SmartCampaignSettingServiceTransport]]]): + 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 SmartCampaignSettingServiceTransport 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 = SmartCampaignSettingServiceClient( + 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.ads.googleads.v24.services.SmartCampaignSettingServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.SmartCampaignSettingService", + "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.ads.googleads.v24.services.SmartCampaignSettingService", + "credentialsType": None, + } + ), + ) + + async def get_smart_campaign_status( + self, + request: Optional[ + Union[ + smart_campaign_setting_service.GetSmartCampaignStatusRequest, + dict, + ] + ] = None, + *, + resource_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]]] = (), + ) -> smart_campaign_setting_service.GetSmartCampaignStatusResponse: + r"""Returns the status of the requested Smart campaign. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.GetSmartCampaignStatusRequest, dict]]): + The request object. Request message for + [SmartCampaignSettingService.GetSmartCampaignStatus][google.ads.googleads.v24.services.SmartCampaignSettingService.GetSmartCampaignStatus]. + resource_name (:class:`str`): + Required. The resource name of the + Smart campaign setting belonging to the + Smart campaign to fetch the status of. + + This corresponds to the ``resource_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.ads.googleads.v24.services.types.GetSmartCampaignStatusResponse: + Response message for + [SmartCampaignSettingService.GetSmartCampaignStatus][google.ads.googleads.v24.services.SmartCampaignSettingService.GetSmartCampaignStatus]. + + """ + # 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 = [resource_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, + smart_campaign_setting_service.GetSmartCampaignStatusRequest, + ): + request = ( + smart_campaign_setting_service.GetSmartCampaignStatusRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_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_smart_campaign_status + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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 mutate_smart_campaign_settings( + self, + request: Optional[ + Union[ + smart_campaign_setting_service.MutateSmartCampaignSettingsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + smart_campaign_setting_service.SmartCampaignSettingOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> smart_campaign_setting_service.MutateSmartCampaignSettingsResponse: + r"""Updates Smart campaign settings for campaigns. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateSmartCampaignSettingsRequest, dict]]): + The request object. Request message for + [SmartCampaignSettingService.MutateSmartCampaignSettings][google.ads.googleads.v24.services.SmartCampaignSettingService.MutateSmartCampaignSettings]. + customer_id (:class:`str`): + Required. The ID of the customer + whose Smart campaign settings are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.SmartCampaignSettingOperation]`): + Required. The list of operations to + perform on individual Smart campaign + settings. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateSmartCampaignSettingsResponse: + Response message for campaign mutate. + """ + # 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 = [customer_id, operations] + 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, + smart_campaign_setting_service.MutateSmartCampaignSettingsRequest, + ): + request = smart_campaign_setting_service.MutateSmartCampaignSettingsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_smart_campaign_settings + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "SmartCampaignSettingServiceAsyncClient": + 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__ = ("SmartCampaignSettingServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/smart_campaign_setting_service/client.py b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/client.py new file mode 100644 index 000000000..e062af6d6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/client.py @@ -0,0 +1,1034 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + smart_campaign_setting_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + SmartCampaignSettingServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import SmartCampaignSettingServiceGrpcTransport +from .transports.grpc_asyncio import ( + SmartCampaignSettingServiceGrpcAsyncIOTransport, +) + + +class SmartCampaignSettingServiceClientMeta(type): + """Metaclass for the SmartCampaignSettingService 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[SmartCampaignSettingServiceTransport]] + _transport_registry["grpc"] = SmartCampaignSettingServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + SmartCampaignSettingServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[SmartCampaignSettingServiceTransport]: + """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 SmartCampaignSettingServiceClient( + metaclass=SmartCampaignSettingServiceClientMeta +): + """Service to manage Smart campaign settings.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + SmartCampaignSettingServiceClient: 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: + SmartCampaignSettingServiceClient: 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) -> SmartCampaignSettingServiceTransport: + """Returns the transport used by the client instance. + + Returns: + SmartCampaignSettingServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def smart_campaign_setting_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified smart_campaign_setting string.""" + return "customers/{customer_id}/smartCampaignSettings/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_smart_campaign_setting_path(path: str) -> Dict[str, str]: + """Parses a smart_campaign_setting path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/smartCampaignSettings/(?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 = ( + SmartCampaignSettingServiceClient._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 = ( + SmartCampaignSettingServiceClient._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 + ): + """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 = ( + SmartCampaignSettingServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + SmartCampaignSettingServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = SmartCampaignSettingServiceClient._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 = SmartCampaignSettingServiceClient._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): + """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, + SmartCampaignSettingServiceTransport, + Callable[..., SmartCampaignSettingServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the smart campaign setting 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,SmartCampaignSettingServiceTransport,Callable[..., SmartCampaignSettingServiceTransport]]]): + 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 SmartCampaignSettingServiceTransport 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, + ) = SmartCampaignSettingServiceClient._read_environment_variables() + self._client_cert_source = ( + SmartCampaignSettingServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + SmartCampaignSettingServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, SmartCampaignSettingServiceTransport + ) + if transport_provided: + # transport is a SmartCampaignSettingServiceTransport 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( + SmartCampaignSettingServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or SmartCampaignSettingServiceClient._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[SmartCampaignSettingServiceTransport], + Callable[..., SmartCampaignSettingServiceTransport], + ] = ( + SmartCampaignSettingServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., SmartCampaignSettingServiceTransport], + 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.ads.googleads.v24.services.SmartCampaignSettingServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.SmartCampaignSettingService", + "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.ads.googleads.v24.services.SmartCampaignSettingService", + "credentialsType": None, + } + ), + ) + + def get_smart_campaign_status( + self, + request: Optional[ + Union[ + smart_campaign_setting_service.GetSmartCampaignStatusRequest, + dict, + ] + ] = None, + *, + resource_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]]] = (), + ) -> smart_campaign_setting_service.GetSmartCampaignStatusResponse: + r"""Returns the status of the requested Smart campaign. + + Args: + request (Union[google.ads.googleads.v24.services.types.GetSmartCampaignStatusRequest, dict]): + The request object. Request message for + [SmartCampaignSettingService.GetSmartCampaignStatus][google.ads.googleads.v24.services.SmartCampaignSettingService.GetSmartCampaignStatus]. + resource_name (str): + Required. The resource name of the + Smart campaign setting belonging to the + Smart campaign to fetch the status of. + + This corresponds to the ``resource_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.ads.googleads.v24.services.types.GetSmartCampaignStatusResponse: + Response message for + [SmartCampaignSettingService.GetSmartCampaignStatus][google.ads.googleads.v24.services.SmartCampaignSettingService.GetSmartCampaignStatus]. + + """ + # 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 = [resource_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, + smart_campaign_setting_service.GetSmartCampaignStatusRequest, + ): + request = ( + smart_campaign_setting_service.GetSmartCampaignStatusRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if resource_name is not None: + request.resource_name = resource_name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.get_smart_campaign_status + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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 mutate_smart_campaign_settings( + self, + request: Optional[ + Union[ + smart_campaign_setting_service.MutateSmartCampaignSettingsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + smart_campaign_setting_service.SmartCampaignSettingOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> smart_campaign_setting_service.MutateSmartCampaignSettingsResponse: + r"""Updates Smart campaign settings for campaigns. + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateSmartCampaignSettingsRequest, dict]): + The request object. Request message for + [SmartCampaignSettingService.MutateSmartCampaignSettings][google.ads.googleads.v24.services.SmartCampaignSettingService.MutateSmartCampaignSettings]. + customer_id (str): + Required. The ID of the customer + whose Smart campaign settings are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.SmartCampaignSettingOperation]): + Required. The list of operations to + perform on individual Smart campaign + settings. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateSmartCampaignSettingsResponse: + Response message for campaign mutate. + """ + # 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 = [customer_id, operations] + 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, + smart_campaign_setting_service.MutateSmartCampaignSettingsRequest, + ): + request = smart_campaign_setting_service.MutateSmartCampaignSettingsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_smart_campaign_settings + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "SmartCampaignSettingServiceClient": + 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() + + +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__ = ("SmartCampaignSettingServiceClient",) diff --git a/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/README.rst b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/README.rst new file mode 100644 index 000000000..3b87eae52 --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`SmartCampaignSettingServiceTransport` is the ABC for all transports. +- public child `SmartCampaignSettingServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `SmartCampaignSettingServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseSmartCampaignSettingServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `SmartCampaignSettingServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/__init__.py b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/__init__.py new file mode 100644 index 000000000..392d38489 --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import SmartCampaignSettingServiceTransport +from .grpc import SmartCampaignSettingServiceGrpcTransport +from .grpc_asyncio import SmartCampaignSettingServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[SmartCampaignSettingServiceTransport]] +_transport_registry["grpc"] = SmartCampaignSettingServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + SmartCampaignSettingServiceGrpcAsyncIOTransport +) + +__all__ = ( + "SmartCampaignSettingServiceTransport", + "SmartCampaignSettingServiceGrpcTransport", + "SmartCampaignSettingServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/base.py b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/base.py new file mode 100644 index 000000000..22f8c0d22 --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/base.py @@ -0,0 +1,196 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + smart_campaign_setting_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 SmartCampaignSettingServiceTransport(abc.ABC): + """Abstract transport class for SmartCampaignSettingService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.get_smart_campaign_status: gapic_v1.method.wrap_method( + self.get_smart_campaign_status, + default_timeout=None, + client_info=client_info, + ), + self.mutate_smart_campaign_settings: gapic_v1.method.wrap_method( + self.mutate_smart_campaign_settings, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def get_smart_campaign_status( + self, + ) -> Callable[ + [smart_campaign_setting_service.GetSmartCampaignStatusRequest], + Union[ + smart_campaign_setting_service.GetSmartCampaignStatusResponse, + Awaitable[ + smart_campaign_setting_service.GetSmartCampaignStatusResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def mutate_smart_campaign_settings( + self, + ) -> Callable[ + [smart_campaign_setting_service.MutateSmartCampaignSettingsRequest], + Union[ + smart_campaign_setting_service.MutateSmartCampaignSettingsResponse, + Awaitable[ + smart_campaign_setting_service.MutateSmartCampaignSettingsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("SmartCampaignSettingServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/grpc.py b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/grpc.py new file mode 100644 index 000000000..6a5eb3297 --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/grpc.py @@ -0,0 +1,418 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + smart_campaign_setting_service, +) +from .base import SmartCampaignSettingServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.SmartCampaignSettingService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.SmartCampaignSettingService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class SmartCampaignSettingServiceGrpcTransport( + SmartCampaignSettingServiceTransport +): + """gRPC backend transport for SmartCampaignSettingService. + + Service to manage Smart campaign settings. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 get_smart_campaign_status( + self, + ) -> Callable[ + [smart_campaign_setting_service.GetSmartCampaignStatusRequest], + smart_campaign_setting_service.GetSmartCampaignStatusResponse, + ]: + r"""Return a callable for the get smart campaign status method over gRPC. + + Returns the status of the requested Smart campaign. + + Returns: + Callable[[~.GetSmartCampaignStatusRequest], + ~.GetSmartCampaignStatusResponse]: + 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_smart_campaign_status" not in self._stubs: + self._stubs["get_smart_campaign_status"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.SmartCampaignSettingService/GetSmartCampaignStatus", + request_serializer=smart_campaign_setting_service.GetSmartCampaignStatusRequest.serialize, + response_deserializer=smart_campaign_setting_service.GetSmartCampaignStatusResponse.deserialize, + ) + ) + return self._stubs["get_smart_campaign_status"] + + @property + def mutate_smart_campaign_settings( + self, + ) -> Callable[ + [smart_campaign_setting_service.MutateSmartCampaignSettingsRequest], + smart_campaign_setting_service.MutateSmartCampaignSettingsResponse, + ]: + r"""Return a callable for the mutate smart campaign settings method over gRPC. + + Updates Smart campaign settings for campaigns. + + Returns: + Callable[[~.MutateSmartCampaignSettingsRequest], + ~.MutateSmartCampaignSettingsResponse]: + 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 "mutate_smart_campaign_settings" not in self._stubs: + self._stubs["mutate_smart_campaign_settings"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.SmartCampaignSettingService/MutateSmartCampaignSettings", + request_serializer=smart_campaign_setting_service.MutateSmartCampaignSettingsRequest.serialize, + response_deserializer=smart_campaign_setting_service.MutateSmartCampaignSettingsResponse.deserialize, + ) + ) + return self._stubs["mutate_smart_campaign_settings"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("SmartCampaignSettingServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..216a4c19c --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_setting_service/transports/grpc_asyncio.py @@ -0,0 +1,448 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + smart_campaign_setting_service, +) +from .base import SmartCampaignSettingServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.SmartCampaignSettingService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.SmartCampaignSettingService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class SmartCampaignSettingServiceGrpcAsyncIOTransport( + SmartCampaignSettingServiceTransport +): + """gRPC AsyncIO backend transport for SmartCampaignSettingService. + + Service to manage Smart campaign settings. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 get_smart_campaign_status( + self, + ) -> Callable[ + [smart_campaign_setting_service.GetSmartCampaignStatusRequest], + Awaitable[ + smart_campaign_setting_service.GetSmartCampaignStatusResponse + ], + ]: + r"""Return a callable for the get smart campaign status method over gRPC. + + Returns the status of the requested Smart campaign. + + Returns: + Callable[[~.GetSmartCampaignStatusRequest], + Awaitable[~.GetSmartCampaignStatusResponse]]: + 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_smart_campaign_status" not in self._stubs: + self._stubs["get_smart_campaign_status"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.SmartCampaignSettingService/GetSmartCampaignStatus", + request_serializer=smart_campaign_setting_service.GetSmartCampaignStatusRequest.serialize, + response_deserializer=smart_campaign_setting_service.GetSmartCampaignStatusResponse.deserialize, + ) + ) + return self._stubs["get_smart_campaign_status"] + + @property + def mutate_smart_campaign_settings( + self, + ) -> Callable[ + [smart_campaign_setting_service.MutateSmartCampaignSettingsRequest], + Awaitable[ + smart_campaign_setting_service.MutateSmartCampaignSettingsResponse + ], + ]: + r"""Return a callable for the mutate smart campaign settings method over gRPC. + + Updates Smart campaign settings for campaigns. + + Returns: + Callable[[~.MutateSmartCampaignSettingsRequest], + Awaitable[~.MutateSmartCampaignSettingsResponse]]: + 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 "mutate_smart_campaign_settings" not in self._stubs: + self._stubs["mutate_smart_campaign_settings"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.SmartCampaignSettingService/MutateSmartCampaignSettings", + request_serializer=smart_campaign_setting_service.MutateSmartCampaignSettingsRequest.serialize, + response_deserializer=smart_campaign_setting_service.MutateSmartCampaignSettingsResponse.deserialize, + ) + ) + return self._stubs["mutate_smart_campaign_settings"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.get_smart_campaign_status: self._wrap_method( + self.get_smart_campaign_status, + default_timeout=None, + client_info=client_info, + ), + self.mutate_smart_campaign_settings: self._wrap_method( + self.mutate_smart_campaign_settings, + 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" + + +__all__ = ("SmartCampaignSettingServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/__init__.py b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/__init__.py new file mode 100644 index 000000000..c74d95f02 --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import SmartCampaignSuggestServiceClient +from .async_client import SmartCampaignSuggestServiceAsyncClient + +__all__ = ( + "SmartCampaignSuggestServiceClient", + "SmartCampaignSuggestServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/async_client.py b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/async_client.py new file mode 100644 index 000000000..53e093622 --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/async_client.py @@ -0,0 +1,632 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + smart_campaign_suggest_service, +) +from .transports.base import ( + SmartCampaignSuggestServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import SmartCampaignSuggestServiceClient + +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 SmartCampaignSuggestServiceAsyncClient: + """Service to get suggestions for Smart Campaigns.""" + + _client: SmartCampaignSuggestServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = SmartCampaignSuggestServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + SmartCampaignSuggestServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + SmartCampaignSuggestServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = SmartCampaignSuggestServiceClient._DEFAULT_UNIVERSE + + campaign_path = staticmethod( + SmartCampaignSuggestServiceClient.campaign_path + ) + parse_campaign_path = staticmethod( + SmartCampaignSuggestServiceClient.parse_campaign_path + ) + keyword_theme_constant_path = staticmethod( + SmartCampaignSuggestServiceClient.keyword_theme_constant_path + ) + parse_keyword_theme_constant_path = staticmethod( + SmartCampaignSuggestServiceClient.parse_keyword_theme_constant_path + ) + common_billing_account_path = staticmethod( + SmartCampaignSuggestServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + SmartCampaignSuggestServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + SmartCampaignSuggestServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + SmartCampaignSuggestServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + SmartCampaignSuggestServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + SmartCampaignSuggestServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + SmartCampaignSuggestServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + SmartCampaignSuggestServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + SmartCampaignSuggestServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + SmartCampaignSuggestServiceClient.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: + SmartCampaignSuggestServiceAsyncClient: The constructed client. + """ + return SmartCampaignSuggestServiceClient.from_service_account_info.__func__(SmartCampaignSuggestServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + SmartCampaignSuggestServiceAsyncClient: The constructed client. + """ + return SmartCampaignSuggestServiceClient.from_service_account_file.__func__(SmartCampaignSuggestServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return SmartCampaignSuggestServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> SmartCampaignSuggestServiceTransport: + """Returns the transport used by the client instance. + + Returns: + SmartCampaignSuggestServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = SmartCampaignSuggestServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + SmartCampaignSuggestServiceTransport, + Callable[..., SmartCampaignSuggestServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the smart campaign suggest 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,SmartCampaignSuggestServiceTransport,Callable[..., SmartCampaignSuggestServiceTransport]]]): + 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 SmartCampaignSuggestServiceTransport 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 = SmartCampaignSuggestServiceClient( + 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.ads.googleads.v24.services.SmartCampaignSuggestServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.SmartCampaignSuggestService", + "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.ads.googleads.v24.services.SmartCampaignSuggestService", + "credentialsType": None, + } + ), + ) + + async def suggest_smart_campaign_budget_options( + self, + request: Optional[ + Union[ + smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsResponse + ): + r"""Returns BudgetOption suggestions. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.SuggestSmartCampaignBudgetOptionsRequest, dict]]): + The request object. Request message for + [SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions]. + 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.googleads.v24.services.types.SuggestSmartCampaignBudgetOptionsResponse: + Response message for + [SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions]. + Depending on whether the system could suggest the + options, either all of the options or none of them + might be returned. + + """ + # 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, + smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsRequest, + ): + request = smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.suggest_smart_campaign_budget_options + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 suggest_smart_campaign_ad( + self, + request: Optional[ + Union[ + smart_campaign_suggest_service.SuggestSmartCampaignAdRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + suggestion_info: Optional[ + smart_campaign_suggest_service.SmartCampaignSuggestionInfo + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> smart_campaign_suggest_service.SuggestSmartCampaignAdResponse: + r"""Suggests a Smart campaign ad compatible with the Ad + family of resources, based on data points such as + targeting and the business to advertise. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.SuggestSmartCampaignAdRequest, dict]]): + The request object. Request message for + [SmartCampaignSuggestService.SuggestSmartCampaignAd][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestSmartCampaignAd]. + customer_id (:class:`str`): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + suggestion_info (:class:`google.ads.googleads.v24.services.types.SmartCampaignSuggestionInfo`): + Required. Inputs used to suggest a Smart campaign ad. + Required fields: final_url, language_code, + keyword_themes. Optional but recommended fields to + improve the quality of the suggestion: business_setting + and geo_target. + + This corresponds to the ``suggestion_info`` 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.ads.googleads.v24.services.types.SuggestSmartCampaignAdResponse: + Response message for + [SmartCampaignSuggestService.SuggestSmartCampaignAd][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestSmartCampaignAd]. + + """ + # 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 = [customer_id, suggestion_info] + 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, + smart_campaign_suggest_service.SuggestSmartCampaignAdRequest, + ): + request = ( + smart_campaign_suggest_service.SuggestSmartCampaignAdRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if suggestion_info is not None: + request.suggestion_info = suggestion_info + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.suggest_smart_campaign_ad + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 suggest_keyword_themes( + self, + request: Optional[ + Union[ + smart_campaign_suggest_service.SuggestKeywordThemesRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + suggestion_info: Optional[ + smart_campaign_suggest_service.SmartCampaignSuggestionInfo + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> smart_campaign_suggest_service.SuggestKeywordThemesResponse: + r"""Suggests keyword themes to advertise on. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.SuggestKeywordThemesRequest, dict]]): + The request object. Request message for + [SmartCampaignSuggestService.SuggestKeywordThemes][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestKeywordThemes]. + customer_id (:class:`str`): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + suggestion_info (:class:`google.ads.googleads.v24.services.types.SmartCampaignSuggestionInfo`): + Required. Information to get keyword theme suggestions. + Required fields: + + - suggestion_info.final_url + - suggestion_info.language_code + - suggestion_info.geo_target + + Recommended fields: + + - suggestion_info.business_setting + + This corresponds to the ``suggestion_info`` 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.ads.googleads.v24.services.types.SuggestKeywordThemesResponse: + Response message for + [SmartCampaignSuggestService.SuggestKeywordThemes][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestKeywordThemes]. + + """ + # 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 = [customer_id, suggestion_info] + 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, smart_campaign_suggest_service.SuggestKeywordThemesRequest + ): + request = ( + smart_campaign_suggest_service.SuggestKeywordThemesRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if suggestion_info is not None: + request.suggestion_info = suggestion_info + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.suggest_keyword_themes + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "SmartCampaignSuggestServiceAsyncClient": + 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__ = ("SmartCampaignSuggestServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/client.py b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/client.py new file mode 100644 index 000000000..8030789fe --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/client.py @@ -0,0 +1,1118 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + smart_campaign_suggest_service, +) +from .transports.base import ( + SmartCampaignSuggestServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import SmartCampaignSuggestServiceGrpcTransport +from .transports.grpc_asyncio import ( + SmartCampaignSuggestServiceGrpcAsyncIOTransport, +) + + +class SmartCampaignSuggestServiceClientMeta(type): + """Metaclass for the SmartCampaignSuggestService 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[SmartCampaignSuggestServiceTransport]] + _transport_registry["grpc"] = SmartCampaignSuggestServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + SmartCampaignSuggestServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[SmartCampaignSuggestServiceTransport]: + """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 SmartCampaignSuggestServiceClient( + metaclass=SmartCampaignSuggestServiceClientMeta +): + """Service to get suggestions for Smart Campaigns.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + SmartCampaignSuggestServiceClient: 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: + SmartCampaignSuggestServiceClient: 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) -> SmartCampaignSuggestServiceTransport: + """Returns the transport used by the client instance. + + Returns: + SmartCampaignSuggestServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def campaign_path( + customer_id: str, + campaign_id: str, + ) -> str: + """Returns a fully-qualified campaign string.""" + return "customers/{customer_id}/campaigns/{campaign_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + ) + + @staticmethod + def parse_campaign_path(path: str) -> Dict[str, str]: + """Parses a campaign path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaigns/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def keyword_theme_constant_path( + express_category_id: str, + express_sub_category_id: str, + ) -> str: + """Returns a fully-qualified keyword_theme_constant string.""" + return "keywordThemeConstants/{express_category_id}~{express_sub_category_id}".format( + express_category_id=express_category_id, + express_sub_category_id=express_sub_category_id, + ) + + @staticmethod + def parse_keyword_theme_constant_path(path: str) -> Dict[str, str]: + """Parses a keyword_theme_constant path into its component segments.""" + m = re.match( + r"^keywordThemeConstants/(?P.+?)~(?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 = ( + SmartCampaignSuggestServiceClient._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 = ( + SmartCampaignSuggestServiceClient._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 + ): + """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 = ( + SmartCampaignSuggestServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + SmartCampaignSuggestServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = SmartCampaignSuggestServiceClient._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 = SmartCampaignSuggestServiceClient._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): + """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, + SmartCampaignSuggestServiceTransport, + Callable[..., SmartCampaignSuggestServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the smart campaign suggest 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,SmartCampaignSuggestServiceTransport,Callable[..., SmartCampaignSuggestServiceTransport]]]): + 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 SmartCampaignSuggestServiceTransport 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, + ) = SmartCampaignSuggestServiceClient._read_environment_variables() + self._client_cert_source = ( + SmartCampaignSuggestServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + SmartCampaignSuggestServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, SmartCampaignSuggestServiceTransport + ) + if transport_provided: + # transport is a SmartCampaignSuggestServiceTransport 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( + SmartCampaignSuggestServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or SmartCampaignSuggestServiceClient._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[SmartCampaignSuggestServiceTransport], + Callable[..., SmartCampaignSuggestServiceTransport], + ] = ( + SmartCampaignSuggestServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., SmartCampaignSuggestServiceTransport], + 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.ads.googleads.v24.services.SmartCampaignSuggestServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.SmartCampaignSuggestService", + "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.ads.googleads.v24.services.SmartCampaignSuggestService", + "credentialsType": None, + } + ), + ) + + def suggest_smart_campaign_budget_options( + self, + request: Optional[ + Union[ + smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsResponse + ): + r"""Returns BudgetOption suggestions. + + Args: + request (Union[google.ads.googleads.v24.services.types.SuggestSmartCampaignBudgetOptionsRequest, dict]): + The request object. Request message for + [SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions]. + 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.googleads.v24.services.types.SuggestSmartCampaignBudgetOptionsResponse: + Response message for + [SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions]. + Depending on whether the system could suggest the + options, either all of the options or none of them + might be returned. + + """ + # 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, + smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsRequest, + ): + request = smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.suggest_smart_campaign_budget_options + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 suggest_smart_campaign_ad( + self, + request: Optional[ + Union[ + smart_campaign_suggest_service.SuggestSmartCampaignAdRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + suggestion_info: Optional[ + smart_campaign_suggest_service.SmartCampaignSuggestionInfo + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> smart_campaign_suggest_service.SuggestSmartCampaignAdResponse: + r"""Suggests a Smart campaign ad compatible with the Ad + family of resources, based on data points such as + targeting and the business to advertise. + + Args: + request (Union[google.ads.googleads.v24.services.types.SuggestSmartCampaignAdRequest, dict]): + The request object. Request message for + [SmartCampaignSuggestService.SuggestSmartCampaignAd][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestSmartCampaignAd]. + customer_id (str): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + suggestion_info (google.ads.googleads.v24.services.types.SmartCampaignSuggestionInfo): + Required. Inputs used to suggest a Smart campaign ad. + Required fields: final_url, language_code, + keyword_themes. Optional but recommended fields to + improve the quality of the suggestion: business_setting + and geo_target. + + This corresponds to the ``suggestion_info`` 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.ads.googleads.v24.services.types.SuggestSmartCampaignAdResponse: + Response message for + [SmartCampaignSuggestService.SuggestSmartCampaignAd][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestSmartCampaignAd]. + + """ + # 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 = [customer_id, suggestion_info] + 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, + smart_campaign_suggest_service.SuggestSmartCampaignAdRequest, + ): + request = ( + smart_campaign_suggest_service.SuggestSmartCampaignAdRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if suggestion_info is not None: + request.suggestion_info = suggestion_info + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.suggest_smart_campaign_ad + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 suggest_keyword_themes( + self, + request: Optional[ + Union[ + smart_campaign_suggest_service.SuggestKeywordThemesRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + suggestion_info: Optional[ + smart_campaign_suggest_service.SmartCampaignSuggestionInfo + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> smart_campaign_suggest_service.SuggestKeywordThemesResponse: + r"""Suggests keyword themes to advertise on. + + Args: + request (Union[google.ads.googleads.v24.services.types.SuggestKeywordThemesRequest, dict]): + The request object. Request message for + [SmartCampaignSuggestService.SuggestKeywordThemes][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestKeywordThemes]. + customer_id (str): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + suggestion_info (google.ads.googleads.v24.services.types.SmartCampaignSuggestionInfo): + Required. Information to get keyword theme suggestions. + Required fields: + + - suggestion_info.final_url + - suggestion_info.language_code + - suggestion_info.geo_target + + Recommended fields: + + - suggestion_info.business_setting + + This corresponds to the ``suggestion_info`` 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.ads.googleads.v24.services.types.SuggestKeywordThemesResponse: + Response message for + [SmartCampaignSuggestService.SuggestKeywordThemes][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestKeywordThemes]. + + """ + # 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 = [customer_id, suggestion_info] + 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, smart_campaign_suggest_service.SuggestKeywordThemesRequest + ): + request = ( + smart_campaign_suggest_service.SuggestKeywordThemesRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if suggestion_info is not None: + request.suggestion_info = suggestion_info + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.suggest_keyword_themes + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "SmartCampaignSuggestServiceClient": + 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() + + +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__ = ("SmartCampaignSuggestServiceClient",) diff --git a/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/README.rst b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/README.rst new file mode 100644 index 000000000..40899e040 --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`SmartCampaignSuggestServiceTransport` is the ABC for all transports. +- public child `SmartCampaignSuggestServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `SmartCampaignSuggestServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseSmartCampaignSuggestServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `SmartCampaignSuggestServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/__init__.py b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/__init__.py new file mode 100644 index 000000000..6161b3140 --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import SmartCampaignSuggestServiceTransport +from .grpc import SmartCampaignSuggestServiceGrpcTransport +from .grpc_asyncio import SmartCampaignSuggestServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[SmartCampaignSuggestServiceTransport]] +_transport_registry["grpc"] = SmartCampaignSuggestServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + SmartCampaignSuggestServiceGrpcAsyncIOTransport +) + +__all__ = ( + "SmartCampaignSuggestServiceTransport", + "SmartCampaignSuggestServiceGrpcTransport", + "SmartCampaignSuggestServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/base.py b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/base.py new file mode 100644 index 000000000..677d9197d --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/base.py @@ -0,0 +1,217 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + smart_campaign_suggest_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 SmartCampaignSuggestServiceTransport(abc.ABC): + """Abstract transport class for SmartCampaignSuggestService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.suggest_smart_campaign_budget_options: gapic_v1.method.wrap_method( + self.suggest_smart_campaign_budget_options, + default_timeout=None, + client_info=client_info, + ), + self.suggest_smart_campaign_ad: gapic_v1.method.wrap_method( + self.suggest_smart_campaign_ad, + default_timeout=None, + client_info=client_info, + ), + self.suggest_keyword_themes: gapic_v1.method.wrap_method( + self.suggest_keyword_themes, + 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 suggest_smart_campaign_budget_options( + self, + ) -> Callable[ + [ + smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsRequest + ], + Union[ + smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsResponse, + Awaitable[ + smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def suggest_smart_campaign_ad( + self, + ) -> Callable[ + [smart_campaign_suggest_service.SuggestSmartCampaignAdRequest], + Union[ + smart_campaign_suggest_service.SuggestSmartCampaignAdResponse, + Awaitable[ + smart_campaign_suggest_service.SuggestSmartCampaignAdResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def suggest_keyword_themes( + self, + ) -> Callable[ + [smart_campaign_suggest_service.SuggestKeywordThemesRequest], + Union[ + smart_campaign_suggest_service.SuggestKeywordThemesResponse, + Awaitable[ + smart_campaign_suggest_service.SuggestKeywordThemesResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("SmartCampaignSuggestServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/grpc.py b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/grpc.py new file mode 100644 index 000000000..de0f70ae1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/grpc.py @@ -0,0 +1,454 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + smart_campaign_suggest_service, +) +from .base import SmartCampaignSuggestServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.SmartCampaignSuggestService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.SmartCampaignSuggestService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class SmartCampaignSuggestServiceGrpcTransport( + SmartCampaignSuggestServiceTransport +): + """gRPC backend transport for SmartCampaignSuggestService. + + Service to get suggestions for Smart Campaigns. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 suggest_smart_campaign_budget_options( + self, + ) -> Callable[ + [ + smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsRequest + ], + smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsResponse, + ]: + r"""Return a callable for the suggest smart campaign budget + options method over gRPC. + + Returns BudgetOption suggestions. + + Returns: + Callable[[~.SuggestSmartCampaignBudgetOptionsRequest], + ~.SuggestSmartCampaignBudgetOptionsResponse]: + 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 "suggest_smart_campaign_budget_options" not in self._stubs: + self._stubs["suggest_smart_campaign_budget_options"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.SmartCampaignSuggestService/SuggestSmartCampaignBudgetOptions", + request_serializer=smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsRequest.serialize, + response_deserializer=smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsResponse.deserialize, + ) + ) + return self._stubs["suggest_smart_campaign_budget_options"] + + @property + def suggest_smart_campaign_ad( + self, + ) -> Callable[ + [smart_campaign_suggest_service.SuggestSmartCampaignAdRequest], + smart_campaign_suggest_service.SuggestSmartCampaignAdResponse, + ]: + r"""Return a callable for the suggest smart campaign ad method over gRPC. + + Suggests a Smart campaign ad compatible with the Ad + family of resources, based on data points such as + targeting and the business to advertise. + + Returns: + Callable[[~.SuggestSmartCampaignAdRequest], + ~.SuggestSmartCampaignAdResponse]: + 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 "suggest_smart_campaign_ad" not in self._stubs: + self._stubs["suggest_smart_campaign_ad"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.SmartCampaignSuggestService/SuggestSmartCampaignAd", + request_serializer=smart_campaign_suggest_service.SuggestSmartCampaignAdRequest.serialize, + response_deserializer=smart_campaign_suggest_service.SuggestSmartCampaignAdResponse.deserialize, + ) + ) + return self._stubs["suggest_smart_campaign_ad"] + + @property + def suggest_keyword_themes( + self, + ) -> Callable[ + [smart_campaign_suggest_service.SuggestKeywordThemesRequest], + smart_campaign_suggest_service.SuggestKeywordThemesResponse, + ]: + r"""Return a callable for the suggest keyword themes method over gRPC. + + Suggests keyword themes to advertise on. + + Returns: + Callable[[~.SuggestKeywordThemesRequest], + ~.SuggestKeywordThemesResponse]: + 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 "suggest_keyword_themes" not in self._stubs: + self._stubs["suggest_keyword_themes"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.SmartCampaignSuggestService/SuggestKeywordThemes", + request_serializer=smart_campaign_suggest_service.SuggestKeywordThemesRequest.serialize, + response_deserializer=smart_campaign_suggest_service.SuggestKeywordThemesResponse.deserialize, + ) + ) + return self._stubs["suggest_keyword_themes"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("SmartCampaignSuggestServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..0c2ff04e4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/smart_campaign_suggest_service/transports/grpc_asyncio.py @@ -0,0 +1,489 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + smart_campaign_suggest_service, +) +from .base import SmartCampaignSuggestServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.SmartCampaignSuggestService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.SmartCampaignSuggestService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class SmartCampaignSuggestServiceGrpcAsyncIOTransport( + SmartCampaignSuggestServiceTransport +): + """gRPC AsyncIO backend transport for SmartCampaignSuggestService. + + Service to get suggestions for Smart Campaigns. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 suggest_smart_campaign_budget_options( + self, + ) -> Callable[ + [ + smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsRequest + ], + Awaitable[ + smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsResponse + ], + ]: + r"""Return a callable for the suggest smart campaign budget + options method over gRPC. + + Returns BudgetOption suggestions. + + Returns: + Callable[[~.SuggestSmartCampaignBudgetOptionsRequest], + Awaitable[~.SuggestSmartCampaignBudgetOptionsResponse]]: + 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 "suggest_smart_campaign_budget_options" not in self._stubs: + self._stubs["suggest_smart_campaign_budget_options"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.SmartCampaignSuggestService/SuggestSmartCampaignBudgetOptions", + request_serializer=smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsRequest.serialize, + response_deserializer=smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsResponse.deserialize, + ) + ) + return self._stubs["suggest_smart_campaign_budget_options"] + + @property + def suggest_smart_campaign_ad( + self, + ) -> Callable[ + [smart_campaign_suggest_service.SuggestSmartCampaignAdRequest], + Awaitable[ + smart_campaign_suggest_service.SuggestSmartCampaignAdResponse + ], + ]: + r"""Return a callable for the suggest smart campaign ad method over gRPC. + + Suggests a Smart campaign ad compatible with the Ad + family of resources, based on data points such as + targeting and the business to advertise. + + Returns: + Callable[[~.SuggestSmartCampaignAdRequest], + Awaitable[~.SuggestSmartCampaignAdResponse]]: + 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 "suggest_smart_campaign_ad" not in self._stubs: + self._stubs["suggest_smart_campaign_ad"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.SmartCampaignSuggestService/SuggestSmartCampaignAd", + request_serializer=smart_campaign_suggest_service.SuggestSmartCampaignAdRequest.serialize, + response_deserializer=smart_campaign_suggest_service.SuggestSmartCampaignAdResponse.deserialize, + ) + ) + return self._stubs["suggest_smart_campaign_ad"] + + @property + def suggest_keyword_themes( + self, + ) -> Callable[ + [smart_campaign_suggest_service.SuggestKeywordThemesRequest], + Awaitable[smart_campaign_suggest_service.SuggestKeywordThemesResponse], + ]: + r"""Return a callable for the suggest keyword themes method over gRPC. + + Suggests keyword themes to advertise on. + + Returns: + Callable[[~.SuggestKeywordThemesRequest], + Awaitable[~.SuggestKeywordThemesResponse]]: + 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 "suggest_keyword_themes" not in self._stubs: + self._stubs["suggest_keyword_themes"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.SmartCampaignSuggestService/SuggestKeywordThemes", + request_serializer=smart_campaign_suggest_service.SuggestKeywordThemesRequest.serialize, + response_deserializer=smart_campaign_suggest_service.SuggestKeywordThemesResponse.deserialize, + ) + ) + return self._stubs["suggest_keyword_themes"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.suggest_smart_campaign_budget_options: self._wrap_method( + self.suggest_smart_campaign_budget_options, + default_timeout=None, + client_info=client_info, + ), + self.suggest_smart_campaign_ad: self._wrap_method( + self.suggest_smart_campaign_ad, + default_timeout=None, + client_info=client_info, + ), + self.suggest_keyword_themes: self._wrap_method( + self.suggest_keyword_themes, + 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" + + +__all__ = ("SmartCampaignSuggestServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/__init__.py b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/__init__.py new file mode 100644 index 000000000..ed26727ff --- /dev/null +++ b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import ThirdPartyAppAnalyticsLinkServiceClient +from .async_client import ThirdPartyAppAnalyticsLinkServiceAsyncClient + +__all__ = ( + "ThirdPartyAppAnalyticsLinkServiceClient", + "ThirdPartyAppAnalyticsLinkServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/async_client.py b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/async_client.py new file mode 100644 index 000000000..83c4d3b62 --- /dev/null +++ b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/async_client.py @@ -0,0 +1,408 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + third_party_app_analytics_link_service, +) +from .transports.base import ( + ThirdPartyAppAnalyticsLinkServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import ThirdPartyAppAnalyticsLinkServiceClient + +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 ThirdPartyAppAnalyticsLinkServiceAsyncClient: + """This service allows management of links between Google Ads + and third party app analytics. + """ + + _client: ThirdPartyAppAnalyticsLinkServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ThirdPartyAppAnalyticsLinkServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + ThirdPartyAppAnalyticsLinkServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + ThirdPartyAppAnalyticsLinkServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ( + ThirdPartyAppAnalyticsLinkServiceClient._DEFAULT_UNIVERSE + ) + + third_party_app_analytics_link_path = staticmethod( + ThirdPartyAppAnalyticsLinkServiceClient.third_party_app_analytics_link_path + ) + parse_third_party_app_analytics_link_path = staticmethod( + ThirdPartyAppAnalyticsLinkServiceClient.parse_third_party_app_analytics_link_path + ) + common_billing_account_path = staticmethod( + ThirdPartyAppAnalyticsLinkServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ThirdPartyAppAnalyticsLinkServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ThirdPartyAppAnalyticsLinkServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ThirdPartyAppAnalyticsLinkServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ThirdPartyAppAnalyticsLinkServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ThirdPartyAppAnalyticsLinkServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ThirdPartyAppAnalyticsLinkServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ThirdPartyAppAnalyticsLinkServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ThirdPartyAppAnalyticsLinkServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ThirdPartyAppAnalyticsLinkServiceClient.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: + ThirdPartyAppAnalyticsLinkServiceAsyncClient: The constructed client. + """ + return ThirdPartyAppAnalyticsLinkServiceClient.from_service_account_info.__func__(ThirdPartyAppAnalyticsLinkServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ThirdPartyAppAnalyticsLinkServiceAsyncClient: The constructed client. + """ + return ThirdPartyAppAnalyticsLinkServiceClient.from_service_account_file.__func__(ThirdPartyAppAnalyticsLinkServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ThirdPartyAppAnalyticsLinkServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ThirdPartyAppAnalyticsLinkServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ThirdPartyAppAnalyticsLinkServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ( + ThirdPartyAppAnalyticsLinkServiceClient.get_transport_class + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ThirdPartyAppAnalyticsLinkServiceTransport, + Callable[..., ThirdPartyAppAnalyticsLinkServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the third party app analytics link 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,ThirdPartyAppAnalyticsLinkServiceTransport,Callable[..., ThirdPartyAppAnalyticsLinkServiceTransport]]]): + 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 ThirdPartyAppAnalyticsLinkServiceTransport 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 = ThirdPartyAppAnalyticsLinkServiceClient( + 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.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService", + "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.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService", + "credentialsType": None, + } + ), + ) + + async def regenerate_shareable_link_id( + self, + request: Optional[ + Union[ + third_party_app_analytics_link_service.RegenerateShareableLinkIdRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + third_party_app_analytics_link_service.RegenerateShareableLinkIdResponse + ): + r"""Regenerate ThirdPartyAppAnalyticsLink.shareable_link_id that + should be provided to the third party when setting up app + analytics. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.RegenerateShareableLinkIdRequest, dict]]): + The request object. Request message for + [ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId][google.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId]. + 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.googleads.v24.services.types.RegenerateShareableLinkIdResponse: + Response message for + [ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId][google.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId]. + + """ + # 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, + third_party_app_analytics_link_service.RegenerateShareableLinkIdRequest, + ): + request = third_party_app_analytics_link_service.RegenerateShareableLinkIdRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.regenerate_shareable_link_id + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_name),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__( + self, + ) -> "ThirdPartyAppAnalyticsLinkServiceAsyncClient": + 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__ = ("ThirdPartyAppAnalyticsLinkServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/client.py b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/client.py new file mode 100644 index 000000000..b9bc634f5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/client.py @@ -0,0 +1,882 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + third_party_app_analytics_link_service, +) +from .transports.base import ( + ThirdPartyAppAnalyticsLinkServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ThirdPartyAppAnalyticsLinkServiceGrpcTransport +from .transports.grpc_asyncio import ( + ThirdPartyAppAnalyticsLinkServiceGrpcAsyncIOTransport, +) + + +class ThirdPartyAppAnalyticsLinkServiceClientMeta(type): + """Metaclass for the ThirdPartyAppAnalyticsLinkService 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[ThirdPartyAppAnalyticsLinkServiceTransport]] + _transport_registry["grpc"] = ThirdPartyAppAnalyticsLinkServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + ThirdPartyAppAnalyticsLinkServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ThirdPartyAppAnalyticsLinkServiceTransport]: + """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 ThirdPartyAppAnalyticsLinkServiceClient( + metaclass=ThirdPartyAppAnalyticsLinkServiceClientMeta +): + """This service allows management of links between Google Ads + and third party app analytics. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + ThirdPartyAppAnalyticsLinkServiceClient: 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: + ThirdPartyAppAnalyticsLinkServiceClient: 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) -> ThirdPartyAppAnalyticsLinkServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ThirdPartyAppAnalyticsLinkServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def third_party_app_analytics_link_path( + customer_id: str, + customer_link_id: str, + ) -> str: + """Returns a fully-qualified third_party_app_analytics_link string.""" + return "customers/{customer_id}/thirdPartyAppAnalyticsLinks/{customer_link_id}".format( + customer_id=customer_id, + customer_link_id=customer_link_id, + ) + + @staticmethod + def parse_third_party_app_analytics_link_path(path: str) -> Dict[str, str]: + """Parses a third_party_app_analytics_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/thirdPartyAppAnalyticsLinks/(?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 = ( + ThirdPartyAppAnalyticsLinkServiceClient._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 = ( + ThirdPartyAppAnalyticsLinkServiceClient._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 + ): + """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 = ( + ThirdPartyAppAnalyticsLinkServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + ThirdPartyAppAnalyticsLinkServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = ThirdPartyAppAnalyticsLinkServiceClient._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 = ( + ThirdPartyAppAnalyticsLinkServiceClient._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): + """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, + ThirdPartyAppAnalyticsLinkServiceTransport, + Callable[..., ThirdPartyAppAnalyticsLinkServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the third party app analytics link 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,ThirdPartyAppAnalyticsLinkServiceTransport,Callable[..., ThirdPartyAppAnalyticsLinkServiceTransport]]]): + 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 ThirdPartyAppAnalyticsLinkServiceTransport 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, + ) = ( + ThirdPartyAppAnalyticsLinkServiceClient._read_environment_variables() + ) + self._client_cert_source = ( + ThirdPartyAppAnalyticsLinkServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + ThirdPartyAppAnalyticsLinkServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, ThirdPartyAppAnalyticsLinkServiceTransport + ) + if transport_provided: + # transport is a ThirdPartyAppAnalyticsLinkServiceTransport 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( + ThirdPartyAppAnalyticsLinkServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ThirdPartyAppAnalyticsLinkServiceClient._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[ThirdPartyAppAnalyticsLinkServiceTransport], + Callable[..., ThirdPartyAppAnalyticsLinkServiceTransport], + ] = ( + ThirdPartyAppAnalyticsLinkServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., ThirdPartyAppAnalyticsLinkServiceTransport], + 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.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService", + "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.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService", + "credentialsType": None, + } + ), + ) + + def regenerate_shareable_link_id( + self, + request: Optional[ + Union[ + third_party_app_analytics_link_service.RegenerateShareableLinkIdRequest, + dict, + ] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ( + third_party_app_analytics_link_service.RegenerateShareableLinkIdResponse + ): + r"""Regenerate ThirdPartyAppAnalyticsLink.shareable_link_id that + should be provided to the third party when setting up app + analytics. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.RegenerateShareableLinkIdRequest, dict]): + The request object. Request message for + [ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId][google.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId]. + 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.googleads.v24.services.types.RegenerateShareableLinkIdResponse: + Response message for + [ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId][google.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId]. + + """ + # 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, + third_party_app_analytics_link_service.RegenerateShareableLinkIdRequest, + ): + request = third_party_app_analytics_link_service.RegenerateShareableLinkIdRequest( + request + ) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.regenerate_shareable_link_id + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("resource_name", request.resource_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) -> "ThirdPartyAppAnalyticsLinkServiceClient": + 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() + + +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__ = ("ThirdPartyAppAnalyticsLinkServiceClient",) diff --git a/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/README.rst b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/README.rst new file mode 100644 index 000000000..d7dfcd0b6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ThirdPartyAppAnalyticsLinkServiceTransport` is the ABC for all transports. +- public child `ThirdPartyAppAnalyticsLinkServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ThirdPartyAppAnalyticsLinkServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseThirdPartyAppAnalyticsLinkServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ThirdPartyAppAnalyticsLinkServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/__init__.py b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/__init__.py new file mode 100644 index 000000000..fa2924fc9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import ThirdPartyAppAnalyticsLinkServiceTransport +from .grpc import ThirdPartyAppAnalyticsLinkServiceGrpcTransport +from .grpc_asyncio import ThirdPartyAppAnalyticsLinkServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ThirdPartyAppAnalyticsLinkServiceTransport]] +_transport_registry["grpc"] = ThirdPartyAppAnalyticsLinkServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + ThirdPartyAppAnalyticsLinkServiceGrpcAsyncIOTransport +) + +__all__ = ( + "ThirdPartyAppAnalyticsLinkServiceTransport", + "ThirdPartyAppAnalyticsLinkServiceGrpcTransport", + "ThirdPartyAppAnalyticsLinkServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/base.py b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/base.py new file mode 100644 index 000000000..54f8d4e1d --- /dev/null +++ b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + third_party_app_analytics_link_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 ThirdPartyAppAnalyticsLinkServiceTransport(abc.ABC): + """Abstract transport class for ThirdPartyAppAnalyticsLinkService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.regenerate_shareable_link_id: gapic_v1.method.wrap_method( + self.regenerate_shareable_link_id, + 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 regenerate_shareable_link_id( + self, + ) -> Callable[ + [ + third_party_app_analytics_link_service.RegenerateShareableLinkIdRequest + ], + Union[ + third_party_app_analytics_link_service.RegenerateShareableLinkIdResponse, + Awaitable[ + third_party_app_analytics_link_service.RegenerateShareableLinkIdResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ThirdPartyAppAnalyticsLinkServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/grpc.py b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/grpc.py new file mode 100644 index 000000000..834921a66 --- /dev/null +++ b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/grpc.py @@ -0,0 +1,399 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + third_party_app_analytics_link_service, +) +from .base import ( + ThirdPartyAppAnalyticsLinkServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ThirdPartyAppAnalyticsLinkServiceGrpcTransport( + ThirdPartyAppAnalyticsLinkServiceTransport +): + """gRPC backend transport for ThirdPartyAppAnalyticsLinkService. + + This service allows management of links between Google Ads + and third party app analytics. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 regenerate_shareable_link_id( + self, + ) -> Callable[ + [ + third_party_app_analytics_link_service.RegenerateShareableLinkIdRequest + ], + third_party_app_analytics_link_service.RegenerateShareableLinkIdResponse, + ]: + r"""Return a callable for the regenerate shareable link id method over gRPC. + + Regenerate ThirdPartyAppAnalyticsLink.shareable_link_id that + should be provided to the third party when setting up app + analytics. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.RegenerateShareableLinkIdRequest], + ~.RegenerateShareableLinkIdResponse]: + 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 "regenerate_shareable_link_id" not in self._stubs: + self._stubs["regenerate_shareable_link_id"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService/RegenerateShareableLinkId", + request_serializer=third_party_app_analytics_link_service.RegenerateShareableLinkIdRequest.serialize, + response_deserializer=third_party_app_analytics_link_service.RegenerateShareableLinkIdResponse.deserialize, + ) + ) + return self._stubs["regenerate_shareable_link_id"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ThirdPartyAppAnalyticsLinkServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..640a48697 --- /dev/null +++ b/google/ads/googleads/v24/services/services/third_party_app_analytics_link_service/transports/grpc_asyncio.py @@ -0,0 +1,422 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + third_party_app_analytics_link_service, +) +from .base import ( + ThirdPartyAppAnalyticsLinkServiceTransport, + DEFAULT_CLIENT_INFO, +) + +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)}" + ) + + 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.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ThirdPartyAppAnalyticsLinkServiceGrpcAsyncIOTransport( + ThirdPartyAppAnalyticsLinkServiceTransport +): + """gRPC AsyncIO backend transport for ThirdPartyAppAnalyticsLinkService. + + This service allows management of links between Google Ads + and third party app analytics. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 regenerate_shareable_link_id( + self, + ) -> Callable[ + [ + third_party_app_analytics_link_service.RegenerateShareableLinkIdRequest + ], + Awaitable[ + third_party_app_analytics_link_service.RegenerateShareableLinkIdResponse + ], + ]: + r"""Return a callable for the regenerate shareable link id method over gRPC. + + Regenerate ThirdPartyAppAnalyticsLink.shareable_link_id that + should be provided to the third party when setting up app + analytics. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.RegenerateShareableLinkIdRequest], + Awaitable[~.RegenerateShareableLinkIdResponse]]: + 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 "regenerate_shareable_link_id" not in self._stubs: + self._stubs["regenerate_shareable_link_id"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService/RegenerateShareableLinkId", + request_serializer=third_party_app_analytics_link_service.RegenerateShareableLinkIdRequest.serialize, + response_deserializer=third_party_app_analytics_link_service.RegenerateShareableLinkIdResponse.deserialize, + ) + ) + return self._stubs["regenerate_shareable_link_id"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.regenerate_shareable_link_id: self._wrap_method( + self.regenerate_shareable_link_id, + 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" + + +__all__ = ("ThirdPartyAppAnalyticsLinkServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/__init__.py b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/__init__.py new file mode 100644 index 000000000..e5e0dec55 --- /dev/null +++ b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import TravelAssetSuggestionServiceClient +from .async_client import TravelAssetSuggestionServiceAsyncClient + +__all__ = ( + "TravelAssetSuggestionServiceClient", + "TravelAssetSuggestionServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/async_client.py b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/async_client.py new file mode 100644 index 000000000..74bee6991 --- /dev/null +++ b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/async_client.py @@ -0,0 +1,426 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + travel_asset_suggestion_service, +) +from .transports.base import ( + TravelAssetSuggestionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import TravelAssetSuggestionServiceClient + +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 TravelAssetSuggestionServiceAsyncClient: + """Service to retrieve Travel asset suggestions.""" + + _client: TravelAssetSuggestionServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = TravelAssetSuggestionServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + TravelAssetSuggestionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + TravelAssetSuggestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = TravelAssetSuggestionServiceClient._DEFAULT_UNIVERSE + + common_billing_account_path = staticmethod( + TravelAssetSuggestionServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + TravelAssetSuggestionServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + TravelAssetSuggestionServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + TravelAssetSuggestionServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + TravelAssetSuggestionServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + TravelAssetSuggestionServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + TravelAssetSuggestionServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + TravelAssetSuggestionServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + TravelAssetSuggestionServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + TravelAssetSuggestionServiceClient.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: + TravelAssetSuggestionServiceAsyncClient: The constructed client. + """ + return TravelAssetSuggestionServiceClient.from_service_account_info.__func__(TravelAssetSuggestionServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + TravelAssetSuggestionServiceAsyncClient: The constructed client. + """ + return TravelAssetSuggestionServiceClient.from_service_account_file.__func__(TravelAssetSuggestionServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return TravelAssetSuggestionServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> TravelAssetSuggestionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + TravelAssetSuggestionServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = TravelAssetSuggestionServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + TravelAssetSuggestionServiceTransport, + Callable[..., TravelAssetSuggestionServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the travel asset suggestion 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,TravelAssetSuggestionServiceTransport,Callable[..., TravelAssetSuggestionServiceTransport]]]): + 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 TravelAssetSuggestionServiceTransport 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 = TravelAssetSuggestionServiceClient( + 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.ads.googleads.v24.services.TravelAssetSuggestionServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.TravelAssetSuggestionService", + "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.ads.googleads.v24.services.TravelAssetSuggestionService", + "credentialsType": None, + } + ), + ) + + async def suggest_travel_assets( + self, + request: Optional[ + Union[ + travel_asset_suggestion_service.SuggestTravelAssetsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + language_option: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> travel_asset_suggestion_service.SuggestTravelAssetsResponse: + r"""Returns Travel Asset suggestions. Asset + suggestions are returned on a best-effort basis. There + are no guarantees that all possible asset types will be + returned for any given hotel property. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.SuggestTravelAssetsRequest, dict]]): + The request object. Request message for + [TravelAssetSuggestionService.SuggestTravelAssets][google.ads.googleads.v24.services.TravelAssetSuggestionService.SuggestTravelAssets]. + customer_id (:class:`str`): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + language_option (:class:`str`): + Required. The language specifications + in BCP 47 format (for example, en-US, + zh-CN, etc.) for the asset suggestions. + Text will be in this language. Usually + matches one of the campaign target + languages. + + This corresponds to the ``language_option`` 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.ads.googleads.v24.services.types.SuggestTravelAssetsResponse: + Response message for + [TravelAssetSuggestionService.SuggestTravelAssets][google.ads.googleads.v24.services.TravelAssetSuggestionService.SuggestTravelAssets]. + + """ + # 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 = [customer_id, language_option] + 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, travel_asset_suggestion_service.SuggestTravelAssetsRequest + ): + request = ( + travel_asset_suggestion_service.SuggestTravelAssetsRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if language_option is not None: + request.language_option = language_option + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.suggest_travel_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "TravelAssetSuggestionServiceAsyncClient": + 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__ = ("TravelAssetSuggestionServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/client.py b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/client.py new file mode 100644 index 000000000..8da6e4cde --- /dev/null +++ b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/client.py @@ -0,0 +1,887 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + travel_asset_suggestion_service, +) +from .transports.base import ( + TravelAssetSuggestionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import TravelAssetSuggestionServiceGrpcTransport +from .transports.grpc_asyncio import ( + TravelAssetSuggestionServiceGrpcAsyncIOTransport, +) + + +class TravelAssetSuggestionServiceClientMeta(type): + """Metaclass for the TravelAssetSuggestionService 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[TravelAssetSuggestionServiceTransport]] + _transport_registry["grpc"] = TravelAssetSuggestionServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + TravelAssetSuggestionServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[TravelAssetSuggestionServiceTransport]: + """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 TravelAssetSuggestionServiceClient( + metaclass=TravelAssetSuggestionServiceClientMeta +): + """Service to retrieve Travel asset suggestions.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + TravelAssetSuggestionServiceClient: 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: + TravelAssetSuggestionServiceClient: 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) -> TravelAssetSuggestionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + TravelAssetSuggestionServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @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 = ( + TravelAssetSuggestionServiceClient._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 = ( + TravelAssetSuggestionServiceClient._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 + ): + """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 = ( + TravelAssetSuggestionServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + TravelAssetSuggestionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = TravelAssetSuggestionServiceClient._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 = TravelAssetSuggestionServiceClient._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): + """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, + TravelAssetSuggestionServiceTransport, + Callable[..., TravelAssetSuggestionServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the travel asset suggestion 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,TravelAssetSuggestionServiceTransport,Callable[..., TravelAssetSuggestionServiceTransport]]]): + 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 TravelAssetSuggestionServiceTransport 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, + ) = TravelAssetSuggestionServiceClient._read_environment_variables() + self._client_cert_source = ( + TravelAssetSuggestionServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + TravelAssetSuggestionServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, TravelAssetSuggestionServiceTransport + ) + if transport_provided: + # transport is a TravelAssetSuggestionServiceTransport 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( + TravelAssetSuggestionServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or TravelAssetSuggestionServiceClient._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[TravelAssetSuggestionServiceTransport], + Callable[..., TravelAssetSuggestionServiceTransport], + ] = ( + TravelAssetSuggestionServiceClient.get_transport_class( + transport + ) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., TravelAssetSuggestionServiceTransport], + 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.ads.googleads.v24.services.TravelAssetSuggestionServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.TravelAssetSuggestionService", + "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.ads.googleads.v24.services.TravelAssetSuggestionService", + "credentialsType": None, + } + ), + ) + + def suggest_travel_assets( + self, + request: Optional[ + Union[ + travel_asset_suggestion_service.SuggestTravelAssetsRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + language_option: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> travel_asset_suggestion_service.SuggestTravelAssetsResponse: + r"""Returns Travel Asset suggestions. Asset + suggestions are returned on a best-effort basis. There + are no guarantees that all possible asset types will be + returned for any given hotel property. + + Args: + request (Union[google.ads.googleads.v24.services.types.SuggestTravelAssetsRequest, dict]): + The request object. Request message for + [TravelAssetSuggestionService.SuggestTravelAssets][google.ads.googleads.v24.services.TravelAssetSuggestionService.SuggestTravelAssets]. + customer_id (str): + Required. The ID of the customer. + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + language_option (str): + Required. The language specifications + in BCP 47 format (for example, en-US, + zh-CN, etc.) for the asset suggestions. + Text will be in this language. Usually + matches one of the campaign target + languages. + + This corresponds to the ``language_option`` 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.ads.googleads.v24.services.types.SuggestTravelAssetsResponse: + Response message for + [TravelAssetSuggestionService.SuggestTravelAssets][google.ads.googleads.v24.services.TravelAssetSuggestionService.SuggestTravelAssets]. + + """ + # 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 = [customer_id, language_option] + 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, travel_asset_suggestion_service.SuggestTravelAssetsRequest + ): + request = ( + travel_asset_suggestion_service.SuggestTravelAssetsRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if language_option is not None: + request.language_option = language_option + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.suggest_travel_assets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "TravelAssetSuggestionServiceClient": + 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() + + +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__ = ("TravelAssetSuggestionServiceClient",) diff --git a/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/README.rst b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/README.rst new file mode 100644 index 000000000..b3d6a4c98 --- /dev/null +++ b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`TravelAssetSuggestionServiceTransport` is the ABC for all transports. +- public child `TravelAssetSuggestionServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `TravelAssetSuggestionServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseTravelAssetSuggestionServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `TravelAssetSuggestionServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/__init__.py b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/__init__.py new file mode 100644 index 000000000..9aae0a904 --- /dev/null +++ b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import TravelAssetSuggestionServiceTransport +from .grpc import TravelAssetSuggestionServiceGrpcTransport +from .grpc_asyncio import TravelAssetSuggestionServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[TravelAssetSuggestionServiceTransport]] +_transport_registry["grpc"] = TravelAssetSuggestionServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + TravelAssetSuggestionServiceGrpcAsyncIOTransport +) + +__all__ = ( + "TravelAssetSuggestionServiceTransport", + "TravelAssetSuggestionServiceGrpcTransport", + "TravelAssetSuggestionServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/base.py b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/base.py new file mode 100644 index 000000000..5115ce23a --- /dev/null +++ b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + travel_asset_suggestion_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 TravelAssetSuggestionServiceTransport(abc.ABC): + """Abstract transport class for TravelAssetSuggestionService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.suggest_travel_assets: gapic_v1.method.wrap_method( + self.suggest_travel_assets, + 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 suggest_travel_assets( + self, + ) -> Callable[ + [travel_asset_suggestion_service.SuggestTravelAssetsRequest], + Union[ + travel_asset_suggestion_service.SuggestTravelAssetsResponse, + Awaitable[ + travel_asset_suggestion_service.SuggestTravelAssetsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("TravelAssetSuggestionServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/grpc.py b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/grpc.py new file mode 100644 index 000000000..060ddb6b6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/grpc.py @@ -0,0 +1,390 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + travel_asset_suggestion_service, +) +from .base import TravelAssetSuggestionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.TravelAssetSuggestionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.TravelAssetSuggestionService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class TravelAssetSuggestionServiceGrpcTransport( + TravelAssetSuggestionServiceTransport +): + """gRPC backend transport for TravelAssetSuggestionService. + + Service to retrieve Travel asset suggestions. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 suggest_travel_assets( + self, + ) -> Callable[ + [travel_asset_suggestion_service.SuggestTravelAssetsRequest], + travel_asset_suggestion_service.SuggestTravelAssetsResponse, + ]: + r"""Return a callable for the suggest travel assets method over gRPC. + + Returns Travel Asset suggestions. Asset + suggestions are returned on a best-effort basis. There + are no guarantees that all possible asset types will be + returned for any given hotel property. + + Returns: + Callable[[~.SuggestTravelAssetsRequest], + ~.SuggestTravelAssetsResponse]: + 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 "suggest_travel_assets" not in self._stubs: + self._stubs["suggest_travel_assets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.TravelAssetSuggestionService/SuggestTravelAssets", + request_serializer=travel_asset_suggestion_service.SuggestTravelAssetsRequest.serialize, + response_deserializer=travel_asset_suggestion_service.SuggestTravelAssetsResponse.deserialize, + ) + ) + return self._stubs["suggest_travel_assets"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("TravelAssetSuggestionServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..c02e2d8f1 --- /dev/null +++ b/google/ads/googleads/v24/services/services/travel_asset_suggestion_service/transports/grpc_asyncio.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + travel_asset_suggestion_service, +) +from .base import TravelAssetSuggestionServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.TravelAssetSuggestionService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.TravelAssetSuggestionService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class TravelAssetSuggestionServiceGrpcAsyncIOTransport( + TravelAssetSuggestionServiceTransport +): + """gRPC AsyncIO backend transport for TravelAssetSuggestionService. + + Service to retrieve Travel asset suggestions. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 suggest_travel_assets( + self, + ) -> Callable[ + [travel_asset_suggestion_service.SuggestTravelAssetsRequest], + Awaitable[travel_asset_suggestion_service.SuggestTravelAssetsResponse], + ]: + r"""Return a callable for the suggest travel assets method over gRPC. + + Returns Travel Asset suggestions. Asset + suggestions are returned on a best-effort basis. There + are no guarantees that all possible asset types will be + returned for any given hotel property. + + Returns: + Callable[[~.SuggestTravelAssetsRequest], + Awaitable[~.SuggestTravelAssetsResponse]]: + 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 "suggest_travel_assets" not in self._stubs: + self._stubs["suggest_travel_assets"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.TravelAssetSuggestionService/SuggestTravelAssets", + request_serializer=travel_asset_suggestion_service.SuggestTravelAssetsRequest.serialize, + response_deserializer=travel_asset_suggestion_service.SuggestTravelAssetsResponse.deserialize, + ) + ) + return self._stubs["suggest_travel_assets"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.suggest_travel_assets: self._wrap_method( + self.suggest_travel_assets, + 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" + + +__all__ = ("TravelAssetSuggestionServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/user_data_service/__init__.py b/google/ads/googleads/v24/services/services/user_data_service/__init__.py new file mode 100644 index 000000000..27e319f3c --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_data_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import UserDataServiceClient +from .async_client import UserDataServiceAsyncClient + +__all__ = ( + "UserDataServiceClient", + "UserDataServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/user_data_service/async_client.py b/google/ads/googleads/v24/services/services/user_data_service/async_client.py new file mode 100644 index 000000000..720e69a90 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_data_service/async_client.py @@ -0,0 +1,386 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import user_data_service +from .transports.base import UserDataServiceTransport, DEFAULT_CLIENT_INFO +from .client import UserDataServiceClient + +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 UserDataServiceAsyncClient: + """Service to manage user data uploads. + Any uploads made to a Customer Match list through this service + will be eligible for matching as per the customer matching + process. See + https://support.google.com/google-ads/answer/7474263. However, + the uploads made through this service will not be visible under + the 'Segment members' section for the Customer Match List in the + Google Ads UI. + """ + + _client: UserDataServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = UserDataServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = UserDataServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + UserDataServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = UserDataServiceClient._DEFAULT_UNIVERSE + + common_billing_account_path = staticmethod( + UserDataServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + UserDataServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(UserDataServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + UserDataServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + UserDataServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + UserDataServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + UserDataServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + UserDataServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + UserDataServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + UserDataServiceClient.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: + UserDataServiceAsyncClient: The constructed client. + """ + return UserDataServiceClient.from_service_account_info.__func__(UserDataServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + UserDataServiceAsyncClient: The constructed client. + """ + return UserDataServiceClient.from_service_account_file.__func__(UserDataServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return UserDataServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> UserDataServiceTransport: + """Returns the transport used by the client instance. + + Returns: + UserDataServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = UserDataServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + UserDataServiceTransport, + Callable[..., UserDataServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the user data 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,UserDataServiceTransport,Callable[..., UserDataServiceTransport]]]): + 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 UserDataServiceTransport 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 = UserDataServiceClient( + 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.ads.googleads.v24.services.UserDataServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.UserDataService", + "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.ads.googleads.v24.services.UserDataService", + "credentialsType": None, + } + ), + ) + + async def upload_user_data( + self, + request: Optional[ + Union[user_data_service.UploadUserDataRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> user_data_service.UploadUserDataResponse: + r"""Uploads the given user data. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `OfflineUserDataJobError <>`__ + `QuotaError <>`__ `RequestError <>`__ `UserDataError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.UploadUserDataRequest, dict]]): + The request object. Request message for + [UserDataService.UploadUserData][google.ads.googleads.v24.services.UserDataService.UploadUserData] + 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.googleads.v24.services.types.UploadUserDataResponse: + Response message for + [UserDataService.UploadUserData][google.ads.googleads.v24.services.UserDataService.UploadUserData] + Uploads made through this service will not be visible + under the 'Segment members' section for the Customer + Match List in the Google Ads UI. + + """ + # 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, user_data_service.UploadUserDataRequest): + request = user_data_service.UploadUserDataRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.upload_user_data + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "UserDataServiceAsyncClient": + 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__ = ("UserDataServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/user_data_service/client.py b/google/ads/googleads/v24/services/services/user_data_service/client.py new file mode 100644 index 000000000..18e464dc6 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_data_service/client.py @@ -0,0 +1,827 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import user_data_service +from .transports.base import UserDataServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import UserDataServiceGrpcTransport +from .transports.grpc_asyncio import UserDataServiceGrpcAsyncIOTransport + + +class UserDataServiceClientMeta(type): + """Metaclass for the UserDataService 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[UserDataServiceTransport]] + _transport_registry["grpc"] = UserDataServiceGrpcTransport + _transport_registry["grpc_asyncio"] = UserDataServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[UserDataServiceTransport]: + """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 UserDataServiceClient(metaclass=UserDataServiceClientMeta): + """Service to manage user data uploads. + Any uploads made to a Customer Match list through this service + will be eligible for matching as per the customer matching + process. See + https://support.google.com/google-ads/answer/7474263. However, + the uploads made through this service will not be visible under + the 'Segment members' section for the Customer Match List in the + Google Ads UI. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + UserDataServiceClient: 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: + UserDataServiceClient: 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) -> UserDataServiceTransport: + """Returns the transport used by the client instance. + + Returns: + UserDataServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @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 = UserDataServiceClient._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 = UserDataServiceClient._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 + ): + """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 = UserDataServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = UserDataServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + UserDataServiceClient._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 = UserDataServiceClient._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): + """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, + UserDataServiceTransport, + Callable[..., UserDataServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the user data 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,UserDataServiceTransport,Callable[..., UserDataServiceTransport]]]): + 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 UserDataServiceTransport 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, + ) = UserDataServiceClient._read_environment_variables() + self._client_cert_source = ( + UserDataServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = UserDataServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, UserDataServiceTransport) + if transport_provided: + # transport is a UserDataServiceTransport 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(UserDataServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or UserDataServiceClient._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[UserDataServiceTransport], + Callable[..., UserDataServiceTransport], + ] = ( + UserDataServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., UserDataServiceTransport], 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.ads.googleads.v24.services.UserDataServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.UserDataService", + "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.ads.googleads.v24.services.UserDataService", + "credentialsType": None, + } + ), + ) + + def upload_user_data( + self, + request: Optional[ + Union[user_data_service.UploadUserDataRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> user_data_service.UploadUserDataResponse: + r"""Uploads the given user data. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `OfflineUserDataJobError <>`__ + `QuotaError <>`__ `RequestError <>`__ `UserDataError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.UploadUserDataRequest, dict]): + The request object. Request message for + [UserDataService.UploadUserData][google.ads.googleads.v24.services.UserDataService.UploadUserData] + 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.googleads.v24.services.types.UploadUserDataResponse: + Response message for + [UserDataService.UploadUserData][google.ads.googleads.v24.services.UserDataService.UploadUserData] + Uploads made through this service will not be visible + under the 'Segment members' section for the Customer + Match List in the Google Ads UI. + + """ + # 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, user_data_service.UploadUserDataRequest): + request = user_data_service.UploadUserDataRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.upload_user_data] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "UserDataServiceClient": + 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() + + +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__ = ("UserDataServiceClient",) diff --git a/google/ads/googleads/v24/services/services/user_data_service/transports/README.rst b/google/ads/googleads/v24/services/services/user_data_service/transports/README.rst new file mode 100644 index 000000000..ca1247d84 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_data_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`UserDataServiceTransport` is the ABC for all transports. +- public child `UserDataServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `UserDataServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseUserDataServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `UserDataServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/user_data_service/transports/__init__.py b/google/ads/googleads/v24/services/services/user_data_service/transports/__init__.py new file mode 100644 index 000000000..6453922fd --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_data_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import UserDataServiceTransport +from .grpc import UserDataServiceGrpcTransport +from .grpc_asyncio import UserDataServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[UserDataServiceTransport]] +_transport_registry["grpc"] = UserDataServiceGrpcTransport +_transport_registry["grpc_asyncio"] = UserDataServiceGrpcAsyncIOTransport + +__all__ = ( + "UserDataServiceTransport", + "UserDataServiceGrpcTransport", + "UserDataServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/user_data_service/transports/base.py b/google/ads/googleads/v24/services/services/user_data_service/transports/base.py new file mode 100644 index 000000000..716cf35c4 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_data_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import user_data_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 UserDataServiceTransport(abc.ABC): + """Abstract transport class for UserDataService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.upload_user_data: gapic_v1.method.wrap_method( + self.upload_user_data, + 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 upload_user_data( + self, + ) -> Callable[ + [user_data_service.UploadUserDataRequest], + Union[ + user_data_service.UploadUserDataResponse, + Awaitable[user_data_service.UploadUserDataResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("UserDataServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/user_data_service/transports/grpc.py b/google/ads/googleads/v24/services/services/user_data_service/transports/grpc.py new file mode 100644 index 000000000..7e3181463 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_data_service/transports/grpc.py @@ -0,0 +1,394 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import user_data_service +from .base import UserDataServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.UserDataService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.UserDataService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class UserDataServiceGrpcTransport(UserDataServiceTransport): + """gRPC backend transport for UserDataService. + + Service to manage user data uploads. + Any uploads made to a Customer Match list through this service + will be eligible for matching as per the customer matching + process. See + https://support.google.com/google-ads/answer/7474263. However, + the uploads made through this service will not be visible under + the 'Segment members' section for the Customer Match List in the + Google Ads UI. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 upload_user_data( + self, + ) -> Callable[ + [user_data_service.UploadUserDataRequest], + user_data_service.UploadUserDataResponse, + ]: + r"""Return a callable for the upload user data method over gRPC. + + Uploads the given user data. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `OfflineUserDataJobError <>`__ + `QuotaError <>`__ `RequestError <>`__ `UserDataError <>`__ + + Returns: + Callable[[~.UploadUserDataRequest], + ~.UploadUserDataResponse]: + 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 "upload_user_data" not in self._stubs: + self._stubs["upload_user_data"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.UserDataService/UploadUserData", + request_serializer=user_data_service.UploadUserDataRequest.serialize, + response_deserializer=user_data_service.UploadUserDataResponse.deserialize, + ) + return self._stubs["upload_user_data"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("UserDataServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/user_data_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/user_data_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..a9592cdc5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_data_service/transports/grpc_asyncio.py @@ -0,0 +1,415 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import user_data_service +from .base import UserDataServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.UserDataService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.UserDataService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class UserDataServiceGrpcAsyncIOTransport(UserDataServiceTransport): + """gRPC AsyncIO backend transport for UserDataService. + + Service to manage user data uploads. + Any uploads made to a Customer Match list through this service + will be eligible for matching as per the customer matching + process. See + https://support.google.com/google-ads/answer/7474263. However, + the uploads made through this service will not be visible under + the 'Segment members' section for the Customer Match List in the + Google Ads UI. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 upload_user_data( + self, + ) -> Callable[ + [user_data_service.UploadUserDataRequest], + Awaitable[user_data_service.UploadUserDataResponse], + ]: + r"""Return a callable for the upload user data method over gRPC. + + Uploads the given user data. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `FieldError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `OfflineUserDataJobError <>`__ + `QuotaError <>`__ `RequestError <>`__ `UserDataError <>`__ + + Returns: + Callable[[~.UploadUserDataRequest], + Awaitable[~.UploadUserDataResponse]]: + 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 "upload_user_data" not in self._stubs: + self._stubs["upload_user_data"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.UserDataService/UploadUserData", + request_serializer=user_data_service.UploadUserDataRequest.serialize, + response_deserializer=user_data_service.UploadUserDataResponse.deserialize, + ) + return self._stubs["upload_user_data"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.upload_user_data: self._wrap_method( + self.upload_user_data, + 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" + + +__all__ = ("UserDataServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/user_list_customer_type_service/__init__.py b/google/ads/googleads/v24/services/services/user_list_customer_type_service/__init__.py new file mode 100644 index 000000000..a2595a5f3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_customer_type_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import UserListCustomerTypeServiceClient +from .async_client import UserListCustomerTypeServiceAsyncClient + +__all__ = ( + "UserListCustomerTypeServiceClient", + "UserListCustomerTypeServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/user_list_customer_type_service/async_client.py b/google/ads/googleads/v24/services/services/user_list_customer_type_service/async_client.py new file mode 100644 index 000000000..71b4643f9 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_customer_type_service/async_client.py @@ -0,0 +1,445 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import ( + user_list_customer_type_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + UserListCustomerTypeServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import UserListCustomerTypeServiceClient + +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 UserListCustomerTypeServiceAsyncClient: + """Service to manage user list customer types.""" + + _client: UserListCustomerTypeServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = UserListCustomerTypeServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + UserListCustomerTypeServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + UserListCustomerTypeServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = UserListCustomerTypeServiceClient._DEFAULT_UNIVERSE + + user_list_path = staticmethod( + UserListCustomerTypeServiceClient.user_list_path + ) + parse_user_list_path = staticmethod( + UserListCustomerTypeServiceClient.parse_user_list_path + ) + user_list_customer_type_path = staticmethod( + UserListCustomerTypeServiceClient.user_list_customer_type_path + ) + parse_user_list_customer_type_path = staticmethod( + UserListCustomerTypeServiceClient.parse_user_list_customer_type_path + ) + common_billing_account_path = staticmethod( + UserListCustomerTypeServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + UserListCustomerTypeServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + UserListCustomerTypeServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + UserListCustomerTypeServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + UserListCustomerTypeServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + UserListCustomerTypeServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + UserListCustomerTypeServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + UserListCustomerTypeServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + UserListCustomerTypeServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + UserListCustomerTypeServiceClient.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: + UserListCustomerTypeServiceAsyncClient: The constructed client. + """ + return UserListCustomerTypeServiceClient.from_service_account_info.__func__(UserListCustomerTypeServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + UserListCustomerTypeServiceAsyncClient: The constructed client. + """ + return UserListCustomerTypeServiceClient.from_service_account_file.__func__(UserListCustomerTypeServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return UserListCustomerTypeServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> UserListCustomerTypeServiceTransport: + """Returns the transport used by the client instance. + + Returns: + UserListCustomerTypeServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = UserListCustomerTypeServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + UserListCustomerTypeServiceTransport, + Callable[..., UserListCustomerTypeServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the user list customer type 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,UserListCustomerTypeServiceTransport,Callable[..., UserListCustomerTypeServiceTransport]]]): + 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 UserListCustomerTypeServiceTransport 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 = UserListCustomerTypeServiceClient( + 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.ads.googleads.v24.services.UserListCustomerTypeServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.UserListCustomerTypeService", + "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.ads.googleads.v24.services.UserListCustomerTypeService", + "credentialsType": None, + } + ), + ) + + async def mutate_user_list_customer_types( + self, + request: Optional[ + Union[ + user_list_customer_type_service.MutateUserListCustomerTypesRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + user_list_customer_type_service.UserListCustomerTypeOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> user_list_customer_type_service.MutateUserListCustomerTypesResponse: + r"""Attach or remove user list customer types. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `UserListCustomerTypeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateUserListCustomerTypesRequest, dict]]): + The request object. Request message for + [UserListCustomerTypeService.MutateUserListCustomerTypes][google.ads.googleads.v24.services.UserListCustomerTypeService.MutateUserListCustomerTypes]. + customer_id (:class:`str`): + Required. The ID of the customer + whose user list customer types are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.UserListCustomerTypeOperation]`): + Required. The list of operations to + perform on the user list customer types. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateUserListCustomerTypesResponse: + Response message for a user list + customer type mutate. + + """ + # 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 = [customer_id, operations] + 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, + user_list_customer_type_service.MutateUserListCustomerTypesRequest, + ): + request = user_list_customer_type_service.MutateUserListCustomerTypesRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_user_list_customer_types + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "UserListCustomerTypeServiceAsyncClient": + 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__ = ("UserListCustomerTypeServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/user_list_customer_type_service/client.py b/google/ads/googleads/v24/services/services/user_list_customer_type_service/client.py new file mode 100644 index 000000000..c781ed32f --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_customer_type_service/client.py @@ -0,0 +1,944 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import ( + user_list_customer_type_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + UserListCustomerTypeServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import UserListCustomerTypeServiceGrpcTransport +from .transports.grpc_asyncio import ( + UserListCustomerTypeServiceGrpcAsyncIOTransport, +) + + +class UserListCustomerTypeServiceClientMeta(type): + """Metaclass for the UserListCustomerTypeService 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[UserListCustomerTypeServiceTransport]] + _transport_registry["grpc"] = UserListCustomerTypeServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + UserListCustomerTypeServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[UserListCustomerTypeServiceTransport]: + """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 UserListCustomerTypeServiceClient( + metaclass=UserListCustomerTypeServiceClientMeta +): + """Service to manage user list customer types.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + UserListCustomerTypeServiceClient: 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: + UserListCustomerTypeServiceClient: 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) -> UserListCustomerTypeServiceTransport: + """Returns the transport used by the client instance. + + Returns: + UserListCustomerTypeServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def user_list_path( + customer_id: str, + user_list_id: str, + ) -> str: + """Returns a fully-qualified user_list string.""" + return "customers/{customer_id}/userLists/{user_list_id}".format( + customer_id=customer_id, + user_list_id=user_list_id, + ) + + @staticmethod + def parse_user_list_path(path: str) -> Dict[str, str]: + """Parses a user_list path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/userLists/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def user_list_customer_type_path( + customer_id: str, + user_list_id: str, + semantic_label: str, + ) -> str: + """Returns a fully-qualified user_list_customer_type string.""" + return "customers/{customer_id}/userListCustomerTypes/{user_list_id}~{semantic_label}".format( + customer_id=customer_id, + user_list_id=user_list_id, + semantic_label=semantic_label, + ) + + @staticmethod + def parse_user_list_customer_type_path(path: str) -> Dict[str, str]: + """Parses a user_list_customer_type path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/userListCustomerTypes/(?P.+?)~(?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 = ( + UserListCustomerTypeServiceClient._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 = ( + UserListCustomerTypeServiceClient._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 + ): + """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 = ( + UserListCustomerTypeServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ( + UserListCustomerTypeServiceClient.DEFAULT_MTLS_ENDPOINT + ) + else: + api_endpoint = UserListCustomerTypeServiceClient._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 = UserListCustomerTypeServiceClient._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): + """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, + UserListCustomerTypeServiceTransport, + Callable[..., UserListCustomerTypeServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the user list customer type 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,UserListCustomerTypeServiceTransport,Callable[..., UserListCustomerTypeServiceTransport]]]): + 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 UserListCustomerTypeServiceTransport 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, + ) = UserListCustomerTypeServiceClient._read_environment_variables() + self._client_cert_source = ( + UserListCustomerTypeServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + UserListCustomerTypeServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, UserListCustomerTypeServiceTransport + ) + if transport_provided: + # transport is a UserListCustomerTypeServiceTransport 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( + UserListCustomerTypeServiceTransport, transport + ) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or UserListCustomerTypeServiceClient._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[UserListCustomerTypeServiceTransport], + Callable[..., UserListCustomerTypeServiceTransport], + ] = ( + UserListCustomerTypeServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., UserListCustomerTypeServiceTransport], + 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.ads.googleads.v24.services.UserListCustomerTypeServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.UserListCustomerTypeService", + "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.ads.googleads.v24.services.UserListCustomerTypeService", + "credentialsType": None, + } + ), + ) + + def mutate_user_list_customer_types( + self, + request: Optional[ + Union[ + user_list_customer_type_service.MutateUserListCustomerTypesRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + user_list_customer_type_service.UserListCustomerTypeOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> user_list_customer_type_service.MutateUserListCustomerTypesResponse: + r"""Attach or remove user list customer types. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `UserListCustomerTypeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateUserListCustomerTypesRequest, dict]): + The request object. Request message for + [UserListCustomerTypeService.MutateUserListCustomerTypes][google.ads.googleads.v24.services.UserListCustomerTypeService.MutateUserListCustomerTypes]. + customer_id (str): + Required. The ID of the customer + whose user list customer types are being + modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.UserListCustomerTypeOperation]): + Required. The list of operations to + perform on the user list customer types. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateUserListCustomerTypesResponse: + Response message for a user list + customer type mutate. + + """ + # 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 = [customer_id, operations] + 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, + user_list_customer_type_service.MutateUserListCustomerTypesRequest, + ): + request = user_list_customer_type_service.MutateUserListCustomerTypesRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_user_list_customer_types + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "UserListCustomerTypeServiceClient": + 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() + + +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__ = ("UserListCustomerTypeServiceClient",) diff --git a/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/README.rst b/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/README.rst new file mode 100644 index 000000000..4eb7d08a8 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`UserListCustomerTypeServiceTransport` is the ABC for all transports. +- public child `UserListCustomerTypeServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `UserListCustomerTypeServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseUserListCustomerTypeServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `UserListCustomerTypeServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/__init__.py b/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/__init__.py new file mode 100644 index 000000000..3f37186cf --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import UserListCustomerTypeServiceTransport +from .grpc import UserListCustomerTypeServiceGrpcTransport +from .grpc_asyncio import UserListCustomerTypeServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[UserListCustomerTypeServiceTransport]] +_transport_registry["grpc"] = UserListCustomerTypeServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + UserListCustomerTypeServiceGrpcAsyncIOTransport +) + +__all__ = ( + "UserListCustomerTypeServiceTransport", + "UserListCustomerTypeServiceGrpcTransport", + "UserListCustomerTypeServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/base.py b/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/base.py new file mode 100644 index 000000000..982b08fbb --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import ( + user_list_customer_type_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 UserListCustomerTypeServiceTransport(abc.ABC): + """Abstract transport class for UserListCustomerTypeService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_user_list_customer_types: gapic_v1.method.wrap_method( + self.mutate_user_list_customer_types, + 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 mutate_user_list_customer_types( + self, + ) -> Callable[ + [user_list_customer_type_service.MutateUserListCustomerTypesRequest], + Union[ + user_list_customer_type_service.MutateUserListCustomerTypesResponse, + Awaitable[ + user_list_customer_type_service.MutateUserListCustomerTypesResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("UserListCustomerTypeServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/grpc.py b/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/grpc.py new file mode 100644 index 000000000..8cced3671 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/grpc.py @@ -0,0 +1,394 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import ( + user_list_customer_type_service, +) +from .base import UserListCustomerTypeServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.UserListCustomerTypeService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.UserListCustomerTypeService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class UserListCustomerTypeServiceGrpcTransport( + UserListCustomerTypeServiceTransport +): + """gRPC backend transport for UserListCustomerTypeService. + + Service to manage user list customer types. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_user_list_customer_types( + self, + ) -> Callable[ + [user_list_customer_type_service.MutateUserListCustomerTypesRequest], + user_list_customer_type_service.MutateUserListCustomerTypesResponse, + ]: + r"""Return a callable for the mutate user list customer + types method over gRPC. + + Attach or remove user list customer types. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `UserListCustomerTypeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateUserListCustomerTypesRequest], + ~.MutateUserListCustomerTypesResponse]: + 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 "mutate_user_list_customer_types" not in self._stubs: + self._stubs["mutate_user_list_customer_types"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.UserListCustomerTypeService/MutateUserListCustomerTypes", + request_serializer=user_list_customer_type_service.MutateUserListCustomerTypesRequest.serialize, + response_deserializer=user_list_customer_type_service.MutateUserListCustomerTypesResponse.deserialize, + ) + ) + return self._stubs["mutate_user_list_customer_types"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("UserListCustomerTypeServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..11c0c1877 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_customer_type_service/transports/grpc_asyncio.py @@ -0,0 +1,417 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import ( + user_list_customer_type_service, +) +from .base import UserListCustomerTypeServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.UserListCustomerTypeService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.UserListCustomerTypeService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class UserListCustomerTypeServiceGrpcAsyncIOTransport( + UserListCustomerTypeServiceTransport +): + """gRPC AsyncIO backend transport for UserListCustomerTypeService. + + Service to manage user list customer types. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_user_list_customer_types( + self, + ) -> Callable[ + [user_list_customer_type_service.MutateUserListCustomerTypesRequest], + Awaitable[ + user_list_customer_type_service.MutateUserListCustomerTypesResponse + ], + ]: + r"""Return a callable for the mutate user list customer + types method over gRPC. + + Attach or remove user list customer types. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `UserListCustomerTypeError <>`__ + `HeaderError <>`__ `InternalError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateUserListCustomerTypesRequest], + Awaitable[~.MutateUserListCustomerTypesResponse]]: + 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 "mutate_user_list_customer_types" not in self._stubs: + self._stubs["mutate_user_list_customer_types"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.UserListCustomerTypeService/MutateUserListCustomerTypes", + request_serializer=user_list_customer_type_service.MutateUserListCustomerTypesRequest.serialize, + response_deserializer=user_list_customer_type_service.MutateUserListCustomerTypesResponse.deserialize, + ) + ) + return self._stubs["mutate_user_list_customer_types"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_user_list_customer_types: self._wrap_method( + self.mutate_user_list_customer_types, + 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" + + +__all__ = ("UserListCustomerTypeServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/user_list_service/__init__.py b/google/ads/googleads/v24/services/services/user_list_service/__init__.py new file mode 100644 index 000000000..ef939340c --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import UserListServiceClient +from .async_client import UserListServiceAsyncClient + +__all__ = ( + "UserListServiceClient", + "UserListServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/user_list_service/async_client.py b/google/ads/googleads/v24/services/services/user_list_service/async_client.py new file mode 100644 index 000000000..43e6e6ea5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_service/async_client.py @@ -0,0 +1,421 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, MutableSequence, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.services.types import user_list_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import UserListServiceTransport, DEFAULT_CLIENT_INFO +from .client import UserListServiceClient + +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 UserListServiceAsyncClient: + """Service to manage user lists.""" + + _client: UserListServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = UserListServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = UserListServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + UserListServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = UserListServiceClient._DEFAULT_UNIVERSE + + user_list_path = staticmethod(UserListServiceClient.user_list_path) + parse_user_list_path = staticmethod( + UserListServiceClient.parse_user_list_path + ) + common_billing_account_path = staticmethod( + UserListServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + UserListServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(UserListServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + UserListServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + UserListServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + UserListServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + UserListServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + UserListServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + UserListServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + UserListServiceClient.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: + UserListServiceAsyncClient: The constructed client. + """ + return UserListServiceClient.from_service_account_info.__func__(UserListServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + UserListServiceAsyncClient: The constructed client. + """ + return UserListServiceClient.from_service_account_file.__func__(UserListServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return UserListServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> UserListServiceTransport: + """Returns the transport used by the client instance. + + Returns: + UserListServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = UserListServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + UserListServiceTransport, + Callable[..., UserListServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the user list 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,UserListServiceTransport,Callable[..., UserListServiceTransport]]]): + 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 UserListServiceTransport 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 = UserListServiceClient( + 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.ads.googleads.v24.services.UserListServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.UserListService", + "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.ads.googleads.v24.services.UserListService", + "credentialsType": None, + } + ), + ) + + async def mutate_user_lists( + self, + request: Optional[ + Union[user_list_service.MutateUserListsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[user_list_service.UserListOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> user_list_service.MutateUserListsResponse: + r"""Creates or updates user lists. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotAllowlistedError <>`__ `NotEmptyError <>`__ + `OperationAccessDeniedError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ `UserListError <>`__ + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.MutateUserListsRequest, dict]]): + The request object. Request message for + [UserListService.MutateUserLists][google.ads.googleads.v24.services.UserListService.MutateUserLists]. + customer_id (:class:`str`): + Required. The ID of the customer + whose user lists are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (:class:`MutableSequence[google.ads.googleads.v24.services.types.UserListOperation]`): + Required. The list of operations to + perform on individual user lists. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateUserListsResponse: + Response message for user list + mutate. + + """ + # 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 = [customer_id, operations] + 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, user_list_service.MutateUserListsRequest): + request = user_list_service.MutateUserListsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations: + request.operations.extend(operations) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.mutate_user_lists + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "UserListServiceAsyncClient": + 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__ = ("UserListServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/user_list_service/client.py b/google/ads/googleads/v24/services/services/user_list_service/client.py new file mode 100644 index 000000000..0d9024ac3 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_service/client.py @@ -0,0 +1,889 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.services.types import user_list_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import UserListServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import UserListServiceGrpcTransport +from .transports.grpc_asyncio import UserListServiceGrpcAsyncIOTransport + + +class UserListServiceClientMeta(type): + """Metaclass for the UserListService 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[UserListServiceTransport]] + _transport_registry["grpc"] = UserListServiceGrpcTransport + _transport_registry["grpc_asyncio"] = UserListServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[UserListServiceTransport]: + """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 UserListServiceClient(metaclass=UserListServiceClientMeta): + """Service to manage user lists.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + UserListServiceClient: 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: + UserListServiceClient: 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) -> UserListServiceTransport: + """Returns the transport used by the client instance. + + Returns: + UserListServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def user_list_path( + customer_id: str, + user_list_id: str, + ) -> str: + """Returns a fully-qualified user_list string.""" + return "customers/{customer_id}/userLists/{user_list_id}".format( + customer_id=customer_id, + user_list_id=user_list_id, + ) + + @staticmethod + def parse_user_list_path(path: str) -> Dict[str, str]: + """Parses a user_list path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/userLists/(?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 = UserListServiceClient._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 = UserListServiceClient._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 + ): + """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 = UserListServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = UserListServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + UserListServiceClient._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 = UserListServiceClient._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): + """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, + UserListServiceTransport, + Callable[..., UserListServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the user list 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,UserListServiceTransport,Callable[..., UserListServiceTransport]]]): + 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 UserListServiceTransport 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, + ) = UserListServiceClient._read_environment_variables() + self._client_cert_source = ( + UserListServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = UserListServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, UserListServiceTransport) + if transport_provided: + # transport is a UserListServiceTransport 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(UserListServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or UserListServiceClient._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[UserListServiceTransport], + Callable[..., UserListServiceTransport], + ] = ( + UserListServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., UserListServiceTransport], 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.ads.googleads.v24.services.UserListServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.UserListService", + "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.ads.googleads.v24.services.UserListService", + "credentialsType": None, + } + ), + ) + + def mutate_user_lists( + self, + request: Optional[ + Union[user_list_service.MutateUserListsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[user_list_service.UserListOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> user_list_service.MutateUserListsResponse: + r"""Creates or updates user lists. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotAllowlistedError <>`__ `NotEmptyError <>`__ + `OperationAccessDeniedError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ `UserListError <>`__ + + Args: + request (Union[google.ads.googleads.v24.services.types.MutateUserListsRequest, dict]): + The request object. Request message for + [UserListService.MutateUserLists][google.ads.googleads.v24.services.UserListService.MutateUserLists]. + customer_id (str): + Required. The ID of the customer + whose user lists are being modified. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + operations (MutableSequence[google.ads.googleads.v24.services.types.UserListOperation]): + Required. The list of operations to + perform on individual user lists. + + This corresponds to the ``operations`` 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.ads.googleads.v24.services.types.MutateUserListsResponse: + Response message for user list + mutate. + + """ + # 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 = [customer_id, operations] + 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, user_list_service.MutateUserListsRequest): + request = user_list_service.MutateUserListsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if operations is not None: + request.operations = operations + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.mutate_user_lists + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "UserListServiceClient": + 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() + + +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__ = ("UserListServiceClient",) diff --git a/google/ads/googleads/v24/services/services/user_list_service/transports/README.rst b/google/ads/googleads/v24/services/services/user_list_service/transports/README.rst new file mode 100644 index 000000000..cf4cc6775 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`UserListServiceTransport` is the ABC for all transports. +- public child `UserListServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `UserListServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseUserListServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `UserListServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/user_list_service/transports/__init__.py b/google/ads/googleads/v24/services/services/user_list_service/transports/__init__.py new file mode 100644 index 000000000..e732ccc16 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import UserListServiceTransport +from .grpc import UserListServiceGrpcTransport +from .grpc_asyncio import UserListServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[UserListServiceTransport]] +_transport_registry["grpc"] = UserListServiceGrpcTransport +_transport_registry["grpc_asyncio"] = UserListServiceGrpcAsyncIOTransport + +__all__ = ( + "UserListServiceTransport", + "UserListServiceGrpcTransport", + "UserListServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/user_list_service/transports/base.py b/google/ads/googleads/v24/services/services/user_list_service/transports/base.py new file mode 100644 index 000000000..d58da953c --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import user_list_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 UserListServiceTransport(abc.ABC): + """Abstract transport class for UserListService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_user_lists: gapic_v1.method.wrap_method( + self.mutate_user_lists, + 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 mutate_user_lists( + self, + ) -> Callable[ + [user_list_service.MutateUserListsRequest], + Union[ + user_list_service.MutateUserListsResponse, + Awaitable[user_list_service.MutateUserListsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("UserListServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/user_list_service/transports/grpc.py b/google/ads/googleads/v24/services/services/user_list_service/transports/grpc.py new file mode 100644 index 000000000..62b2ff1b2 --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_service/transports/grpc.py @@ -0,0 +1,391 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import user_list_service +from .base import UserListServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.UserListService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.UserListService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class UserListServiceGrpcTransport(UserListServiceTransport): + """gRPC backend transport for UserListService. + + Service to manage user lists. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 mutate_user_lists( + self, + ) -> Callable[ + [user_list_service.MutateUserListsRequest], + user_list_service.MutateUserListsResponse, + ]: + r"""Return a callable for the mutate user lists method over gRPC. + + Creates or updates user lists. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotAllowlistedError <>`__ `NotEmptyError <>`__ + `OperationAccessDeniedError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ `UserListError <>`__ + + Returns: + Callable[[~.MutateUserListsRequest], + ~.MutateUserListsResponse]: + 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 "mutate_user_lists" not in self._stubs: + self._stubs["mutate_user_lists"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.UserListService/MutateUserLists", + request_serializer=user_list_service.MutateUserListsRequest.serialize, + response_deserializer=user_list_service.MutateUserListsResponse.deserialize, + ) + return self._stubs["mutate_user_lists"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("UserListServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/user_list_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/user_list_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..716a62b4a --- /dev/null +++ b/google/ads/googleads/v24/services/services/user_list_service/transports/grpc_asyncio.py @@ -0,0 +1,412 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import user_list_service +from .base import UserListServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.UserListService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.UserListService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class UserListServiceGrpcAsyncIOTransport(UserListServiceTransport): + """gRPC AsyncIO backend transport for UserListService. + + Service to manage user lists. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 mutate_user_lists( + self, + ) -> Callable[ + [user_list_service.MutateUserListsRequest], + Awaitable[user_list_service.MutateUserListsResponse], + ]: + r"""Return a callable for the mutate user lists method over gRPC. + + Creates or updates user lists. Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `InternalError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotAllowlistedError <>`__ `NotEmptyError <>`__ + `OperationAccessDeniedError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ `UserListError <>`__ + + Returns: + Callable[[~.MutateUserListsRequest], + Awaitable[~.MutateUserListsResponse]]: + 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 "mutate_user_lists" not in self._stubs: + self._stubs["mutate_user_lists"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.UserListService/MutateUserLists", + request_serializer=user_list_service.MutateUserListsRequest.serialize, + response_deserializer=user_list_service.MutateUserListsResponse.deserialize, + ) + return self._stubs["mutate_user_lists"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.mutate_user_lists: self._wrap_method( + self.mutate_user_lists, + 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" + + +__all__ = ("UserListServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/you_tube_video_upload_service/__init__.py b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/__init__.py new file mode 100644 index 000000000..18d94eb38 --- /dev/null +++ b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .client import YouTubeVideoUploadServiceClient +from .async_client import YouTubeVideoUploadServiceAsyncClient + +__all__ = ( + "YouTubeVideoUploadServiceClient", + "YouTubeVideoUploadServiceAsyncClient", +) diff --git a/google/ads/googleads/v24/services/services/you_tube_video_upload_service/async_client.py b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/async_client.py new file mode 100644 index 000000000..210cf146e --- /dev/null +++ b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/async_client.py @@ -0,0 +1,624 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 +from typing import Callable, Optional, BinaryIO, Sequence, Tuple, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +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.ads.googleads.v24.resources.types import youtube_video_upload +from google.ads.googleads.v24.services.types import youtube_video_upload_service +from google.protobuf import field_mask_pb2 # type: ignore +from .transports.base import ( + YouTubeVideoUploadServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .client import YouTubeVideoUploadServiceClient + +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 YouTubeVideoUploadServiceAsyncClient: + """Service to manage YouTube video uploads.""" + + _client: YouTubeVideoUploadServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = YouTubeVideoUploadServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ( + YouTubeVideoUploadServiceClient.DEFAULT_MTLS_ENDPOINT + ) + _DEFAULT_ENDPOINT_TEMPLATE = ( + YouTubeVideoUploadServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = YouTubeVideoUploadServiceClient._DEFAULT_UNIVERSE + + you_tube_video_upload_path = staticmethod( + YouTubeVideoUploadServiceClient.you_tube_video_upload_path + ) + parse_you_tube_video_upload_path = staticmethod( + YouTubeVideoUploadServiceClient.parse_you_tube_video_upload_path + ) + common_billing_account_path = staticmethod( + YouTubeVideoUploadServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + YouTubeVideoUploadServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + YouTubeVideoUploadServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + YouTubeVideoUploadServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + YouTubeVideoUploadServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + YouTubeVideoUploadServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + YouTubeVideoUploadServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + YouTubeVideoUploadServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + YouTubeVideoUploadServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + YouTubeVideoUploadServiceClient.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: + YouTubeVideoUploadServiceAsyncClient: The constructed client. + """ + return YouTubeVideoUploadServiceClient.from_service_account_info.__func__(YouTubeVideoUploadServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + YouTubeVideoUploadServiceAsyncClient: The constructed client. + """ + return YouTubeVideoUploadServiceClient.from_service_account_file.__func__(YouTubeVideoUploadServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return YouTubeVideoUploadServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> YouTubeVideoUploadServiceTransport: + """Returns the transport used by the client instance. + + Returns: + YouTubeVideoUploadServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = YouTubeVideoUploadServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + developer_token: Optional[str] = None, + login_customer_id: Optional[str] = None, + linked_customer_id: Optional[str] = None, + use_cloud_org_for_api_access: bool = False, + transport: Optional[ + Union[ + str, + YouTubeVideoUploadServiceTransport, + Callable[..., YouTubeVideoUploadServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the you tube video upload 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. + developer_token (Optional[str]): The developer token to use for the + resumable upload transport. This will be used by the resumable upload methods + (create_you_tube_video_upload) ONLY! + login_customer_id (Optional[str]): The login customer ID to use for + the resumable upload transport. This will be used by the resumable upload methods + (create_you_tube_video_upload) ONLY! + linked_customer_id (Optional[str]): The linked customer ID to use for + the resumable upload transport. This will be used by the resumable upload methods + (create_you_tube_video_upload) ONLY! + use_cloud_org_for_api_access (bool): Whether to use the cloud org for + API access for the resumable upload transport. This will be used by the resumable upload methods + (create_you_tube_video_upload) ONLY! + transport (Optional[Union[str,YouTubeVideoUploadServiceTransport,Callable[..., YouTubeVideoUploadServiceTransport]]]): + 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 YouTubeVideoUploadServiceTransport 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 = YouTubeVideoUploadServiceClient( + credentials=credentials, + developer_token=developer_token, + login_customer_id=login_customer_id, + linked_customer_id=linked_customer_id, + use_cloud_org_for_api_access=use_cloud_org_for_api_access, + 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.ads.googleads.v24.services.YouTubeVideoUploadServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.YouTubeVideoUploadService", + "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.ads.googleads.v24.services.YouTubeVideoUploadService", + "credentialsType": None, + } + ), + ) + + async def create_you_tube_video_upload( + self, + request: Optional[ + Union[ + youtube_video_upload_service.CreateYouTubeVideoUploadRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + you_tube_video_upload: Optional[ + youtube_video_upload.YouTubeVideoUpload + ] = None, + stream: BinaryIO, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> youtube_video_upload_service.CreateYouTubeVideoUploadResponse: + r"""Uploads a video to Google-managed or advertiser owned + (brand) YouTube channel. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.CreateYouTubeVideoUploadRequest, dict]]): + The request object. Request message for + [YouTubeVideoUploadService.CreateYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.CreateYouTubeVideoUpload]. + customer_id (:class:`str`): + Required. The customer ID requesting + the upload. Required. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + you_tube_video_upload (:class:`google.ads.googleads.v24.resources.types.YouTubeVideoUpload`): + Required. The initial details of the + video to upload. Required. + + This corresponds to the ``you_tube_video_upload`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + stream (BinaryIO): + The stream to upload. + 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.googleads.v24.services.types.CreateYouTubeVideoUploadResponse: + Response message for + [YouTubeVideoUploadService.CreateYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.CreateYouTubeVideoUpload]. + + """ + raise NotImplementedError( + "Resumable upload is not yet supported in the async client." + ) + + async def update_you_tube_video_upload( + self, + request: Optional[ + Union[ + youtube_video_upload_service.UpdateYouTubeVideoUploadRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + you_tube_video_upload: Optional[ + youtube_video_upload.YouTubeVideoUpload + ] = 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]]] = (), + ) -> youtube_video_upload_service.UpdateYouTubeVideoUploadResponse: + r"""Updates YouTube video's metadata, but only for videos + uploaded using this API. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.UpdateYouTubeVideoUploadRequest, dict]]): + The request object. Request message for + [YouTubeVideoUploadService.UpdateYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.UpdateYouTubeVideoUpload]. + customer_id (:class:`str`): + Required. The customer ID requesting + the YouTube video upload update. + Required. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + you_tube_video_upload (:class:`google.ads.googleads.v24.resources.types.YouTubeVideoUpload`): + Required. The YouTube video upload + resource to be updated. It's expected to + have a valid resource name. Required. + + This corresponds to the ``you_tube_video_upload`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): + Required. FieldMask that determines + which resource fields are modified in an + 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.ads.googleads.v24.services.types.UpdateYouTubeVideoUploadResponse: + Response message for + [YouTubeVideoUploadService.UpdateYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.UpdateYouTubeVideoUpload]. + + """ + # 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 = [customer_id, you_tube_video_upload, 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, + youtube_video_upload_service.UpdateYouTubeVideoUploadRequest, + ): + request = ( + youtube_video_upload_service.UpdateYouTubeVideoUploadRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if you_tube_video_upload is not None: + request.you_tube_video_upload = you_tube_video_upload + 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_you_tube_video_upload + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 remove_you_tube_video_upload( + self, + request: Optional[ + Union[ + youtube_video_upload_service.RemoveYouTubeVideoUploadRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> youtube_video_upload_service.RemoveYouTubeVideoUploadResponse: + r"""Removes YouTube videos uploaded using this API. + + Args: + request (Optional[Union[google.ads.googleads.v24.services.types.RemoveYouTubeVideoUploadRequest, dict]]): + The request object. Request message for + [YouTubeVideoUploadService.RemoveYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.RemoveYouTubeVideoUpload]. + customer_id (:class:`str`): + Required. The customer ID requesting + the YouTube video upload deletion. + Required. + + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.RemoveYouTubeVideoUploadResponse: + Response message for + [YouTubeVideoUploadService.RemoveYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.RemoveYouTubeVideoUpload]. + + """ + # 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 = [customer_id] + 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, + youtube_video_upload_service.RemoveYouTubeVideoUploadRequest, + ): + request = ( + youtube_video_upload_service.RemoveYouTubeVideoUploadRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.remove_you_tube_video_upload + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "YouTubeVideoUploadServiceAsyncClient": + 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__ = ("YouTubeVideoUploadServiceAsyncClient",) diff --git a/google/ads/googleads/v24/services/services/you_tube_video_upload_service/client.py b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/client.py new file mode 100644 index 000000000..7a2f1efb5 --- /dev/null +++ b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/client.py @@ -0,0 +1,1191 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import ( + Dict, + Callable, + Optional, + BinaryIO, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.ads.googleads.v24 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +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.ads.googleads.v24.resources.types import youtube_video_upload +from google.ads.googleads.v24.services.types import youtube_video_upload_service +from google.protobuf import field_mask_pb2 # type: ignore +from .transports.base import ( + YouTubeVideoUploadServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.rest_resumable import ( + YouTubeVideoUploadServiceRestResumableTransport, +) +from .transports.grpc import YouTubeVideoUploadServiceGrpcTransport +from .transports.grpc_asyncio import ( + YouTubeVideoUploadServiceGrpcAsyncIOTransport, +) + + +class YouTubeVideoUploadServiceClientMeta(type): + """Metaclass for the YouTubeVideoUploadService 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[YouTubeVideoUploadServiceTransport]] + _transport_registry["grpc"] = YouTubeVideoUploadServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ( + YouTubeVideoUploadServiceGrpcAsyncIOTransport + ) + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[YouTubeVideoUploadServiceTransport]: + """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 YouTubeVideoUploadServiceClient( + metaclass=YouTubeVideoUploadServiceClientMeta +): + """Service to manage YouTube video uploads.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{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: + YouTubeVideoUploadServiceClient: 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: + YouTubeVideoUploadServiceClient: 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) -> YouTubeVideoUploadServiceTransport: + """Returns the transport used by the client instance. + + Returns: + YouTubeVideoUploadServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def you_tube_video_upload_path( + customer_id: str, + video_upload_id: str, + ) -> str: + """Returns a fully-qualified you_tube_video_upload string.""" + return "customers/{customer_id}/youTubeVideoUploads/{video_upload_id}".format( + customer_id=customer_id, + video_upload_id=video_upload_id, + ) + + @staticmethod + def parse_you_tube_video_upload_path(path: str) -> Dict[str, str]: + """Parses a you_tube_video_upload path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/youTubeVideoUploads/(?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 = ( + YouTubeVideoUploadServiceClient._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 = ( + YouTubeVideoUploadServiceClient._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 + ): + """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 = ( + YouTubeVideoUploadServiceClient._DEFAULT_UNIVERSE + ) + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = YouTubeVideoUploadServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = YouTubeVideoUploadServiceClient._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 = YouTubeVideoUploadServiceClient._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): + """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, + developer_token: Optional[str] = None, + login_customer_id: Optional[str] = None, + linked_customer_id: Optional[str] = None, + use_cloud_org_for_api_access: bool = False, + transport: Optional[ + Union[ + str, + YouTubeVideoUploadServiceTransport, + Callable[..., YouTubeVideoUploadServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the you tube video upload 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. + developer_token (Optional[str]): The developer token to use for the + resumable upload transport. This will be used by the resumable upload methods + (create_you_tube_video_upload) ONLY! + login_customer_id (Optional[str]): The login customer ID to use for + the resumable upload transport. This will be used by the resumable upload methods + (create_you_tube_video_upload) ONLY! + linked_customer_id (Optional[str]): The linked customer ID to use for + the resumable upload transport. This will be used by the resumable upload methods + (create_you_tube_video_upload) ONLY! + use_cloud_org_for_api_access (bool): Whether to use the cloud org for + API access for the resumable upload transport. This will be used by the resumable upload methods + (create_you_tube_video_upload) ONLY! + transport (Optional[Union[str,YouTubeVideoUploadServiceTransport,Callable[..., YouTubeVideoUploadServiceTransport]]]): + 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 YouTubeVideoUploadServiceTransport 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, + ) = YouTubeVideoUploadServiceClient._read_environment_variables() + self._client_cert_source = ( + YouTubeVideoUploadServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ( + YouTubeVideoUploadServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + 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, YouTubeVideoUploadServiceTransport + ) + if transport_provided: + # transport is a YouTubeVideoUploadServiceTransport instance. + if 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( + YouTubeVideoUploadServiceTransport, transport + ) + self._api_endpoint = self._transport.host + resumable_creds = credentials or getattr( + self._transport, "_credentials", None + ) + + if resumable_creds is None: + raise ValueError( + "For the correct REST resumable transport initialization, either the credentials should be explicitly provided as a `credentials` parameter, or the transport passed should contain readable `_credentials` property. E.g. passing a GRPC channel as a transport does not satisfy this since the credentials cannot be extracted from it. This requirement is unique to the YouTubeVideoUploadService." + ) + + self._rest_resumable_transport = ( + YouTubeVideoUploadServiceRestResumableTransport( + credentials=resumable_creds, + credentials_file=None, + host=self._transport.host, + scopes=self._transport._scopes, + developer_token=developer_token, + login_customer_id=login_customer_id, + linked_customer_id=linked_customer_id, + use_cloud_org_for_api_access=use_cloud_org_for_api_access, + ) + ) + + self._api_endpoint = ( + self._api_endpoint + or YouTubeVideoUploadServiceClient._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[YouTubeVideoUploadServiceTransport], + Callable[..., YouTubeVideoUploadServiceTransport], + ] = ( + YouTubeVideoUploadServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast( + Callable[..., YouTubeVideoUploadServiceTransport], 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, + ) + + # Initialize a separate transport for the rest resumable uploads + self._rest_resumable_transport = ( + YouTubeVideoUploadServiceRestResumableTransport( + 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, + developer_token=developer_token, + login_customer_id=login_customer_id, + linked_customer_id=linked_customer_id, + use_cloud_org_for_api_access=use_cloud_org_for_api_access, + ) + ) + + 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.ads.googleads.v24.services.YouTubeVideoUploadServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v24.services.YouTubeVideoUploadService", + "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.ads.googleads.v24.services.YouTubeVideoUploadService", + "credentialsType": None, + } + ), + ) + + def create_you_tube_video_upload( + self, + request: Optional[ + Union[ + youtube_video_upload_service.CreateYouTubeVideoUploadRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + you_tube_video_upload: Optional[ + youtube_video_upload.YouTubeVideoUpload + ] = None, + stream: BinaryIO, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> youtube_video_upload_service.CreateYouTubeVideoUploadResponse: + r"""Uploads a video to Google-managed or advertiser owned + (brand) YouTube channel. + + Args: + request (Union[google.ads.googleads.v24.services.types.CreateYouTubeVideoUploadRequest, dict]): + The request object. Request message for + [YouTubeVideoUploadService.CreateYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.CreateYouTubeVideoUpload]. + customer_id (str): + Required. The customer ID requesting + the upload. Required. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + you_tube_video_upload (google.ads.googleads.v24.resources.types.YouTubeVideoUpload): + Required. The initial details of the + video to upload. Required. + + This corresponds to the ``you_tube_video_upload`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + stream (BinaryIO): + The stream to upload. + 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.googleads.v24.services.types.CreateYouTubeVideoUploadResponse: + Response message for + [YouTubeVideoUploadService.CreateYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.CreateYouTubeVideoUpload]. + + """ + # 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 = [customer_id, you_tube_video_upload] + 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, + youtube_video_upload_service.CreateYouTubeVideoUploadRequest, + ): + request = ( + youtube_video_upload_service.CreateYouTubeVideoUploadRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if you_tube_video_upload is not None: + request.you_tube_video_upload = you_tube_video_upload + + if stream is None: + raise ValueError("stream is required for resumable upload methods") + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = self._rest_resumable_transport.create_you_tube_video_upload_resumable( + request=request, + stream=stream, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def update_you_tube_video_upload( + self, + request: Optional[ + Union[ + youtube_video_upload_service.UpdateYouTubeVideoUploadRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + you_tube_video_upload: Optional[ + youtube_video_upload.YouTubeVideoUpload + ] = 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]]] = (), + ) -> youtube_video_upload_service.UpdateYouTubeVideoUploadResponse: + r"""Updates YouTube video's metadata, but only for videos + uploaded using this API. + + Args: + request (Union[google.ads.googleads.v24.services.types.UpdateYouTubeVideoUploadRequest, dict]): + The request object. Request message for + [YouTubeVideoUploadService.UpdateYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.UpdateYouTubeVideoUpload]. + customer_id (str): + Required. The customer ID requesting + the YouTube video upload update. + Required. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + you_tube_video_upload (google.ads.googleads.v24.resources.types.YouTubeVideoUpload): + Required. The YouTube video upload + resource to be updated. It's expected to + have a valid resource name. Required. + + This corresponds to the ``you_tube_video_upload`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Required. FieldMask that determines + which resource fields are modified in an + 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.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.googleads.v24.services.types.UpdateYouTubeVideoUploadResponse: + Response message for + [YouTubeVideoUploadService.UpdateYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.UpdateYouTubeVideoUpload]. + + """ + # 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 = [customer_id, you_tube_video_upload, 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, + youtube_video_upload_service.UpdateYouTubeVideoUploadRequest, + ): + request = ( + youtube_video_upload_service.UpdateYouTubeVideoUploadRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + if you_tube_video_upload is not None: + request.you_tube_video_upload = you_tube_video_upload + 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_you_tube_video_upload + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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 remove_you_tube_video_upload( + self, + request: Optional[ + Union[ + youtube_video_upload_service.RemoveYouTubeVideoUploadRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> youtube_video_upload_service.RemoveYouTubeVideoUploadResponse: + r"""Removes YouTube videos uploaded using this API. + + Args: + request (Union[google.ads.googleads.v24.services.types.RemoveYouTubeVideoUploadRequest, dict]): + The request object. Request message for + [YouTubeVideoUploadService.RemoveYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.RemoveYouTubeVideoUpload]. + customer_id (str): + Required. The customer ID requesting + the YouTube video upload deletion. + Required. + + This corresponds to the ``customer_id`` 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.ads.googleads.v24.services.types.RemoveYouTubeVideoUploadResponse: + Response message for + [YouTubeVideoUploadService.RemoveYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.RemoveYouTubeVideoUpload]. + + """ + # 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 = [customer_id] + 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, + youtube_video_upload_service.RemoveYouTubeVideoUploadRequest, + ): + request = ( + youtube_video_upload_service.RemoveYouTubeVideoUploadRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.remove_you_tube_video_upload + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # 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) -> "YouTubeVideoUploadServiceClient": + 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() + + +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__ = ("YouTubeVideoUploadServiceClient",) diff --git a/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/README.rst b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/README.rst new file mode 100644 index 000000000..ec14177eb --- /dev/null +++ b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`YouTubeVideoUploadServiceTransport` is the ABC for all transports. +- public child `YouTubeVideoUploadServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `YouTubeVideoUploadServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseYouTubeVideoUploadServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `YouTubeVideoUploadServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/__init__.py b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/__init__.py new file mode 100644 index 000000000..8fa98f6ea --- /dev/null +++ b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .base import YouTubeVideoUploadServiceTransport +from .grpc import YouTubeVideoUploadServiceGrpcTransport +from .grpc_asyncio import YouTubeVideoUploadServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[YouTubeVideoUploadServiceTransport]] +_transport_registry["grpc"] = YouTubeVideoUploadServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ( + YouTubeVideoUploadServiceGrpcAsyncIOTransport +) + +__all__ = ( + "YouTubeVideoUploadServiceTransport", + "YouTubeVideoUploadServiceGrpcTransport", + "YouTubeVideoUploadServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/base.py b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/base.py new file mode 100644 index 000000000..0085ee9bb --- /dev/null +++ b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/base.py @@ -0,0 +1,213 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Optional, Sequence, Union + +from google.ads.googleads.v24 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v24.services.types import youtube_video_upload_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 YouTubeVideoUploadServiceTransport(abc.ABC): + """Abstract transport class for YouTubeVideoUploadService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.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: 'googleads.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. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.create_you_tube_video_upload: gapic_v1.method.wrap_method( + self.create_you_tube_video_upload, + default_timeout=None, + client_info=client_info, + ), + self.update_you_tube_video_upload: gapic_v1.method.wrap_method( + self.update_you_tube_video_upload, + default_timeout=None, + client_info=client_info, + ), + self.remove_you_tube_video_upload: gapic_v1.method.wrap_method( + self.remove_you_tube_video_upload, + 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 create_you_tube_video_upload( + self, + ) -> Callable[ + [youtube_video_upload_service.CreateYouTubeVideoUploadRequest], + Union[ + youtube_video_upload_service.CreateYouTubeVideoUploadResponse, + Awaitable[ + youtube_video_upload_service.CreateYouTubeVideoUploadResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def update_you_tube_video_upload( + self, + ) -> Callable[ + [youtube_video_upload_service.UpdateYouTubeVideoUploadRequest], + Union[ + youtube_video_upload_service.UpdateYouTubeVideoUploadResponse, + Awaitable[ + youtube_video_upload_service.UpdateYouTubeVideoUploadResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def remove_you_tube_video_upload( + self, + ) -> Callable[ + [youtube_video_upload_service.RemoveYouTubeVideoUploadRequest], + Union[ + youtube_video_upload_service.RemoveYouTubeVideoUploadResponse, + Awaitable[ + youtube_video_upload_service.RemoveYouTubeVideoUploadResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("YouTubeVideoUploadServiceTransport",) diff --git a/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/grpc.py b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/grpc.py new file mode 100644 index 000000000..ffdf914e0 --- /dev/null +++ b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/grpc.py @@ -0,0 +1,449 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v24.services.types import youtube_video_upload_service +from .base import YouTubeVideoUploadServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.YouTubeVideoUploadService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.YouTubeVideoUploadService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class YouTubeVideoUploadServiceGrpcTransport( + YouTubeVideoUploadServiceTransport +): + """gRPC backend transport for YouTubeVideoUploadService. + + Service to manage YouTube video uploads. + + 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 = "googleads.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: 'googleads.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. + + 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 = "googleads.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 create_you_tube_video_upload( + self, + ) -> Callable[ + [youtube_video_upload_service.CreateYouTubeVideoUploadRequest], + youtube_video_upload_service.CreateYouTubeVideoUploadResponse, + ]: + r"""Return a callable for the create you tube video upload method over gRPC. + + Uploads a video to Google-managed or advertiser owned + (brand) YouTube channel. + + Returns: + Callable[[~.CreateYouTubeVideoUploadRequest], + ~.CreateYouTubeVideoUploadResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_you_tube_video_upload" not in self._stubs: + self._stubs["create_you_tube_video_upload"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.YouTubeVideoUploadService/CreateYouTubeVideoUpload", + request_serializer=youtube_video_upload_service.CreateYouTubeVideoUploadRequest.serialize, + response_deserializer=youtube_video_upload_service.CreateYouTubeVideoUploadResponse.deserialize, + ) + ) + return self._stubs["create_you_tube_video_upload"] + + @property + def update_you_tube_video_upload( + self, + ) -> Callable[ + [youtube_video_upload_service.UpdateYouTubeVideoUploadRequest], + youtube_video_upload_service.UpdateYouTubeVideoUploadResponse, + ]: + r"""Return a callable for the update you tube video upload method over gRPC. + + Updates YouTube video's metadata, but only for videos + uploaded using this API. + + Returns: + Callable[[~.UpdateYouTubeVideoUploadRequest], + ~.UpdateYouTubeVideoUploadResponse]: + 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_you_tube_video_upload" not in self._stubs: + self._stubs["update_you_tube_video_upload"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.YouTubeVideoUploadService/UpdateYouTubeVideoUpload", + request_serializer=youtube_video_upload_service.UpdateYouTubeVideoUploadRequest.serialize, + response_deserializer=youtube_video_upload_service.UpdateYouTubeVideoUploadResponse.deserialize, + ) + ) + return self._stubs["update_you_tube_video_upload"] + + @property + def remove_you_tube_video_upload( + self, + ) -> Callable[ + [youtube_video_upload_service.RemoveYouTubeVideoUploadRequest], + youtube_video_upload_service.RemoveYouTubeVideoUploadResponse, + ]: + r"""Return a callable for the remove you tube video upload method over gRPC. + + Removes YouTube videos uploaded using this API. + + Returns: + Callable[[~.RemoveYouTubeVideoUploadRequest], + ~.RemoveYouTubeVideoUploadResponse]: + 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 "remove_you_tube_video_upload" not in self._stubs: + self._stubs["remove_you_tube_video_upload"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.YouTubeVideoUploadService/RemoveYouTubeVideoUpload", + request_serializer=youtube_video_upload_service.RemoveYouTubeVideoUploadRequest.serialize, + response_deserializer=youtube_video_upload_service.RemoveYouTubeVideoUploadResponse.deserialize, + ) + ) + return self._stubs["remove_you_tube_video_upload"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("YouTubeVideoUploadServiceGrpcTransport",) diff --git a/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/grpc_asyncio.py b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..e843a5c7d --- /dev/null +++ b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/grpc_asyncio.py @@ -0,0 +1,486 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v24.services.types import youtube_video_upload_service +from .base import YouTubeVideoUploadServiceTransport, DEFAULT_CLIENT_INFO + +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)}" + ) + + 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.ads.googleads.v24.services.YouTubeVideoUploadService", + "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)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v24.services.YouTubeVideoUploadService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class YouTubeVideoUploadServiceGrpcAsyncIOTransport( + YouTubeVideoUploadServiceTransport +): + """gRPC AsyncIO backend transport for YouTubeVideoUploadService. + + Service to manage YouTube video uploads. + + 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 = "googleads.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 = "googleads.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: 'googleads.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. + + 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 create_you_tube_video_upload( + self, + ) -> Callable[ + [youtube_video_upload_service.CreateYouTubeVideoUploadRequest], + Awaitable[ + youtube_video_upload_service.CreateYouTubeVideoUploadResponse + ], + ]: + r"""Return a callable for the create you tube video upload method over gRPC. + + Uploads a video to Google-managed or advertiser owned + (brand) YouTube channel. + + Returns: + Callable[[~.CreateYouTubeVideoUploadRequest], + Awaitable[~.CreateYouTubeVideoUploadResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_you_tube_video_upload" not in self._stubs: + self._stubs["create_you_tube_video_upload"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.YouTubeVideoUploadService/CreateYouTubeVideoUpload", + request_serializer=youtube_video_upload_service.CreateYouTubeVideoUploadRequest.serialize, + response_deserializer=youtube_video_upload_service.CreateYouTubeVideoUploadResponse.deserialize, + ) + ) + return self._stubs["create_you_tube_video_upload"] + + @property + def update_you_tube_video_upload( + self, + ) -> Callable[ + [youtube_video_upload_service.UpdateYouTubeVideoUploadRequest], + Awaitable[ + youtube_video_upload_service.UpdateYouTubeVideoUploadResponse + ], + ]: + r"""Return a callable for the update you tube video upload method over gRPC. + + Updates YouTube video's metadata, but only for videos + uploaded using this API. + + Returns: + Callable[[~.UpdateYouTubeVideoUploadRequest], + Awaitable[~.UpdateYouTubeVideoUploadResponse]]: + 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_you_tube_video_upload" not in self._stubs: + self._stubs["update_you_tube_video_upload"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.YouTubeVideoUploadService/UpdateYouTubeVideoUpload", + request_serializer=youtube_video_upload_service.UpdateYouTubeVideoUploadRequest.serialize, + response_deserializer=youtube_video_upload_service.UpdateYouTubeVideoUploadResponse.deserialize, + ) + ) + return self._stubs["update_you_tube_video_upload"] + + @property + def remove_you_tube_video_upload( + self, + ) -> Callable[ + [youtube_video_upload_service.RemoveYouTubeVideoUploadRequest], + Awaitable[ + youtube_video_upload_service.RemoveYouTubeVideoUploadResponse + ], + ]: + r"""Return a callable for the remove you tube video upload method over gRPC. + + Removes YouTube videos uploaded using this API. + + Returns: + Callable[[~.RemoveYouTubeVideoUploadRequest], + Awaitable[~.RemoveYouTubeVideoUploadResponse]]: + 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 "remove_you_tube_video_upload" not in self._stubs: + self._stubs["remove_you_tube_video_upload"] = ( + self._logged_channel.unary_unary( + "/google.ads.googleads.v24.services.YouTubeVideoUploadService/RemoveYouTubeVideoUpload", + request_serializer=youtube_video_upload_service.RemoveYouTubeVideoUploadRequest.serialize, + response_deserializer=youtube_video_upload_service.RemoveYouTubeVideoUploadResponse.deserialize, + ) + ) + return self._stubs["remove_you_tube_video_upload"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.create_you_tube_video_upload: self._wrap_method( + self.create_you_tube_video_upload, + default_timeout=None, + client_info=client_info, + ), + self.update_you_tube_video_upload: self._wrap_method( + self.update_you_tube_video_upload, + default_timeout=None, + client_info=client_info, + ), + self.remove_you_tube_video_upload: self._wrap_method( + self.remove_you_tube_video_upload, + 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" + + +__all__ = ("YouTubeVideoUploadServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/rest_resumable.py b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/rest_resumable.py new file mode 100644 index 000000000..b2945beab --- /dev/null +++ b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/rest_resumable.py @@ -0,0 +1,343 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 base64 +import json # type: ignore +import os +from typing import Callable, Dict, Optional, Sequence, Tuple, Union, BinaryIO +from datetime import datetime, timedelta, timezone + +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.requests import AuthorizedSession # type: ignore + +import google.protobuf +from google.protobuf import empty_pb2 # type: ignore +from google.protobuf import json_format + +from google.ads.googleads.v24.services.types import youtube_video_upload_service + +from .rest_resumable_base import ( + _BaseYouTubeVideoUploadServiceRestResumableTransport, +) +from .resumable_upload import make_resumable_upload + + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + +_DEFAULT_CHUNK_SIZE = 10 * 1024 * 1024 # 10MB +_DEFAULT_TIMEOUT = 14400 +_DEFAULT_CONTENT_TYPE = "application/octet-stream" + +_DEFAULT_RETRY = retries.Retry( + predicate=retries.if_exception_type( + core_exceptions.ServiceUnavailable, + core_exceptions.DeadlineExceeded, + ), + initial=1.0, + maximum=60.0, + multiplier=1.3, +) + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + +if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER + DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ + + +class YouTubeVideoUploadServiceRestResumableInterceptor: + """Interceptor for YouTubeVideoUploadService. Not implemented yet""" + + +class YouTubeVideoUploadServiceRestResumableTransport( + _BaseYouTubeVideoUploadServiceRestResumableTransport +): + """REST backend synchronous transport for YouTubeVideoUploadService. + It is only used by Resumable Media Upload functionality + """ + + def __init__( + self, + *, + host: str = "googleads.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[ + YouTubeVideoUploadServiceRestResumableInterceptor + ] = None, + api_audience: Optional[str] = None, + developer_token: Optional[str] = None, + login_customer_id: Optional[str] = None, + linked_customer_id: Optional[str] = None, + use_cloud_org_for_api_access: bool = False, + **kwargs, # Catch-all for forward compatibility + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'googleads.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. + developer_token (Optional[str]): The developer token to use for the + resumable upload transport. + login_customer_id (Optional[str]): The login customer ID to use for + the resumable upload transport. + linked_customer_id (Optional[str]): The linked customer ID to use for + the resumable upload transport. + use_cloud_org_for_api_access (bool): Whether to use the cloud org for + API access for the resumable upload transport. + """ + # Run the base constructor + 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._developer_token = developer_token + self._login_customer_id = login_customer_id + self._linked_customer_id = linked_customer_id + self._use_cloud_org_for_api_access = use_cloud_org_for_api_access + + def _sanitize_headers_for_rest( + self, metadata: Union[Dict, Sequence[Tuple[str, Union[str, bytes]]]] + ) -> Dict[str, str]: + """ + Converts gRPC metadata into REST-friendly headers. + + - Decodes byte keys to strings. + - Base64 encodes byte values if the key ends with '-bin'. + - Raises ValueError if binary data is found in a non-'-bin' key. + """ + # Normalize input to a dict if it's a sequence + raw_headers = ( + dict(metadata) if not isinstance(metadata, dict) else metadata + ) + clean_headers = {} + + for key, value in raw_headers.items(): + # Ensure Key is a String + k_str = key.decode("utf-8") if isinstance(key, bytes) else key + + if isinstance(value, bytes): + if not k_str.endswith("-bin"): + raise ValueError( + f"Invalid binary header '{k_str}'. Binary data is only " + "allowed in keys ending with '-bin'." + ) + # Valid binary header: Base64 encode + clean_headers[k_str] = base64.b64encode(value).decode("ascii") + else: + # String value: Keep as is + clean_headers[k_str] = str(value) + + return clean_headers + + def _update_headers_with_googleads( + self, headers: dict[str, str] + ) -> dict[str, str]: + """ + Returns a new dictionary with identity headers injected, mirroring the + MetadataInterceptor logic. Does not modify the input dictionary. + """ + # Create a shallow copy to avoid in-place modification + new_headers = headers.copy() if headers else {} + + # 1. Developer Token Logic + # Only add if we are NOT using Cloud Org access AND the token exists. + # This prevents the crash if developer_token is None. + if not self._use_cloud_org_for_api_access and self._developer_token: + new_headers["developer-token"] = self._developer_token + + # 2. Login Customer ID Logic + if self._login_customer_id: + new_headers["login-customer-id"] = self._login_customer_id + + # 3. Linked Customer ID Logic + if self._linked_customer_id: + new_headers["linked-customer-id"] = self._linked_customer_id + + return new_headers + + @staticmethod + def _maybe_rewind(stream, rewind=False): + """Rewind the stream if desired. + + :type stream: IO[bytes] + :param stream: A bytes IO object open for reading. + + :type rewind: bool + :param rewind: Indicates if we should seek to the beginning of the stream. + """ + if rewind: + stream.seek(0, os.SEEK_SET) + + def create_you_tube_video_upload_resumable( + self, + request: youtube_video_upload_service.CreateYouTubeVideoUploadRequest, + *, + stream: BinaryIO, + rewind: bool = False, + size: Optional[int] = None, + content_type: Optional[str] = None, + chunk_size: Optional[int] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> youtube_video_upload_service.CreateYouTubeVideoUploadResponse: + r"""Uploads a video to Google-managed or advertiser owned + (brand) YouTube channel. + + Args: + request (Union[google.ads.googleads.v24.services.types.CreateYouTubeVideoUploadRequest, dict]): + The request object. Request message for + [YouTubeVideoUploadService.CreateYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.CreateYouTubeVideoUpload]. + stream (BinaryIO): + A stream of bytes, such as a file opened in binary mode for reading. + rewind (bool): + If True, seek to the beginning of the file handle before uploading from the stream. + size (int): + The number of bytes to be uploaded (which will be read from + ``stream``). If not provided, the upload will be concluded once + ``stream`` is exhausted. + content_type (str): + The MIME type of the content being uploaded. + chunk_size (int): + The size of each chunk to be uploaded. + 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.googleads.v24.services.types.CreateYouTubeVideoUploadResponse: + Response message for + [YouTubeVideoUploadService.CreateYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.CreateYouTubeVideoUpload]. + + + """ + + self._maybe_rewind(stream, rewind=rewind) + + http_options = ( + _BaseYouTubeVideoUploadServiceRestResumableTransport._BaseCreateYouTubeVideoUploadRequest._get_http_options() + ) + transcoded_request = _BaseYouTubeVideoUploadServiceRestResumableTransport._BaseCreateYouTubeVideoUploadRequest._get_transcoded_request( + http_options, request + ) + request_url = "{host}/resumable/upload{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + + # preserving_proto_field_name=True ensures we get snake case "customer_id" + json_body = json_format.MessageToJson( + request._pb, + preserving_proto_field_name=True, + ) + + if chunk_size is None: + chunk_size = _DEFAULT_CHUNK_SIZE + if retry is gapic_v1.method.DEFAULT: + retry = _DEFAULT_RETRY + if timeout is None or timeout is gapic_v1.method.DEFAULT: + timeout = _DEFAULT_TIMEOUT + if content_type is None: + content_type = _DEFAULT_CONTENT_TYPE + + deadline = datetime.now(timezone.utc) + timedelta(seconds=timeout) + headers = dict(metadata) + + # 1. Sanitize (will raise ValueError if headers are invalid) + headers = self._sanitize_headers_for_rest(headers or {}) + + # 2. Inject google-ads specific metadata + headers = self._update_headers_with_googleads(headers) + + response = make_resumable_upload( + transport=self._session, + request_body=json_body, + stream=stream, + upload_url=request_url, + size=size, + content_type=content_type, + chunk_size=chunk_size, + request_retry=retry, + deadline=deadline, + headers=headers, + on_progress=None, + ) + + data = response.json() + response_message = ( + youtube_video_upload_service.CreateYouTubeVideoUploadResponse() + ) + json_format.ParseDict( + data, response_message._pb, ignore_unknown_fields=True + ) + + return response_message + + +__all__ = ("YouTubeVideoUploadServiceRestResumableTransport",) diff --git a/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/rest_resumable_base.py b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/rest_resumable_base.py new file mode 100644 index 000000000..bedac189e --- /dev/null +++ b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/rest_resumable_base.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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, Dict, List, Optional + +from google.api_core import gapic_v1, path_template +from google.protobuf import empty_pb2 # type: ignore + +from google.ads.googleads.v24.services.types import youtube_video_upload_service + +from .base import DEFAULT_CLIENT_INFO, YouTubeVideoUploadServiceTransport + + +class _BaseYouTubeVideoUploadServiceRestResumableTransport( + YouTubeVideoUploadServiceTransport +): + """Base REST Resumable backend transport for YouTubeVideoUploadService. + + Note: This class is not meant to be used directly. Only services that has RPCs + that should be invoked as resumable upload should instantiate it and use it. + """ + + def __init__( + self, + *, + host: str = "googleads.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: 'googleads.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 _BaseCreateYouTubeVideoUploadRequest: + 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": "/v24/customers/{customer_id=*}/youTubeVideoUploads:create", + "body": "*", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = ( + youtube_video_upload_service.CreateYouTubeVideoUploadRequest.pb( + request + ) + ) + transcoded_request = path_template.transcode( + http_options, pb_request + ) + return transcoded_request + + +__all__ = ("_BaseYouTubeVideoUploadServiceRestResumableTransport",) diff --git a/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/resumable_upload.py b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/resumable_upload.py new file mode 100644 index 000000000..34533022f --- /dev/null +++ b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/resumable_upload.py @@ -0,0 +1,483 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 datetime +import logging + +from dataclasses import dataclass +from typing import ( + Any, + BinaryIO, + Callable, + Dict, + Optional, + Sequence, + Tuple, + Union, +) + +import google.api_core.retry +import requests +from .resumable_upload_error_adapter import raise_formatted_for_status + +_LOGGER = logging.getLogger(__name__) + +_DEFAULT_CHUNK_SIZE = 10 * 1024 * 1024 # 10MB + + +@dataclass(frozen=True) +class ResumableUploadStatus: + """Status of a resumable upload. + + Attributes: + upload_url (str): + The session URL for the resumable upload. + total_bytes (Optional[int]): + The total number of bytes to be uploaded, if known. + bytes_uploaded (int): + The number of bytes successfully uploaded so far. + finished (bool): + Whether the upload has completed. + """ + + upload_url: str + total_bytes: Optional[int] + bytes_uploaded: int + finished: bool + + +class ResumableUpload: + """Manages a resumable upload session. + + This class handles the initiation, chunk transmission, and recovery + of a resumable upload according to the Google Resumable Upload protocol. + """ + + def __init__( + self, + upload_url: str, + stream: BinaryIO, + size: Optional[int] = None, + content_type: Optional[str] = None, + chunk_size: Optional[int] = None, + deadline: Optional[datetime.datetime] = None, + headers: Optional[Sequence[Tuple[str, Union[str, bytes]]]] = None, + on_progress: Optional[Callable[[ResumableUploadStatus], None]] = None, + ): + """Initializes the ResumableUpload object. + + Args: + upload_url (str): + The initial URL to start the resumable upload. + stream (BinaryIO): + A stream of bytes to be uploaded. + size (Optional[int]): + The total number of bytes to be uploaded. If not provided, + the upload continues until the stream is exhausted. + content_type (Optional[str]): + The MIME type of the content being uploaded. + chunk_size (Optional[int]): + The size of each chunk to be uploaded. Defaults to 10MB. + deadline (Optional[datetime.datetime]): + The deadline for the entire upload process. + headers (Optional[Sequence[Tuple[str, Union[str, bytes]]]]): + Extra headers to be sent with the initiation and chunk requests. + on_progress (Optional[Callable[[ResumableUploadStatus], None]]): + A callback function called after each successful chunk upload. + """ + self.initial_url = upload_url + self.stream = stream + self.size = size + self.content_type = content_type + self.chunk_size = chunk_size or _DEFAULT_CHUNK_SIZE + self.deadline = deadline + self.extra_headers = dict(headers or []) + self.on_progress = on_progress + + self.session_url = None + self.bytes_uploaded = 0 + self.finished = False + self.chunk_granularity = None + + def _check_deadline(self) -> Optional[float]: + if self.deadline: + now = datetime.datetime.now(datetime.timezone.utc) + timeout = (self.deadline - now).total_seconds() + if timeout <= 0: + raise Exception( + f"Upload deadline {self.deadline} (as calculated from the timeout argument) was exceeded" + ) + return timeout + return None + + def _get_retry_predicate(self): + def should_retry(exc): + if isinstance(exc, requests.exceptions.RequestException): + if isinstance( + exc, + ( + requests.exceptions.ConnectionError, + requests.exceptions.Timeout, + ), + ): + return True + if exc.response is not None: + status_code = exc.response.status_code + return status_code in (408, 429, 500, 502, 503, 504) + return False + + return should_retry + + def _log_request( + self, method: str, url: str, headers: Dict[str, str], data: Any = None + ): + if not _LOGGER.isEnabledFor(logging.DEBUG): + return + + display_data = data + if isinstance(data, bytes) and len(data) > 64: + display_data = f"{data[:64]!r}... ({len(data)} bytes)" + + _LOGGER.debug( + "HTTP Request: %s %s\nHeaders: %s\nBody: %s", + method, + url, + headers, + display_data, + ) + + def _log_response(self, response: requests.Response): + if not _LOGGER.isEnabledFor(logging.DEBUG): + return + + _LOGGER.debug( + "HTTP Response: %s %s\nHeaders: %s\nBody: %s", + response.status_code, + response.reason, + response.headers, + response.text, + ) + + def _prepare_initiate_request( + self, body: str + ) -> Tuple[str, str, str, Dict[str, str]]: + headers = { + "X-Goog-Upload-Protocol": "resumable", + "X-Goog-Upload-Command": "start", + } + + # Prefix logical headers + if self.content_type: + headers["X-Goog-Upload-Header-Content-Type"] = self.content_type + if self.size is not None: + headers["X-Goog-Upload-Header-Content-Length"] = str(self.size) + + # Add extra headers, prefixing if necessary + for k, v in self.extra_headers.items(): + if k.lower() in ( + "content-length", + "content-type", + "content-encoding", + "transfer-encoding", + ): + headers[f"X-Goog-Upload-Header-{k}"] = str(v) + else: + headers[k] = str(v) + + return "POST", self.initial_url, body, headers + + def _process_initiate_response(self, response: requests.Response): + raise_formatted_for_status(response) + + self.session_url = response.headers.get("X-Goog-Upload-URL") + if not self.session_url: + raise ValueError("Server did not return X-Goog-Upload-URL") + + granularity = response.headers.get("X-Goog-Upload-Chunk-Granularity") + if granularity: + self.chunk_granularity = int(granularity) + _LOGGER.debug( + "Server requested chunk granularity: %d", self.chunk_granularity + ) + + if self.on_progress: + self.on_progress( + ResumableUploadStatus( + upload_url=self.session_url, + total_bytes=self.size, + bytes_uploaded=0, + finished=False, + ) + ) + + def initiate( + self, + transport: requests.Session, + request_body: str = "", + request_retry: Optional[google.api_core.retry.Retry] = None, + ): + """Initiates the resumable upload session. + + This method sends the initial request to the server to start a new + resumable upload session and retrieves the session URL. + + Args: + transport (requests.Session): + The authorized session to use for the initiation request. + request_body (str): + The JSON-encoded request body for the initiation request. + request_retry (Optional[google.api_core.retry.Retry]): + Designation of what errors, if any, should be retried. + """ + _LOGGER.info("Initiating resumable upload to %s", self.initial_url) + method, url, body, headers = self._prepare_initiate_request( + request_body + ) + + def do_initiate(): + timeout = self._check_deadline() + self._log_request(method, url, headers, body) + response = transport.request( + method, url, data=body, headers=headers, timeout=timeout + ) + self._log_response(response) + raise_formatted_for_status(response) + return response + + if request_retry: + response = request_retry(do_initiate)() + else: + response = do_initiate() + + self._process_initiate_response(response) + + def _prepare_chunk_request( + self, + ) -> Tuple[str, str, bytes, Dict[str, str], int]: + # Adjust chunk size based on granularity if needed + actual_chunk_size = self.chunk_size + if self.chunk_granularity: + if actual_chunk_size % self.chunk_granularity != 0: + actual_chunk_size = ( + (actual_chunk_size // self.chunk_granularity) + 1 + ) * self.chunk_granularity + _LOGGER.debug( + "Adjusted chunk size to %d based on granularity %d", + actual_chunk_size, + self.chunk_granularity, + ) + + data = self.stream.read(actual_chunk_size) + data_len = len(data) + is_last_chunk = data_len < actual_chunk_size or ( + self.size is not None + and self.bytes_uploaded + data_len >= self.size + ) + + command = "upload" + if is_last_chunk: + command = "upload, finalize" + + headers = { + "X-Goog-Upload-Command": command, + "X-Goog-Upload-Offset": str(self.bytes_uploaded), + } + + return "POST", self.session_url, data, headers, data_len + + def _process_chunk_response( + self, response: requests.Response, chunk_len: int + ): + raise_formatted_for_status(response) + + status = response.headers.get("X-Goog-Upload-Status") + if status == "active": + self.bytes_uploaded += chunk_len + elif status == "final": + self.finished = True + self.bytes_uploaded += chunk_len + + def transmit_next_chunk( + self, transport: requests.Session + ) -> requests.Response: + """Uploads the next chunk of data from the stream. + + This method reads a chunk from the stream, prepares the upload request, + transmits it to the server, and processes the response. + + Args: + transport (requests.Session): + The authorized session to use for the upload. + + Returns: + requests.Response: + The response from the server for this chunk upload. + """ + self._check_deadline() + method, url, data, headers, chunk_len = self._prepare_chunk_request() + + retry = google.api_core.retry.Retry( + predicate=self._get_retry_predicate(), + deadline=self._check_deadline(), + ) + + def do_upload(): + _LOGGER.info( + "Uploading chunk at offset %s, size %d, command %s", + headers["X-Goog-Upload-Offset"], + chunk_len, + headers["X-Goog-Upload-Command"], + ) + timeout = self._check_deadline() + self._log_request(method, url, headers, data) + response = transport.request( + method, url, data=data, headers=headers, timeout=timeout + ) + self._log_response(response) + raise_formatted_for_status(response) + return response + + try: + response = retry(do_upload)() + self._process_chunk_response(response, chunk_len) + except Exception as e: + _LOGGER.error("Error during chunk upload: %s", e) + self._recover(transport, retry) + if ( + isinstance(e, requests.exceptions.HTTPError) + and e.response is not None + ): + return e.response + raise + + if self.on_progress: + self.on_progress( + ResumableUploadStatus( + upload_url=self.session_url, + total_bytes=self.size, + bytes_uploaded=self.bytes_uploaded, + finished=self.finished, + ) + ) + + return response + + def _prepare_recovery_request(self) -> Tuple[str, str, Dict[str, str]]: + headers = {"X-Goog-Upload-Command": "query"} + return "POST", self.session_url, headers + + def _process_recovery_response(self, response: requests.Response): + raise_formatted_for_status(response) + status = response.headers.get("X-Goog-Upload-Status") + + if status == "active": + received = int( + response.headers.get("X-Goog-Upload-Size-Received", 0) + ) + _LOGGER.info( + "Server reported %d bytes received. Seeking stream.", received + ) + self.bytes_uploaded = received + self.stream.seek(received) + elif status == "final": + _LOGGER.info("Upload already finalized according to server.") + self.finished = True + elif status == "cancelled": + raise RuntimeError("Upload was cancelled by server") + + def _recover( + self, transport: requests.Session, retry: google.api_core.retry.Retry + ): + _LOGGER.info("Attempting recovery via query command") + method, url, headers = self._prepare_recovery_request() + + def do_query(): + timeout = self._check_deadline() + self._log_request(method, url, headers) + response = transport.request( + method, url, headers=headers, timeout=timeout + ) + self._log_response(response) + raise_formatted_for_status(response) + return response + + response = retry(do_query)() + self._process_recovery_response(response) + + +def make_resumable_upload( + transport: requests.Session, + request_body: str, + stream: BinaryIO, + upload_url: str, + size: Optional[int] = None, + content_type: Optional[str] = None, + chunk_size: Optional[int] = None, + request_retry: Optional[google.api_core.retry.Retry] = None, + deadline: Optional[datetime.datetime] = None, + headers: Optional[Sequence[Tuple[str, Union[str, bytes]]]] = None, + on_progress: Optional[Callable[[ResumableUploadStatus], None]] = None, +) -> requests.Response: + """Makes a resumable upload. + + Args: + transport (requests.Session): + The authorized session to use for the upload. + request_body (str): + The JSON-encoded request body to send during initiation. + stream (BinaryIO): + A stream of bytes to be uploaded. + upload_url (str): + The initial URL to start the resumable upload. + size (int): + The number of bytes to be uploaded. If not provided, + the upload will continue until the stream is exhausted. + content_type (str): + The MIME type of the content being uploaded. + chunk_size (int): + The size of each chunk to be uploaded. + request_retry (google.api_core.retry.Retry): + Designation of what errors, if any, should be retried during initiation. + deadline (datetime.datetime): + The deadline for the entire upload process. + headers (Sequence[Tuple[str, Union[str, bytes]]]): + Key/value pairs which should be sent along with the request as metadata. + on_progress (Callable[[ResumableUploadStatus], None]): + A callback function that will be called after each chunk is uploaded. + + Returns: + requests.Response: + The final response from the server after the upload is complete. + """ + upload = ResumableUpload( + upload_url, + stream=stream, + size=size, + content_type=content_type, + chunk_size=chunk_size, + deadline=deadline, + headers=headers, + on_progress=on_progress, + ) + upload.initiate( + transport=transport, + request_body=request_body, + request_retry=request_retry, + ) + + final_response = None + while not upload.finished: + final_response = upload.transmit_next_chunk(transport=transport) + return final_response diff --git a/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/resumable_upload_error_adapter.py b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/resumable_upload_error_adapter.py new file mode 100644 index 000000000..08be9c2be --- /dev/null +++ b/google/ads/googleads/v24/services/services/you_tube_video_upload_service/transports/resumable_upload_error_adapter.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 grpc +import requests +from typing import Any, Optional +from google.api_core import exceptions as core_exceptions + +from google.ads.googleads.errors import GoogleAdsException +from google.ads.googleads.v24.errors.types.errors import ( + GoogleAdsError, + GoogleAdsFailure, + ErrorCode, +) + + +class ResumableUploadErrorAdapter(grpc.RpcError, grpc.Call): + """ + A concrete implementation of gRPC abstract classes. + Wraps a requests.Response to mimic a gRPC call for GoogleAdsException. + """ + + def __init__( + self, response: requests.Response, mapped_grpc_code: grpc.StatusCode + ): + self._response = response + self._mapped_code = mapped_grpc_code + + # --- grpc.Call & grpc.RpcContext Required Methods --- + def code(self) -> grpc.StatusCode: + return self._mapped_code + + def details(self) -> str: + # RUP specifies error details are in the response body + return self._response.text + + def initial_metadata(self) -> Any: + return None + + def trailing_metadata(self) -> Any: + # HTTP headers serve as trailing metadata in RUP + return tuple(self._response.headers.items()) + + def is_active(self) -> bool: + return False + + def time_remaining(self) -> Optional[float]: + return None + + def cancel(self) -> None: + pass + + def add_callback(self, callback: Any) -> None: + pass + + +def raise_formatted_ads_exception(response: requests.Response): + """Converts a RUP HTTP response into a rich GoogleAdsException. + + Args: + response (requests.Response): + The HTTP response containing error details. + + Raises: + GoogleAdsException: + A rich exception containing the mapped gRPC status, failure details, + and request ID. + """ + # 1. Map HTTP status (e.g., 400) to gRPC status (e.g., INVALID_ARGUMENT) + core_error = core_exceptions.from_http_response(response) + grpc_code = core_error.grpc_status_code or grpc.StatusCode.INTERNAL + + # 2. Build the ErrorCode using the specific oneof member 'request_error' + # Setting this automatically sets the 'error_code' oneof group. + # We use '1' (UNSPECIFIED/UNKNOWN) for the enum value within RequestError. + e_code = ErrorCode(request_error=1) + + # 3. Build the GoogleAdsError + # Message is populated from the RUP response text + g_error = GoogleAdsError(message=core_error.message, error_code=e_code) + + # 4. Build the GoogleAdsFailure container + # request_id comes from X-Goog-Upload-Status per protocol + request_id = response.headers.get("X-Goog-Upload-Status", "unknown") + failure = GoogleAdsFailure(errors=[g_error], request_id=request_id) + + # 5. Instantiate the adapter and raise the final exception + adapter = ResumableUploadErrorAdapter(response, grpc_code) + + raise GoogleAdsException( + error=adapter, call=adapter, failure=failure, request_id=request_id + ) + + +def raise_formatted_for_status(response: requests.Response): + """Replacement for response.raise_for_status() that raises GoogleAdsException. + + Args: + response (requests.Response): + The HTTP response to check for errors. + + Raises: + GoogleAdsException: + If the response status code indicates an error. + """ + if not response.ok: + raise_formatted_ads_exception(response) diff --git a/google/ads/googleads/v24/services/types/__init__.py b/google/ads/googleads/v24/services/types/__init__.py new file mode 100644 index 000000000..8f1b1c1d6 --- /dev/null +++ b/google/ads/googleads/v24/services/types/__init__.py @@ -0,0 +1,1486 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 .account_budget_proposal_service import ( + AccountBudgetProposalOperation, + MutateAccountBudgetProposalRequest, + MutateAccountBudgetProposalResponse, + MutateAccountBudgetProposalResult, +) +from .account_link_service import ( + AccountLinkOperation, + CreateAccountLinkRequest, + CreateAccountLinkResponse, + MutateAccountLinkRequest, + MutateAccountLinkResponse, + MutateAccountLinkResult, +) +from .ad_group_ad_label_service import ( + AdGroupAdLabelOperation, + MutateAdGroupAdLabelResult, + MutateAdGroupAdLabelsRequest, + MutateAdGroupAdLabelsResponse, +) +from .ad_group_ad_service import ( + AdGroupAdOperation, + AssetsWithFieldType, + MutateAdGroupAdResult, + MutateAdGroupAdsRequest, + MutateAdGroupAdsResponse, + RemoveAutomaticallyCreatedAssetsRequest, +) +from .ad_group_asset_service import ( + AdGroupAssetOperation, + MutateAdGroupAssetResult, + MutateAdGroupAssetsRequest, + MutateAdGroupAssetsResponse, +) +from .ad_group_asset_set_service import ( + AdGroupAssetSetOperation, + MutateAdGroupAssetSetResult, + MutateAdGroupAssetSetsRequest, + MutateAdGroupAssetSetsResponse, +) +from .ad_group_bid_modifier_service import ( + AdGroupBidModifierOperation, + MutateAdGroupBidModifierResult, + MutateAdGroupBidModifiersRequest, + MutateAdGroupBidModifiersResponse, +) +from .ad_group_criterion_customizer_service import ( + AdGroupCriterionCustomizerOperation, + MutateAdGroupCriterionCustomizerResult, + MutateAdGroupCriterionCustomizersRequest, + MutateAdGroupCriterionCustomizersResponse, +) +from .ad_group_criterion_label_service import ( + AdGroupCriterionLabelOperation, + MutateAdGroupCriterionLabelResult, + MutateAdGroupCriterionLabelsRequest, + MutateAdGroupCriterionLabelsResponse, +) +from .ad_group_criterion_service import ( + AdGroupCriterionOperation, + MutateAdGroupCriteriaRequest, + MutateAdGroupCriteriaResponse, + MutateAdGroupCriterionResult, +) +from .ad_group_customizer_service import ( + AdGroupCustomizerOperation, + MutateAdGroupCustomizerResult, + MutateAdGroupCustomizersRequest, + MutateAdGroupCustomizersResponse, +) +from .ad_group_label_service import ( + AdGroupLabelOperation, + MutateAdGroupLabelResult, + MutateAdGroupLabelsRequest, + MutateAdGroupLabelsResponse, +) +from .ad_group_service import ( + AdGroupOperation, + MutateAdGroupResult, + MutateAdGroupsRequest, + MutateAdGroupsResponse, +) +from .ad_parameter_service import ( + AdParameterOperation, + MutateAdParameterResult, + MutateAdParametersRequest, + MutateAdParametersResponse, +) +from .ad_service import ( + AdOperation, + MutateAdResult, + MutateAdsRequest, + MutateAdsResponse, +) +from .asset_generation_service import ( + AssetGenerationExistingContext, + FinalUrlImageGenerationInput, + FreeformImageGenerationInput, + GeneratedImage, + GeneratedText, + GenerateImagesRequest, + GenerateImagesResponse, + GenerateTextRequest, + GenerateTextResponse, + ProductRecontextGenerationImageInput, + SourceImage, +) +from .asset_group_asset_service import ( + AssetGroupAssetOperation, + MutateAssetGroupAssetResult, + MutateAssetGroupAssetsRequest, + MutateAssetGroupAssetsResponse, +) +from .asset_group_listing_group_filter_service import ( + AssetGroupListingGroupFilterOperation, + MutateAssetGroupListingGroupFilterResult, + MutateAssetGroupListingGroupFiltersRequest, + MutateAssetGroupListingGroupFiltersResponse, +) +from .asset_group_service import ( + AssetGroupOperation, + MutateAssetGroupResult, + MutateAssetGroupsRequest, + MutateAssetGroupsResponse, +) +from .asset_group_signal_service import ( + AssetGroupSignalOperation, + MutateAssetGroupSignalResult, + MutateAssetGroupSignalsRequest, + MutateAssetGroupSignalsResponse, +) +from .asset_service import ( + AssetOperation, + MutateAssetResult, + MutateAssetsRequest, + MutateAssetsResponse, +) +from .asset_set_asset_service import ( + AssetSetAssetOperation, + MutateAssetSetAssetResult, + MutateAssetSetAssetsRequest, + MutateAssetSetAssetsResponse, +) +from .asset_set_service import ( + AssetSetOperation, + MutateAssetSetResult, + MutateAssetSetsRequest, + MutateAssetSetsResponse, +) +from .audience_insights_service import ( + AudienceCompositionAttribute, + AudienceCompositionAttributeCluster, + AudienceCompositionMetrics, + AudienceCompositionSection, + AudienceInsightsDimensions, + AudienceOverlapItem, + DimensionOverlapResult, + GenerateAudienceCompositionInsightsRequest, + GenerateAudienceCompositionInsightsResponse, + GenerateAudienceDefinitionRequest, + GenerateAudienceDefinitionResponse, + GenerateAudienceOverlapInsightsRequest, + GenerateAudienceOverlapInsightsResponse, + GenerateInsightsFinderReportRequest, + GenerateInsightsFinderReportResponse, + GenerateSuggestedTargetingInsightsRequest, + GenerateSuggestedTargetingInsightsResponse, + GenerateTargetingSuggestionMetricsRequest, + GenerateTargetingSuggestionMetricsResponse, + InsightsAudience, + InsightsAudienceDefinition, + InsightsAudienceDescription, + ListAudienceInsightsAttributesRequest, + ListAudienceInsightsAttributesResponse, + ListInsightsEligibleDatesRequest, + ListInsightsEligibleDatesResponse, + TargetingSuggestionMetrics, +) +from .audience_service import ( + AudienceOperation, + MutateAudienceResult, + MutateAudiencesRequest, + MutateAudiencesResponse, +) +from .automatically_created_asset_removal_service import ( + RemoveCampaignAutomaticallyCreatedAssetOperation, + RemoveCampaignAutomaticallyCreatedAssetRequest, + RemoveCampaignAutomaticallyCreatedAssetResponse, +) +from .batch_job_service import ( + AddBatchJobOperationsRequest, + AddBatchJobOperationsResponse, + BatchJobOperation, + BatchJobResult, + ListBatchJobResultsRequest, + ListBatchJobResultsResponse, + MutateBatchJobRequest, + MutateBatchJobResponse, + MutateBatchJobResult, + RunBatchJobRequest, +) +from .benchmarks_service import ( + BenchmarksLocation, + BenchmarksProductMetadata, + BenchmarksSource, + BenchmarksSourceMetadata, + BreakdownDefinition, + BreakdownKey, + BreakdownMetrics, + GenerateBenchmarksMetricsRequest, + GenerateBenchmarksMetricsResponse, + IndustryVerticalInfo, + ListBenchmarksAvailableDatesRequest, + ListBenchmarksAvailableDatesResponse, + ListBenchmarksLocationsRequest, + ListBenchmarksLocationsResponse, + ListBenchmarksProductsRequest, + ListBenchmarksProductsResponse, + ListBenchmarksSourcesRequest, + ListBenchmarksSourcesResponse, + Metrics, + ProductFilter, + RateMetrics, +) +from .bidding_data_exclusion_service import ( + BiddingDataExclusionOperation, + MutateBiddingDataExclusionsRequest, + MutateBiddingDataExclusionsResponse, + MutateBiddingDataExclusionsResult, +) +from .bidding_seasonality_adjustment_service import ( + BiddingSeasonalityAdjustmentOperation, + MutateBiddingSeasonalityAdjustmentsRequest, + MutateBiddingSeasonalityAdjustmentsResponse, + MutateBiddingSeasonalityAdjustmentsResult, +) +from .bidding_strategy_service import ( + BiddingStrategyOperation, + MutateBiddingStrategiesRequest, + MutateBiddingStrategiesResponse, + MutateBiddingStrategyResult, +) +from .billing_setup_service import ( + BillingSetupOperation, + MutateBillingSetupRequest, + MutateBillingSetupResponse, + MutateBillingSetupResult, +) +from .brand_suggestion_service import ( + BrandSuggestion, + SuggestBrandsRequest, + SuggestBrandsResponse, +) +from .campaign_asset_service import ( + CampaignAssetOperation, + MutateCampaignAssetResult, + MutateCampaignAssetsRequest, + MutateCampaignAssetsResponse, +) +from .campaign_asset_set_service import ( + CampaignAssetSetOperation, + MutateCampaignAssetSetResult, + MutateCampaignAssetSetsRequest, + MutateCampaignAssetSetsResponse, +) +from .campaign_bid_modifier_service import ( + CampaignBidModifierOperation, + MutateCampaignBidModifierResult, + MutateCampaignBidModifiersRequest, + MutateCampaignBidModifiersResponse, +) +from .campaign_budget_service import ( + CampaignBudgetOperation, + MutateCampaignBudgetResult, + MutateCampaignBudgetsRequest, + MutateCampaignBudgetsResponse, +) +from .campaign_conversion_goal_service import ( + CampaignConversionGoalOperation, + MutateCampaignConversionGoalResult, + MutateCampaignConversionGoalsRequest, + MutateCampaignConversionGoalsResponse, +) +from .campaign_criterion_service import ( + CampaignCriterionOperation, + MutateCampaignCriteriaRequest, + MutateCampaignCriteriaResponse, + MutateCampaignCriterionResult, +) +from .campaign_customizer_service import ( + CampaignCustomizerOperation, + MutateCampaignCustomizerResult, + MutateCampaignCustomizersRequest, + MutateCampaignCustomizersResponse, +) +from .campaign_draft_service import ( + CampaignDraftOperation, + ListCampaignDraftAsyncErrorsRequest, + ListCampaignDraftAsyncErrorsResponse, + MutateCampaignDraftResult, + MutateCampaignDraftsRequest, + MutateCampaignDraftsResponse, + PromoteCampaignDraftRequest, +) +from .campaign_goal_config_service import ( + CampaignGoalConfigOperation, + MutateCampaignGoalConfigResult, + MutateCampaignGoalConfigsRequest, + MutateCampaignGoalConfigsResponse, +) +from .campaign_group_service import ( + CampaignGroupOperation, + MutateCampaignGroupResult, + MutateCampaignGroupsRequest, + MutateCampaignGroupsResponse, +) +from .campaign_label_service import ( + CampaignLabelOperation, + MutateCampaignLabelResult, + MutateCampaignLabelsRequest, + MutateCampaignLabelsResponse, +) +from .campaign_lifecycle_goal_service import ( + CampaignLifecycleGoalOperation, + ConfigureCampaignLifecycleGoalsRequest, + ConfigureCampaignLifecycleGoalsResponse, + ConfigureCampaignLifecycleGoalsResult, +) +from .campaign_service import ( + BrandCampaignAssets, + CampaignOperation, + EnablementResult, + EnableOperation, + EnablePMaxBrandGuidelinesRequest, + EnablePMaxBrandGuidelinesResponse, + MutateCampaignResult, + MutateCampaignsRequest, + MutateCampaignsResponse, +) +from .campaign_shared_set_service import ( + CampaignSharedSetOperation, + MutateCampaignSharedSetResult, + MutateCampaignSharedSetsRequest, + MutateCampaignSharedSetsResponse, +) +from .content_creator_insights_service import ( + GenerateCreatorInsightsRequest, + GenerateCreatorInsightsResponse, + GenerateTrendingInsightsRequest, + GenerateTrendingInsightsResponse, + LanguageDistribution, + SearchAudience, + SearchTopics, + TrendInsight, + TrendInsightDataPoint, + TrendInsightMetrics, + YouTubeChannelInsights, + YouTubeCreatorInsights, + YouTubeMetrics, +) +from .conversion_action_service import ( + ConversionActionOperation, + MutateConversionActionResult, + MutateConversionActionsRequest, + MutateConversionActionsResponse, +) +from .conversion_adjustment_upload_service import ( + ConversionAdjustment, + ConversionAdjustmentResult, + GclidDateTimePair, + RestatementValue, + UploadConversionAdjustmentsRequest, + UploadConversionAdjustmentsResponse, +) +from .conversion_custom_variable_service import ( + ConversionCustomVariableOperation, + MutateConversionCustomVariableResult, + MutateConversionCustomVariablesRequest, + MutateConversionCustomVariablesResponse, +) +from .conversion_goal_campaign_config_service import ( + ConversionGoalCampaignConfigOperation, + MutateConversionGoalCampaignConfigResult, + MutateConversionGoalCampaignConfigsRequest, + MutateConversionGoalCampaignConfigsResponse, +) +from .conversion_upload_service import ( + CallConversion, + CallConversionResult, + CartData, + ClickConversion, + ClickConversionResult, + CustomVariable, + ExternalAttributionData, + SessionAttributeKeyValuePair, + SessionAttributesKeyValuePairs, + UploadCallConversionsRequest, + UploadCallConversionsResponse, + UploadClickConversionsRequest, + UploadClickConversionsResponse, +) +from .conversion_value_rule_service import ( + ConversionValueRuleOperation, + MutateConversionValueRuleResult, + MutateConversionValueRulesRequest, + MutateConversionValueRulesResponse, +) +from .conversion_value_rule_set_service import ( + ConversionValueRuleSetOperation, + MutateConversionValueRuleSetResult, + MutateConversionValueRuleSetsRequest, + MutateConversionValueRuleSetsResponse, +) +from .custom_audience_service import ( + CustomAudienceOperation, + MutateCustomAudienceResult, + MutateCustomAudiencesRequest, + MutateCustomAudiencesResponse, +) +from .custom_conversion_goal_service import ( + CustomConversionGoalOperation, + MutateCustomConversionGoalResult, + MutateCustomConversionGoalsRequest, + MutateCustomConversionGoalsResponse, +) +from .custom_interest_service import ( + CustomInterestOperation, + MutateCustomInterestResult, + MutateCustomInterestsRequest, + MutateCustomInterestsResponse, +) +from .customer_asset_service import ( + CustomerAssetOperation, + MutateCustomerAssetResult, + MutateCustomerAssetsRequest, + MutateCustomerAssetsResponse, +) +from .customer_asset_set_service import ( + CustomerAssetSetOperation, + MutateCustomerAssetSetResult, + MutateCustomerAssetSetsRequest, + MutateCustomerAssetSetsResponse, +) +from .customer_client_link_service import ( + CustomerClientLinkOperation, + MutateCustomerClientLinkRequest, + MutateCustomerClientLinkResponse, + MutateCustomerClientLinkResult, +) +from .customer_conversion_goal_service import ( + CustomerConversionGoalOperation, + MutateCustomerConversionGoalResult, + MutateCustomerConversionGoalsRequest, + MutateCustomerConversionGoalsResponse, +) +from .customer_customizer_service import ( + CustomerCustomizerOperation, + MutateCustomerCustomizerResult, + MutateCustomerCustomizersRequest, + MutateCustomerCustomizersResponse, +) +from .customer_label_service import ( + CustomerLabelOperation, + MutateCustomerLabelResult, + MutateCustomerLabelsRequest, + MutateCustomerLabelsResponse, +) +from .customer_lifecycle_goal_service import ( + ConfigureCustomerLifecycleGoalsRequest, + ConfigureCustomerLifecycleGoalsResponse, + ConfigureCustomerLifecycleGoalsResult, + CustomerLifecycleGoalOperation, +) +from .customer_manager_link_service import ( + CustomerManagerLinkOperation, + MoveManagerLinkRequest, + MoveManagerLinkResponse, + MutateCustomerManagerLinkRequest, + MutateCustomerManagerLinkResponse, + MutateCustomerManagerLinkResult, +) +from .customer_negative_criterion_service import ( + CustomerNegativeCriterionOperation, + MutateCustomerNegativeCriteriaRequest, + MutateCustomerNegativeCriteriaResponse, + MutateCustomerNegativeCriteriaResult, +) +from .customer_service import ( + CreateCustomerClientRequest, + CreateCustomerClientResponse, + CustomerOperation, + ListAccessibleCustomersRequest, + ListAccessibleCustomersResponse, + MutateCustomerRequest, + MutateCustomerResponse, + MutateCustomerResult, +) +from .customer_sk_ad_network_conversion_value_schema_service import ( + CustomerSkAdNetworkConversionValueSchemaOperation, + MutateCustomerSkAdNetworkConversionValueSchemaRequest, + MutateCustomerSkAdNetworkConversionValueSchemaResponse, + MutateCustomerSkAdNetworkConversionValueSchemaResult, +) +from .customer_user_access_invitation_service import ( + CustomerUserAccessInvitationOperation, + MutateCustomerUserAccessInvitationRequest, + MutateCustomerUserAccessInvitationResponse, + MutateCustomerUserAccessInvitationResult, +) +from .customer_user_access_service import ( + CustomerUserAccessOperation, + MutateCustomerUserAccessRequest, + MutateCustomerUserAccessResponse, + MutateCustomerUserAccessResult, +) +from .customizer_attribute_service import ( + CustomizerAttributeOperation, + MutateCustomizerAttributeResult, + MutateCustomizerAttributesRequest, + MutateCustomizerAttributesResponse, +) +from .data_link_service import ( + CreateDataLinkRequest, + CreateDataLinkResponse, + RemoveDataLinkRequest, + RemoveDataLinkResponse, + UpdateDataLinkRequest, + UpdateDataLinkResponse, +) +from .experiment_arm_service import ( + ExperimentArmOperation, + MutateExperimentArmResult, + MutateExperimentArmsRequest, + MutateExperimentArmsResponse, +) +from .experiment_service import ( + CampaignBudgetMapping, + EndExperimentRequest, + ExperimentOperation, + GraduateExperimentRequest, + ListExperimentAsyncErrorsRequest, + ListExperimentAsyncErrorsResponse, + MutateExperimentResult, + MutateExperimentsRequest, + MutateExperimentsResponse, + PromoteExperimentMetadata, + PromoteExperimentRequest, + ScheduleExperimentMetadata, + ScheduleExperimentRequest, +) +from .geo_target_constant_service import ( + GeoTargetConstantSuggestion, + SuggestGeoTargetConstantsRequest, + SuggestGeoTargetConstantsResponse, +) +from .goal_service import ( + GoalOperation, + MutateGoalResult, + MutateGoalsRequest, + MutateGoalsResponse, +) +from .google_ads_field_service import ( + GetGoogleAdsFieldRequest, + SearchGoogleAdsFieldsRequest, + SearchGoogleAdsFieldsResponse, +) +from .google_ads_service import ( + GoogleAdsRow, + MetricAttributes, + MutateGoogleAdsRequest, + MutateGoogleAdsResponse, + MutateOperation, + MutateOperationResponse, + SearchGoogleAdsRequest, + SearchGoogleAdsResponse, + SearchGoogleAdsStreamRequest, + SearchGoogleAdsStreamResponse, + SearchSettings, +) +from .identity_verification_service import ( + GetIdentityVerificationRequest, + GetIdentityVerificationResponse, + IdentityVerification, + IdentityVerificationProgress, + IdentityVerificationRequirement, + StartIdentityVerificationRequest, +) +from .incentive_service import ( + ApplyIncentiveRequest, + ApplyIncentiveResponse, + CyoIncentives, + FetchIncentiveRequest, + FetchIncentiveResponse, + Incentive, + IncentiveOffer, +) +from .invoice_service import ( + ListInvoicesRequest, + ListInvoicesResponse, +) +from .keyword_plan_ad_group_keyword_service import ( + KeywordPlanAdGroupKeywordOperation, + MutateKeywordPlanAdGroupKeywordResult, + MutateKeywordPlanAdGroupKeywordsRequest, + MutateKeywordPlanAdGroupKeywordsResponse, +) +from .keyword_plan_ad_group_service import ( + KeywordPlanAdGroupOperation, + MutateKeywordPlanAdGroupResult, + MutateKeywordPlanAdGroupsRequest, + MutateKeywordPlanAdGroupsResponse, +) +from .keyword_plan_campaign_keyword_service import ( + KeywordPlanCampaignKeywordOperation, + MutateKeywordPlanCampaignKeywordResult, + MutateKeywordPlanCampaignKeywordsRequest, + MutateKeywordPlanCampaignKeywordsResponse, +) +from .keyword_plan_campaign_service import ( + KeywordPlanCampaignOperation, + MutateKeywordPlanCampaignResult, + MutateKeywordPlanCampaignsRequest, + MutateKeywordPlanCampaignsResponse, +) +from .keyword_plan_idea_service import ( + AdGroupKeywordSuggestion, + CampaignToForecast, + ForecastAdGroup, + GenerateAdGroupThemesRequest, + GenerateAdGroupThemesResponse, + GenerateKeywordForecastMetricsRequest, + GenerateKeywordForecastMetricsResponse, + GenerateKeywordHistoricalMetricsRequest, + GenerateKeywordHistoricalMetricsResponse, + GenerateKeywordHistoricalMetricsResult, + GenerateKeywordIdeaResponse, + GenerateKeywordIdeaResult, + GenerateKeywordIdeasRequest, + KeywordAndUrlSeed, + KeywordForecastMetrics, + KeywordSeed, + ManualCpcBiddingStrategy, + MaximizeClicksBiddingStrategy, + MaximizeConversionsBiddingStrategy, + SiteSeed, + UnusableAdGroup, + UrlSeed, +) +from .keyword_plan_service import ( + KeywordPlanOperation, + MutateKeywordPlansRequest, + MutateKeywordPlansResponse, + MutateKeywordPlansResult, +) +from .keyword_theme_constant_service import ( + SuggestKeywordThemeConstantsRequest, + SuggestKeywordThemeConstantsResponse, +) +from .label_service import ( + LabelOperation, + MutateLabelResult, + MutateLabelsRequest, + MutateLabelsResponse, +) +from .local_services_lead_service import ( + AppendLeadConversationRequest, + AppendLeadConversationResponse, + Conversation, + ConversationOrError, + ProvideLeadFeedbackRequest, + ProvideLeadFeedbackResponse, + SurveyDissatisfied, + SurveySatisfied, +) +from .offline_user_data_job_service import ( + AddOfflineUserDataJobOperationsRequest, + AddOfflineUserDataJobOperationsResponse, + CreateOfflineUserDataJobRequest, + CreateOfflineUserDataJobResponse, + OfflineUserDataJobOperation, + RunOfflineUserDataJobRequest, +) +from .payments_account_service import ( + ListPaymentsAccountsRequest, + ListPaymentsAccountsResponse, +) +from .product_link_invitation_service import ( + CreateProductLinkInvitationRequest, + CreateProductLinkInvitationResponse, + RemoveProductLinkInvitationRequest, + RemoveProductLinkInvitationResponse, + UpdateProductLinkInvitationRequest, + UpdateProductLinkInvitationResponse, +) +from .product_link_service import ( + CreateProductLinkRequest, + CreateProductLinkResponse, + RemoveProductLinkRequest, + RemoveProductLinkResponse, +) +from .reach_plan_service import ( + AdvancedProductTargeting, + AudienceTargeting, + CampaignDuration, + ConversionRateSuggestion, + EffectiveFrequencyBreakdown, + EffectiveFrequencyLimit, + Forecast, + ForecastMetricOptions, + FrequencyCap, + GenerateConversionRatesRequest, + GenerateConversionRatesResponse, + GenerateReachForecastRequest, + GenerateReachForecastResponse, + ListPlannableLocationsRequest, + ListPlannableLocationsResponse, + ListPlannableProductsRequest, + ListPlannableProductsResponse, + ListPlannableUserInterestsRequest, + ListPlannableUserInterestsResponse, + ListPlannableUserListsRequest, + ListPlannableUserListsResponse, + OnTargetAudienceMetrics, + PlannableLocation, + PlannableTargeting, + PlannableUserInterest, + PlannableUserList, + PlannableUserListMetadata, + PlannedProduct, + PlannedProductForecast, + PlannedProductReachForecast, + ProductCoreAttributes, + ProductMetadata, + ReachCurve, + ReachForecast, + SurfaceTargeting, + SurfaceTargetingCombinations, + TargetFrequencySettings, + Targeting, + YouTubeSelectLineUp, + YouTubeSelectLineUpTargeting, + YouTubeSelectSettings, +) +from .recommendation_service import ( + ApplyRecommendationOperation, + ApplyRecommendationRequest, + ApplyRecommendationResponse, + ApplyRecommendationResult, + DismissRecommendationRequest, + DismissRecommendationResponse, + GenerateRecommendationsRequest, + GenerateRecommendationsResponse, +) +from .recommendation_subscription_service import ( + MutateRecommendationSubscriptionRequest, + MutateRecommendationSubscriptionResponse, + MutateRecommendationSubscriptionResult, + RecommendationSubscriptionOperation, +) +from .remarketing_action_service import ( + MutateRemarketingActionResult, + MutateRemarketingActionsRequest, + MutateRemarketingActionsResponse, + RemarketingActionOperation, +) +from .reservation_service import ( + BookCampaignsRequest, + BookCampaignsResponse, + QuoteCampaignsRequest, + QuoteCampaignsResponse, +) +from .shareable_preview_service import ( + GenerateShareablePreviewsRequest, + GenerateShareablePreviewsResponse, +) +from .shared_criterion_service import ( + MutateSharedCriteriaRequest, + MutateSharedCriteriaResponse, + MutateSharedCriterionResult, + SharedCriterionOperation, +) +from .shared_set_service import ( + MutateSharedSetResult, + MutateSharedSetsRequest, + MutateSharedSetsResponse, + SharedSetOperation, +) +from .smart_campaign_setting_service import ( + GetSmartCampaignStatusRequest, + GetSmartCampaignStatusResponse, + MutateSmartCampaignSettingResult, + MutateSmartCampaignSettingsRequest, + MutateSmartCampaignSettingsResponse, + SmartCampaignEligibleDetails, + SmartCampaignEndedDetails, + SmartCampaignNotEligibleDetails, + SmartCampaignPausedDetails, + SmartCampaignRemovedDetails, + SmartCampaignSettingOperation, +) +from .smart_campaign_suggest_service import ( + SmartCampaignSuggestionInfo, + SuggestKeywordThemesRequest, + SuggestKeywordThemesResponse, + SuggestSmartCampaignAdRequest, + SuggestSmartCampaignAdResponse, + SuggestSmartCampaignBudgetOptionsRequest, + SuggestSmartCampaignBudgetOptionsResponse, +) +from .third_party_app_analytics_link_service import ( + RegenerateShareableLinkIdRequest, + RegenerateShareableLinkIdResponse, +) +from .travel_asset_suggestion_service import ( + HotelAssetSuggestion, + HotelImageAsset, + HotelTextAsset, + SuggestTravelAssetsRequest, + SuggestTravelAssetsResponse, +) +from .user_data_service import ( + UploadUserDataRequest, + UploadUserDataResponse, + UserDataOperation, +) +from .user_list_customer_type_service import ( + MutateUserListCustomerTypeResult, + MutateUserListCustomerTypesRequest, + MutateUserListCustomerTypesResponse, + UserListCustomerTypeOperation, +) +from .user_list_service import ( + MutateUserListResult, + MutateUserListsRequest, + MutateUserListsResponse, + UserListOperation, +) +from .youtube_video_upload_service import ( + CreateYouTubeVideoUploadRequest, + CreateYouTubeVideoUploadResponse, + RemoveYouTubeVideoUploadRequest, + RemoveYouTubeVideoUploadResponse, + UpdateYouTubeVideoUploadRequest, + UpdateYouTubeVideoUploadResponse, +) + +__all__ = ( + "AccountBudgetProposalOperation", + "MutateAccountBudgetProposalRequest", + "MutateAccountBudgetProposalResponse", + "MutateAccountBudgetProposalResult", + "AccountLinkOperation", + "CreateAccountLinkRequest", + "CreateAccountLinkResponse", + "MutateAccountLinkRequest", + "MutateAccountLinkResponse", + "MutateAccountLinkResult", + "AdGroupAdLabelOperation", + "MutateAdGroupAdLabelResult", + "MutateAdGroupAdLabelsRequest", + "MutateAdGroupAdLabelsResponse", + "AdGroupAdOperation", + "AssetsWithFieldType", + "MutateAdGroupAdResult", + "MutateAdGroupAdsRequest", + "MutateAdGroupAdsResponse", + "RemoveAutomaticallyCreatedAssetsRequest", + "AdGroupAssetOperation", + "MutateAdGroupAssetResult", + "MutateAdGroupAssetsRequest", + "MutateAdGroupAssetsResponse", + "AdGroupAssetSetOperation", + "MutateAdGroupAssetSetResult", + "MutateAdGroupAssetSetsRequest", + "MutateAdGroupAssetSetsResponse", + "AdGroupBidModifierOperation", + "MutateAdGroupBidModifierResult", + "MutateAdGroupBidModifiersRequest", + "MutateAdGroupBidModifiersResponse", + "AdGroupCriterionCustomizerOperation", + "MutateAdGroupCriterionCustomizerResult", + "MutateAdGroupCriterionCustomizersRequest", + "MutateAdGroupCriterionCustomizersResponse", + "AdGroupCriterionLabelOperation", + "MutateAdGroupCriterionLabelResult", + "MutateAdGroupCriterionLabelsRequest", + "MutateAdGroupCriterionLabelsResponse", + "AdGroupCriterionOperation", + "MutateAdGroupCriteriaRequest", + "MutateAdGroupCriteriaResponse", + "MutateAdGroupCriterionResult", + "AdGroupCustomizerOperation", + "MutateAdGroupCustomizerResult", + "MutateAdGroupCustomizersRequest", + "MutateAdGroupCustomizersResponse", + "AdGroupLabelOperation", + "MutateAdGroupLabelResult", + "MutateAdGroupLabelsRequest", + "MutateAdGroupLabelsResponse", + "AdGroupOperation", + "MutateAdGroupResult", + "MutateAdGroupsRequest", + "MutateAdGroupsResponse", + "AdParameterOperation", + "MutateAdParameterResult", + "MutateAdParametersRequest", + "MutateAdParametersResponse", + "AdOperation", + "MutateAdResult", + "MutateAdsRequest", + "MutateAdsResponse", + "AssetGenerationExistingContext", + "FinalUrlImageGenerationInput", + "FreeformImageGenerationInput", + "GeneratedImage", + "GeneratedText", + "GenerateImagesRequest", + "GenerateImagesResponse", + "GenerateTextRequest", + "GenerateTextResponse", + "ProductRecontextGenerationImageInput", + "SourceImage", + "AssetGroupAssetOperation", + "MutateAssetGroupAssetResult", + "MutateAssetGroupAssetsRequest", + "MutateAssetGroupAssetsResponse", + "AssetGroupListingGroupFilterOperation", + "MutateAssetGroupListingGroupFilterResult", + "MutateAssetGroupListingGroupFiltersRequest", + "MutateAssetGroupListingGroupFiltersResponse", + "AssetGroupOperation", + "MutateAssetGroupResult", + "MutateAssetGroupsRequest", + "MutateAssetGroupsResponse", + "AssetGroupSignalOperation", + "MutateAssetGroupSignalResult", + "MutateAssetGroupSignalsRequest", + "MutateAssetGroupSignalsResponse", + "AssetOperation", + "MutateAssetResult", + "MutateAssetsRequest", + "MutateAssetsResponse", + "AssetSetAssetOperation", + "MutateAssetSetAssetResult", + "MutateAssetSetAssetsRequest", + "MutateAssetSetAssetsResponse", + "AssetSetOperation", + "MutateAssetSetResult", + "MutateAssetSetsRequest", + "MutateAssetSetsResponse", + "AudienceCompositionAttribute", + "AudienceCompositionAttributeCluster", + "AudienceCompositionMetrics", + "AudienceCompositionSection", + "AudienceInsightsDimensions", + "AudienceOverlapItem", + "DimensionOverlapResult", + "GenerateAudienceCompositionInsightsRequest", + "GenerateAudienceCompositionInsightsResponse", + "GenerateAudienceDefinitionRequest", + "GenerateAudienceDefinitionResponse", + "GenerateAudienceOverlapInsightsRequest", + "GenerateAudienceOverlapInsightsResponse", + "GenerateInsightsFinderReportRequest", + "GenerateInsightsFinderReportResponse", + "GenerateSuggestedTargetingInsightsRequest", + "GenerateSuggestedTargetingInsightsResponse", + "GenerateTargetingSuggestionMetricsRequest", + "GenerateTargetingSuggestionMetricsResponse", + "InsightsAudience", + "InsightsAudienceDefinition", + "InsightsAudienceDescription", + "ListAudienceInsightsAttributesRequest", + "ListAudienceInsightsAttributesResponse", + "ListInsightsEligibleDatesRequest", + "ListInsightsEligibleDatesResponse", + "TargetingSuggestionMetrics", + "AudienceOperation", + "MutateAudienceResult", + "MutateAudiencesRequest", + "MutateAudiencesResponse", + "RemoveCampaignAutomaticallyCreatedAssetOperation", + "RemoveCampaignAutomaticallyCreatedAssetRequest", + "RemoveCampaignAutomaticallyCreatedAssetResponse", + "AddBatchJobOperationsRequest", + "AddBatchJobOperationsResponse", + "BatchJobOperation", + "BatchJobResult", + "ListBatchJobResultsRequest", + "ListBatchJobResultsResponse", + "MutateBatchJobRequest", + "MutateBatchJobResponse", + "MutateBatchJobResult", + "RunBatchJobRequest", + "BenchmarksLocation", + "BenchmarksProductMetadata", + "BenchmarksSource", + "BenchmarksSourceMetadata", + "BreakdownDefinition", + "BreakdownKey", + "BreakdownMetrics", + "GenerateBenchmarksMetricsRequest", + "GenerateBenchmarksMetricsResponse", + "IndustryVerticalInfo", + "ListBenchmarksAvailableDatesRequest", + "ListBenchmarksAvailableDatesResponse", + "ListBenchmarksLocationsRequest", + "ListBenchmarksLocationsResponse", + "ListBenchmarksProductsRequest", + "ListBenchmarksProductsResponse", + "ListBenchmarksSourcesRequest", + "ListBenchmarksSourcesResponse", + "Metrics", + "ProductFilter", + "RateMetrics", + "BiddingDataExclusionOperation", + "MutateBiddingDataExclusionsRequest", + "MutateBiddingDataExclusionsResponse", + "MutateBiddingDataExclusionsResult", + "BiddingSeasonalityAdjustmentOperation", + "MutateBiddingSeasonalityAdjustmentsRequest", + "MutateBiddingSeasonalityAdjustmentsResponse", + "MutateBiddingSeasonalityAdjustmentsResult", + "BiddingStrategyOperation", + "MutateBiddingStrategiesRequest", + "MutateBiddingStrategiesResponse", + "MutateBiddingStrategyResult", + "BillingSetupOperation", + "MutateBillingSetupRequest", + "MutateBillingSetupResponse", + "MutateBillingSetupResult", + "BrandSuggestion", + "SuggestBrandsRequest", + "SuggestBrandsResponse", + "CampaignAssetOperation", + "MutateCampaignAssetResult", + "MutateCampaignAssetsRequest", + "MutateCampaignAssetsResponse", + "CampaignAssetSetOperation", + "MutateCampaignAssetSetResult", + "MutateCampaignAssetSetsRequest", + "MutateCampaignAssetSetsResponse", + "CampaignBidModifierOperation", + "MutateCampaignBidModifierResult", + "MutateCampaignBidModifiersRequest", + "MutateCampaignBidModifiersResponse", + "CampaignBudgetOperation", + "MutateCampaignBudgetResult", + "MutateCampaignBudgetsRequest", + "MutateCampaignBudgetsResponse", + "CampaignConversionGoalOperation", + "MutateCampaignConversionGoalResult", + "MutateCampaignConversionGoalsRequest", + "MutateCampaignConversionGoalsResponse", + "CampaignCriterionOperation", + "MutateCampaignCriteriaRequest", + "MutateCampaignCriteriaResponse", + "MutateCampaignCriterionResult", + "CampaignCustomizerOperation", + "MutateCampaignCustomizerResult", + "MutateCampaignCustomizersRequest", + "MutateCampaignCustomizersResponse", + "CampaignDraftOperation", + "ListCampaignDraftAsyncErrorsRequest", + "ListCampaignDraftAsyncErrorsResponse", + "MutateCampaignDraftResult", + "MutateCampaignDraftsRequest", + "MutateCampaignDraftsResponse", + "PromoteCampaignDraftRequest", + "CampaignGoalConfigOperation", + "MutateCampaignGoalConfigResult", + "MutateCampaignGoalConfigsRequest", + "MutateCampaignGoalConfigsResponse", + "CampaignGroupOperation", + "MutateCampaignGroupResult", + "MutateCampaignGroupsRequest", + "MutateCampaignGroupsResponse", + "CampaignLabelOperation", + "MutateCampaignLabelResult", + "MutateCampaignLabelsRequest", + "MutateCampaignLabelsResponse", + "CampaignLifecycleGoalOperation", + "ConfigureCampaignLifecycleGoalsRequest", + "ConfigureCampaignLifecycleGoalsResponse", + "ConfigureCampaignLifecycleGoalsResult", + "BrandCampaignAssets", + "CampaignOperation", + "EnablementResult", + "EnableOperation", + "EnablePMaxBrandGuidelinesRequest", + "EnablePMaxBrandGuidelinesResponse", + "MutateCampaignResult", + "MutateCampaignsRequest", + "MutateCampaignsResponse", + "CampaignSharedSetOperation", + "MutateCampaignSharedSetResult", + "MutateCampaignSharedSetsRequest", + "MutateCampaignSharedSetsResponse", + "GenerateCreatorInsightsRequest", + "GenerateCreatorInsightsResponse", + "GenerateTrendingInsightsRequest", + "GenerateTrendingInsightsResponse", + "LanguageDistribution", + "SearchAudience", + "SearchTopics", + "TrendInsight", + "TrendInsightDataPoint", + "TrendInsightMetrics", + "YouTubeChannelInsights", + "YouTubeCreatorInsights", + "YouTubeMetrics", + "ConversionActionOperation", + "MutateConversionActionResult", + "MutateConversionActionsRequest", + "MutateConversionActionsResponse", + "ConversionAdjustment", + "ConversionAdjustmentResult", + "GclidDateTimePair", + "RestatementValue", + "UploadConversionAdjustmentsRequest", + "UploadConversionAdjustmentsResponse", + "ConversionCustomVariableOperation", + "MutateConversionCustomVariableResult", + "MutateConversionCustomVariablesRequest", + "MutateConversionCustomVariablesResponse", + "ConversionGoalCampaignConfigOperation", + "MutateConversionGoalCampaignConfigResult", + "MutateConversionGoalCampaignConfigsRequest", + "MutateConversionGoalCampaignConfigsResponse", + "CallConversion", + "CallConversionResult", + "CartData", + "ClickConversion", + "ClickConversionResult", + "CustomVariable", + "ExternalAttributionData", + "SessionAttributeKeyValuePair", + "SessionAttributesKeyValuePairs", + "UploadCallConversionsRequest", + "UploadCallConversionsResponse", + "UploadClickConversionsRequest", + "UploadClickConversionsResponse", + "ConversionValueRuleOperation", + "MutateConversionValueRuleResult", + "MutateConversionValueRulesRequest", + "MutateConversionValueRulesResponse", + "ConversionValueRuleSetOperation", + "MutateConversionValueRuleSetResult", + "MutateConversionValueRuleSetsRequest", + "MutateConversionValueRuleSetsResponse", + "CustomAudienceOperation", + "MutateCustomAudienceResult", + "MutateCustomAudiencesRequest", + "MutateCustomAudiencesResponse", + "CustomConversionGoalOperation", + "MutateCustomConversionGoalResult", + "MutateCustomConversionGoalsRequest", + "MutateCustomConversionGoalsResponse", + "CustomInterestOperation", + "MutateCustomInterestResult", + "MutateCustomInterestsRequest", + "MutateCustomInterestsResponse", + "CustomerAssetOperation", + "MutateCustomerAssetResult", + "MutateCustomerAssetsRequest", + "MutateCustomerAssetsResponse", + "CustomerAssetSetOperation", + "MutateCustomerAssetSetResult", + "MutateCustomerAssetSetsRequest", + "MutateCustomerAssetSetsResponse", + "CustomerClientLinkOperation", + "MutateCustomerClientLinkRequest", + "MutateCustomerClientLinkResponse", + "MutateCustomerClientLinkResult", + "CustomerConversionGoalOperation", + "MutateCustomerConversionGoalResult", + "MutateCustomerConversionGoalsRequest", + "MutateCustomerConversionGoalsResponse", + "CustomerCustomizerOperation", + "MutateCustomerCustomizerResult", + "MutateCustomerCustomizersRequest", + "MutateCustomerCustomizersResponse", + "CustomerLabelOperation", + "MutateCustomerLabelResult", + "MutateCustomerLabelsRequest", + "MutateCustomerLabelsResponse", + "ConfigureCustomerLifecycleGoalsRequest", + "ConfigureCustomerLifecycleGoalsResponse", + "ConfigureCustomerLifecycleGoalsResult", + "CustomerLifecycleGoalOperation", + "CustomerManagerLinkOperation", + "MoveManagerLinkRequest", + "MoveManagerLinkResponse", + "MutateCustomerManagerLinkRequest", + "MutateCustomerManagerLinkResponse", + "MutateCustomerManagerLinkResult", + "CustomerNegativeCriterionOperation", + "MutateCustomerNegativeCriteriaRequest", + "MutateCustomerNegativeCriteriaResponse", + "MutateCustomerNegativeCriteriaResult", + "CreateCustomerClientRequest", + "CreateCustomerClientResponse", + "CustomerOperation", + "ListAccessibleCustomersRequest", + "ListAccessibleCustomersResponse", + "MutateCustomerRequest", + "MutateCustomerResponse", + "MutateCustomerResult", + "CustomerSkAdNetworkConversionValueSchemaOperation", + "MutateCustomerSkAdNetworkConversionValueSchemaRequest", + "MutateCustomerSkAdNetworkConversionValueSchemaResponse", + "MutateCustomerSkAdNetworkConversionValueSchemaResult", + "CustomerUserAccessInvitationOperation", + "MutateCustomerUserAccessInvitationRequest", + "MutateCustomerUserAccessInvitationResponse", + "MutateCustomerUserAccessInvitationResult", + "CustomerUserAccessOperation", + "MutateCustomerUserAccessRequest", + "MutateCustomerUserAccessResponse", + "MutateCustomerUserAccessResult", + "CustomizerAttributeOperation", + "MutateCustomizerAttributeResult", + "MutateCustomizerAttributesRequest", + "MutateCustomizerAttributesResponse", + "CreateDataLinkRequest", + "CreateDataLinkResponse", + "RemoveDataLinkRequest", + "RemoveDataLinkResponse", + "UpdateDataLinkRequest", + "UpdateDataLinkResponse", + "ExperimentArmOperation", + "MutateExperimentArmResult", + "MutateExperimentArmsRequest", + "MutateExperimentArmsResponse", + "CampaignBudgetMapping", + "EndExperimentRequest", + "ExperimentOperation", + "GraduateExperimentRequest", + "ListExperimentAsyncErrorsRequest", + "ListExperimentAsyncErrorsResponse", + "MutateExperimentResult", + "MutateExperimentsRequest", + "MutateExperimentsResponse", + "PromoteExperimentMetadata", + "PromoteExperimentRequest", + "ScheduleExperimentMetadata", + "ScheduleExperimentRequest", + "GeoTargetConstantSuggestion", + "SuggestGeoTargetConstantsRequest", + "SuggestGeoTargetConstantsResponse", + "GoalOperation", + "MutateGoalResult", + "MutateGoalsRequest", + "MutateGoalsResponse", + "GetGoogleAdsFieldRequest", + "SearchGoogleAdsFieldsRequest", + "SearchGoogleAdsFieldsResponse", + "GoogleAdsRow", + "MetricAttributes", + "MutateGoogleAdsRequest", + "MutateGoogleAdsResponse", + "MutateOperation", + "MutateOperationResponse", + "SearchGoogleAdsRequest", + "SearchGoogleAdsResponse", + "SearchGoogleAdsStreamRequest", + "SearchGoogleAdsStreamResponse", + "SearchSettings", + "GetIdentityVerificationRequest", + "GetIdentityVerificationResponse", + "IdentityVerification", + "IdentityVerificationProgress", + "IdentityVerificationRequirement", + "StartIdentityVerificationRequest", + "ApplyIncentiveRequest", + "ApplyIncentiveResponse", + "CyoIncentives", + "FetchIncentiveRequest", + "FetchIncentiveResponse", + "Incentive", + "IncentiveOffer", + "ListInvoicesRequest", + "ListInvoicesResponse", + "KeywordPlanAdGroupKeywordOperation", + "MutateKeywordPlanAdGroupKeywordResult", + "MutateKeywordPlanAdGroupKeywordsRequest", + "MutateKeywordPlanAdGroupKeywordsResponse", + "KeywordPlanAdGroupOperation", + "MutateKeywordPlanAdGroupResult", + "MutateKeywordPlanAdGroupsRequest", + "MutateKeywordPlanAdGroupsResponse", + "KeywordPlanCampaignKeywordOperation", + "MutateKeywordPlanCampaignKeywordResult", + "MutateKeywordPlanCampaignKeywordsRequest", + "MutateKeywordPlanCampaignKeywordsResponse", + "KeywordPlanCampaignOperation", + "MutateKeywordPlanCampaignResult", + "MutateKeywordPlanCampaignsRequest", + "MutateKeywordPlanCampaignsResponse", + "AdGroupKeywordSuggestion", + "CampaignToForecast", + "ForecastAdGroup", + "GenerateAdGroupThemesRequest", + "GenerateAdGroupThemesResponse", + "GenerateKeywordForecastMetricsRequest", + "GenerateKeywordForecastMetricsResponse", + "GenerateKeywordHistoricalMetricsRequest", + "GenerateKeywordHistoricalMetricsResponse", + "GenerateKeywordHistoricalMetricsResult", + "GenerateKeywordIdeaResponse", + "GenerateKeywordIdeaResult", + "GenerateKeywordIdeasRequest", + "KeywordAndUrlSeed", + "KeywordForecastMetrics", + "KeywordSeed", + "ManualCpcBiddingStrategy", + "MaximizeClicksBiddingStrategy", + "MaximizeConversionsBiddingStrategy", + "SiteSeed", + "UnusableAdGroup", + "UrlSeed", + "KeywordPlanOperation", + "MutateKeywordPlansRequest", + "MutateKeywordPlansResponse", + "MutateKeywordPlansResult", + "SuggestKeywordThemeConstantsRequest", + "SuggestKeywordThemeConstantsResponse", + "LabelOperation", + "MutateLabelResult", + "MutateLabelsRequest", + "MutateLabelsResponse", + "AppendLeadConversationRequest", + "AppendLeadConversationResponse", + "Conversation", + "ConversationOrError", + "ProvideLeadFeedbackRequest", + "ProvideLeadFeedbackResponse", + "SurveyDissatisfied", + "SurveySatisfied", + "AddOfflineUserDataJobOperationsRequest", + "AddOfflineUserDataJobOperationsResponse", + "CreateOfflineUserDataJobRequest", + "CreateOfflineUserDataJobResponse", + "OfflineUserDataJobOperation", + "RunOfflineUserDataJobRequest", + "ListPaymentsAccountsRequest", + "ListPaymentsAccountsResponse", + "CreateProductLinkInvitationRequest", + "CreateProductLinkInvitationResponse", + "RemoveProductLinkInvitationRequest", + "RemoveProductLinkInvitationResponse", + "UpdateProductLinkInvitationRequest", + "UpdateProductLinkInvitationResponse", + "CreateProductLinkRequest", + "CreateProductLinkResponse", + "RemoveProductLinkRequest", + "RemoveProductLinkResponse", + "AdvancedProductTargeting", + "AudienceTargeting", + "CampaignDuration", + "ConversionRateSuggestion", + "EffectiveFrequencyBreakdown", + "EffectiveFrequencyLimit", + "Forecast", + "ForecastMetricOptions", + "FrequencyCap", + "GenerateConversionRatesRequest", + "GenerateConversionRatesResponse", + "GenerateReachForecastRequest", + "GenerateReachForecastResponse", + "ListPlannableLocationsRequest", + "ListPlannableLocationsResponse", + "ListPlannableProductsRequest", + "ListPlannableProductsResponse", + "ListPlannableUserInterestsRequest", + "ListPlannableUserInterestsResponse", + "ListPlannableUserListsRequest", + "ListPlannableUserListsResponse", + "OnTargetAudienceMetrics", + "PlannableLocation", + "PlannableTargeting", + "PlannableUserInterest", + "PlannableUserList", + "PlannableUserListMetadata", + "PlannedProduct", + "PlannedProductForecast", + "PlannedProductReachForecast", + "ProductCoreAttributes", + "ProductMetadata", + "ReachCurve", + "ReachForecast", + "SurfaceTargeting", + "SurfaceTargetingCombinations", + "TargetFrequencySettings", + "Targeting", + "YouTubeSelectLineUp", + "YouTubeSelectLineUpTargeting", + "YouTubeSelectSettings", + "ApplyRecommendationOperation", + "ApplyRecommendationRequest", + "ApplyRecommendationResponse", + "ApplyRecommendationResult", + "DismissRecommendationRequest", + "DismissRecommendationResponse", + "GenerateRecommendationsRequest", + "GenerateRecommendationsResponse", + "MutateRecommendationSubscriptionRequest", + "MutateRecommendationSubscriptionResponse", + "MutateRecommendationSubscriptionResult", + "RecommendationSubscriptionOperation", + "MutateRemarketingActionResult", + "MutateRemarketingActionsRequest", + "MutateRemarketingActionsResponse", + "RemarketingActionOperation", + "BookCampaignsRequest", + "BookCampaignsResponse", + "QuoteCampaignsRequest", + "QuoteCampaignsResponse", + "GenerateShareablePreviewsRequest", + "GenerateShareablePreviewsResponse", + "MutateSharedCriteriaRequest", + "MutateSharedCriteriaResponse", + "MutateSharedCriterionResult", + "SharedCriterionOperation", + "MutateSharedSetResult", + "MutateSharedSetsRequest", + "MutateSharedSetsResponse", + "SharedSetOperation", + "GetSmartCampaignStatusRequest", + "GetSmartCampaignStatusResponse", + "MutateSmartCampaignSettingResult", + "MutateSmartCampaignSettingsRequest", + "MutateSmartCampaignSettingsResponse", + "SmartCampaignEligibleDetails", + "SmartCampaignEndedDetails", + "SmartCampaignNotEligibleDetails", + "SmartCampaignPausedDetails", + "SmartCampaignRemovedDetails", + "SmartCampaignSettingOperation", + "SmartCampaignSuggestionInfo", + "SuggestKeywordThemesRequest", + "SuggestKeywordThemesResponse", + "SuggestSmartCampaignAdRequest", + "SuggestSmartCampaignAdResponse", + "SuggestSmartCampaignBudgetOptionsRequest", + "SuggestSmartCampaignBudgetOptionsResponse", + "RegenerateShareableLinkIdRequest", + "RegenerateShareableLinkIdResponse", + "HotelAssetSuggestion", + "HotelImageAsset", + "HotelTextAsset", + "SuggestTravelAssetsRequest", + "SuggestTravelAssetsResponse", + "UploadUserDataRequest", + "UploadUserDataResponse", + "UserDataOperation", + "MutateUserListCustomerTypeResult", + "MutateUserListCustomerTypesRequest", + "MutateUserListCustomerTypesResponse", + "UserListCustomerTypeOperation", + "MutateUserListResult", + "MutateUserListsRequest", + "MutateUserListsResponse", + "UserListOperation", + "CreateYouTubeVideoUploadRequest", + "CreateYouTubeVideoUploadResponse", + "RemoveYouTubeVideoUploadRequest", + "RemoveYouTubeVideoUploadResponse", + "UpdateYouTubeVideoUploadRequest", + "UpdateYouTubeVideoUploadResponse", +) diff --git a/google/ads/googleads/v24/services/types/account_budget_proposal_service.py b/google/ads/googleads/v24/services/types/account_budget_proposal_service.py new file mode 100644 index 000000000..4aa85094e --- /dev/null +++ b/google/ads/googleads/v24/services/types/account_budget_proposal_service.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import account_budget_proposal +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAccountBudgetProposalRequest", + "AccountBudgetProposalOperation", + "MutateAccountBudgetProposalResponse", + "MutateAccountBudgetProposalResult", + }, +) + + +class MutateAccountBudgetProposalRequest(proto.Message): + r"""Request message for + [AccountBudgetProposalService.MutateAccountBudgetProposal][google.ads.googleads.v24.services.AccountBudgetProposalService.MutateAccountBudgetProposal]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + operation (google.ads.googleads.v24.services.types.AccountBudgetProposalOperation): + Required. The operation to perform on an + individual account-level budget proposal. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: "AccountBudgetProposalOperation" = proto.Field( + proto.MESSAGE, + number=2, + message="AccountBudgetProposalOperation", + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class AccountBudgetProposalOperation(proto.Message): + r"""A single operation to propose the creation of a new + account-level budget or edit/end/remove an existing one. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which budget fields + are modified. While budgets may be modified, + proposals that propose such modifications are + final. Therefore, update operations are not + supported for proposals. + + Proposals that modify budgets have the 'update' + proposal type. Specifying a mask for any other + proposal type is considered an error. + create (google.ads.googleads.v24.resources.types.AccountBudgetProposal): + Create operation: A new proposal to create a + new budget, edit an existing budget, end an + actively running budget, or remove an approved + budget scheduled to start in the future. + No resource name is expected for the new + proposal. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed proposal + is expected, in this format: + + ``customers/{customer_id}/accountBudgetProposals/{account_budget_proposal_id}`` + A request may be cancelled iff it is pending. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=3, + message=field_mask_pb2.FieldMask, + ) + create: account_budget_proposal.AccountBudgetProposal = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=account_budget_proposal.AccountBudgetProposal, + ) + remove: str = proto.Field( + proto.STRING, + number=1, + oneof="operation", + ) + + +class MutateAccountBudgetProposalResponse(proto.Message): + r"""Response message for account-level budget mutate operations. + + Attributes: + result (google.ads.googleads.v24.services.types.MutateAccountBudgetProposalResult): + The result of the mutate. + """ + + result: "MutateAccountBudgetProposalResult" = proto.Field( + proto.MESSAGE, + number=2, + message="MutateAccountBudgetProposalResult", + ) + + +class MutateAccountBudgetProposalResult(proto.Message): + r"""The result for the account budget proposal mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/account_link_service.py b/google/ads/googleads/v24/services/types/account_link_service.py new file mode 100644 index 000000000..74b25ac19 --- /dev/null +++ b/google/ads/googleads/v24/services/types/account_link_service.py @@ -0,0 +1,208 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import ( + account_link as gagr_account_link, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "CreateAccountLinkRequest", + "CreateAccountLinkResponse", + "MutateAccountLinkRequest", + "AccountLinkOperation", + "MutateAccountLinkResponse", + "MutateAccountLinkResult", + }, +) + + +class CreateAccountLinkRequest(proto.Message): + r"""Request message for + [AccountLinkService.CreateAccountLink][google.ads.googleads.v24.services.AccountLinkService.CreateAccountLink]. + + Attributes: + customer_id (str): + Required. The ID of the customer for which + the account link is created. + account_link (google.ads.googleads.v24.resources.types.AccountLink): + Required. The account link to be created. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + account_link: gagr_account_link.AccountLink = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_account_link.AccountLink, + ) + + +class CreateAccountLinkResponse(proto.Message): + r"""Response message for + [AccountLinkService.CreateAccountLink][google.ads.googleads.v24.services.AccountLinkService.CreateAccountLink]. + + Attributes: + resource_name (str): + Returned for successful operations. Resource + name of the account link. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class MutateAccountLinkRequest(proto.Message): + r"""Request message for + [AccountLinkService.MutateAccountLink][google.ads.googleads.v24.services.AccountLinkService.MutateAccountLink]. + + Attributes: + customer_id (str): + Required. The ID of the customer being + modified. + operation (google.ads.googleads.v24.services.types.AccountLinkOperation): + Required. The operation to perform on the + link. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: "AccountLinkOperation" = proto.Field( + proto.MESSAGE, + number=2, + message="AccountLinkOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class AccountLinkOperation(proto.Message): + r"""A single update on an account link. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + update (google.ads.googleads.v24.resources.types.AccountLink): + Update operation: The account link is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the account link to + remove is expected, in this format: + + ``customers/{customer_id}/accountLinks/{account_link_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + update: gagr_account_link.AccountLink = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_account_link.AccountLink, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateAccountLinkResponse(proto.Message): + r"""Response message for account link mutate. + + Attributes: + result (google.ads.googleads.v24.services.types.MutateAccountLinkResult): + Result for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + result: "MutateAccountLinkResult" = proto.Field( + proto.MESSAGE, + number=1, + message="MutateAccountLinkResult", + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateAccountLinkResult(proto.Message): + r"""The result for the account link mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/ad_group_ad_label_service.py b/google/ads/googleads/v24/services/types/ad_group_ad_label_service.py new file mode 100644 index 000000000..4c22addd4 --- /dev/null +++ b/google/ads/googleads/v24/services/types/ad_group_ad_label_service.py @@ -0,0 +1,161 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import ad_group_ad_label +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAdGroupAdLabelsRequest", + "AdGroupAdLabelOperation", + "MutateAdGroupAdLabelsResponse", + "MutateAdGroupAdLabelResult", + }, +) + + +class MutateAdGroupAdLabelsRequest(proto.Message): + r"""Request message for + [AdGroupAdLabelService.MutateAdGroupAdLabels][google.ads.googleads.v24.services.AdGroupAdLabelService.MutateAdGroupAdLabels]. + + Attributes: + customer_id (str): + Required. ID of the customer whose ad group + ad labels are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupAdLabelOperation]): + Required. The list of operations to perform + on ad group ad labels. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AdGroupAdLabelOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupAdLabelOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class AdGroupAdLabelOperation(proto.Message): + r"""A single operation (create, remove) on an ad group ad label. + + 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: + create (google.ads.googleads.v24.resources.types.AdGroupAdLabel): + Create operation: No resource name is + expected for the new ad group ad label. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the ad group ad label + being removed, in this format: + + ``customers/{customer_id}/adGroupAdLabels/{ad_group_id}~{ad_id}~{label_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: ad_group_ad_label.AdGroupAdLabel = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=ad_group_ad_label.AdGroupAdLabel, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateAdGroupAdLabelsResponse(proto.Message): + r"""Response message for an ad group ad labels mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAdGroupAdLabelResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateAdGroupAdLabelResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateAdGroupAdLabelResult", + ) + ) + + +class MutateAdGroupAdLabelResult(proto.Message): + r"""The result for an ad group ad label mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/ad_group_ad_service.py b/google/ads/googleads/v24/services/types/ad_group_ad_service.py new file mode 100644 index 000000000..503dfd7ff --- /dev/null +++ b/google/ads/googleads/v24/services/types/ad_group_ad_service.py @@ -0,0 +1,268 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import policy +from google.ads.googleads.v24.enums.types import ( + asset_field_type as gage_asset_field_type, +) +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_ad as gagr_ad_group_ad, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAdGroupAdsRequest", + "AdGroupAdOperation", + "MutateAdGroupAdsResponse", + "MutateAdGroupAdResult", + "RemoveAutomaticallyCreatedAssetsRequest", + "AssetsWithFieldType", + }, +) + + +class MutateAdGroupAdsRequest(proto.Message): + r"""Request message for + [AdGroupAdService.MutateAdGroupAds][google.ads.googleads.v24.services.AdGroupAdService.MutateAdGroupAds]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose ads + are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupAdOperation]): + Required. The list of operations to perform + on individual ads. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AdGroupAdOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupAdOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class AdGroupAdOperation(proto.Message): + r"""A single operation (create, update, remove) on an ad group + ad. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + policy_validation_parameter (google.ads.googleads.v24.common.types.PolicyValidationParameter): + Configuration for how policies are validated. + create (google.ads.googleads.v24.resources.types.AdGroupAd): + Create operation: No resource name is + expected for the new ad. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.AdGroupAd): + Update operation: The ad is expected to have + a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed ad is + expected, in this format: + + ``customers/{customer_id}/adGroupAds/{ad_group_id}~{ad_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + policy_validation_parameter: policy.PolicyValidationParameter = proto.Field( + proto.MESSAGE, + number=5, + message=policy.PolicyValidationParameter, + ) + create: gagr_ad_group_ad.AdGroupAd = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_ad_group_ad.AdGroupAd, + ) + update: gagr_ad_group_ad.AdGroupAd = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_ad_group_ad.AdGroupAd, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateAdGroupAdsResponse(proto.Message): + r"""Response message for an ad group ad mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAdGroupAdResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateAdGroupAdResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateAdGroupAdResult", + ) + + +class MutateAdGroupAdResult(proto.Message): + r"""The result for the ad mutate. + + Attributes: + resource_name (str): + The resource name returned for successful + operations. + ad_group_ad (google.ads.googleads.v24.resources.types.AdGroupAd): + The mutated ad group ad with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_ad: gagr_ad_group_ad.AdGroupAd = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad_group_ad.AdGroupAd, + ) + + +class RemoveAutomaticallyCreatedAssetsRequest(proto.Message): + r"""Request message for + [AdGroupAdService.RemoveAutomaticallyCreatedAssets][google.ads.googleads.v24.services.AdGroupAdService.RemoveAutomaticallyCreatedAssets]. + + Attributes: + ad_group_ad (str): + Required. The resource name of the AdGroupAd + from which to remove automatically created + assets. + assets_with_field_type (MutableSequence[google.ads.googleads.v24.services.types.AssetsWithFieldType]): + Required. List of assets with field type to + be removed from the AdGroupAd. + """ + + ad_group_ad: str = proto.Field( + proto.STRING, + number=1, + ) + assets_with_field_type: MutableSequence["AssetsWithFieldType"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AssetsWithFieldType", + ) + ) + + +class AssetsWithFieldType(proto.Message): + r"""The combination of system asset and field type to remove. + + Attributes: + asset (str): + Required. The resource name of the asset to + be removed. + asset_field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + Required. The asset field type. + """ + + asset: str = proto.Field( + proto.STRING, + number=1, + ) + asset_field_type: ( + gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/ad_group_asset_service.py b/google/ads/googleads/v24/services/types/ad_group_asset_service.py new file mode 100644 index 000000000..5d8f51a3b --- /dev/null +++ b/google/ads/googleads/v24/services/types/ad_group_asset_service.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_asset as gagr_ad_group_asset, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAdGroupAssetsRequest", + "AdGroupAssetOperation", + "MutateAdGroupAssetsResponse", + "MutateAdGroupAssetResult", + }, +) + + +class MutateAdGroupAssetsRequest(proto.Message): + r"""Request message for + [AdGroupAssetService.MutateAdGroupAssets][google.ads.googleads.v24.services.AdGroupAssetService.MutateAdGroupAssets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose ad + group assets are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupAssetOperation]): + Required. The list of operations to perform + on individual ad group assets. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AdGroupAssetOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupAssetOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class AdGroupAssetOperation(proto.Message): + r"""A single operation (create, update, remove) on an ad group + asset. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.AdGroupAsset): + Create operation: No resource name is + expected for the new ad group asset. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.AdGroupAsset): + Update operation: The ad group asset is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed ad group + asset is expected, in this format: + + ``customers/{customer_id}/adGroupAssets/{ad_group_id}~{asset_id}~{field_type}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_ad_group_asset.AdGroupAsset = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_ad_group_asset.AdGroupAsset, + ) + update: gagr_ad_group_asset.AdGroupAsset = proto.Field( + proto.MESSAGE, + number=3, + oneof="operation", + message=gagr_ad_group_asset.AdGroupAsset, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateAdGroupAssetsResponse(proto.Message): + r"""Response message for an ad group asset mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAdGroupAssetResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + results: MutableSequence["MutateAdGroupAssetResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateAdGroupAssetResult", + ) + + +class MutateAdGroupAssetResult(proto.Message): + r"""The result for the ad group asset mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + ad_group_asset (google.ads.googleads.v24.resources.types.AdGroupAsset): + The mutated ad group asset with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_asset: gagr_ad_group_asset.AdGroupAsset = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad_group_asset.AdGroupAsset, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/ad_group_asset_set_service.py b/google/ads/googleads/v24/services/types/ad_group_asset_set_service.py new file mode 100644 index 000000000..445578158 --- /dev/null +++ b/google/ads/googleads/v24/services/types/ad_group_asset_set_service.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_asset_set as gagr_ad_group_asset_set, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAdGroupAssetSetsRequest", + "AdGroupAssetSetOperation", + "MutateAdGroupAssetSetsResponse", + "MutateAdGroupAssetSetResult", + }, +) + + +class MutateAdGroupAssetSetsRequest(proto.Message): + r"""Request message for + [AdGroupAssetSetService.MutateAdGroupAssetSets][google.ads.googleads.v24.services.AdGroupAssetSetService.MutateAdGroupAssetSets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose ad + group asset sets are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupAssetSetOperation]): + Required. The list of operations to perform + on individual ad group asset sets. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AdGroupAssetSetOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupAssetSetOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class AdGroupAssetSetOperation(proto.Message): + r"""A single operation (create, remove) on an ad group asset set. + + 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: + create (google.ads.googleads.v24.resources.types.AdGroupAssetSet): + Create operation: No resource name is + expected for the new ad group asset set. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed ad group + asset set is expected, in this format: + ``customers/{customer_id}/adGroupAssetSets/{ad_group_id}~{asset_set_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: gagr_ad_group_asset_set.AdGroupAssetSet = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_ad_group_asset_set.AdGroupAssetSet, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateAdGroupAssetSetsResponse(proto.Message): + r"""Response message for an ad group asset set mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAdGroupAssetSetResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (e.g. auth errors), we return an RPC + level error. + """ + + results: MutableSequence["MutateAdGroupAssetSetResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateAdGroupAssetSetResult", + ) + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateAdGroupAssetSetResult(proto.Message): + r"""The result for the ad group asset set mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + ad_group_asset_set (google.ads.googleads.v24.resources.types.AdGroupAssetSet): + The mutated ad group asset set with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_asset_set: gagr_ad_group_asset_set.AdGroupAssetSet = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad_group_asset_set.AdGroupAssetSet, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/ad_group_bid_modifier_service.py b/google/ads/googleads/v24/services/types/ad_group_bid_modifier_service.py new file mode 100644 index 000000000..c58b25514 --- /dev/null +++ b/google/ads/googleads/v24/services/types/ad_group_bid_modifier_service.py @@ -0,0 +1,209 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_bid_modifier as gagr_ad_group_bid_modifier, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAdGroupBidModifiersRequest", + "AdGroupBidModifierOperation", + "MutateAdGroupBidModifiersResponse", + "MutateAdGroupBidModifierResult", + }, +) + + +class MutateAdGroupBidModifiersRequest(proto.Message): + r"""Request message for + [AdGroupBidModifierService.MutateAdGroupBidModifiers][google.ads.googleads.v24.services.AdGroupBidModifierService.MutateAdGroupBidModifiers]. + + Attributes: + customer_id (str): + Required. ID of the customer whose ad group + bid modifiers are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupBidModifierOperation]): + Required. The list of operations to perform + on individual ad group bid modifiers. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AdGroupBidModifierOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupBidModifierOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class AdGroupBidModifierOperation(proto.Message): + r"""A single operation (create, remove, update) on an ad group + bid modifier. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.AdGroupBidModifier): + Create operation: No resource name is + expected for the new ad group bid modifier. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.AdGroupBidModifier): + Update operation: The ad group bid modifier + is expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed ad group + bid modifier is expected, in this format: + + ``customers/{customer_id}/adGroupBidModifiers/{ad_group_id}~{criterion_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_ad_group_bid_modifier.AdGroupBidModifier = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_ad_group_bid_modifier.AdGroupBidModifier, + ) + update: gagr_ad_group_bid_modifier.AdGroupBidModifier = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_ad_group_bid_modifier.AdGroupBidModifier, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateAdGroupBidModifiersResponse(proto.Message): + r"""Response message for ad group bid modifiers mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAdGroupBidModifierResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateAdGroupBidModifierResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateAdGroupBidModifierResult", + ) + ) + + +class MutateAdGroupBidModifierResult(proto.Message): + r"""The result for the criterion mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + ad_group_bid_modifier (google.ads.googleads.v24.resources.types.AdGroupBidModifier): + The mutated ad group bid modifier with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_bid_modifier: gagr_ad_group_bid_modifier.AdGroupBidModifier = ( + proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad_group_bid_modifier.AdGroupBidModifier, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/ad_group_criterion_customizer_service.py b/google/ads/googleads/v24/services/types/ad_group_criterion_customizer_service.py new file mode 100644 index 000000000..78e50d7c9 --- /dev/null +++ b/google/ads/googleads/v24/services/types/ad_group_criterion_customizer_service.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_criterion_customizer as gagr_ad_group_criterion_customizer, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAdGroupCriterionCustomizersRequest", + "AdGroupCriterionCustomizerOperation", + "MutateAdGroupCriterionCustomizersResponse", + "MutateAdGroupCriterionCustomizerResult", + }, +) + + +class MutateAdGroupCriterionCustomizersRequest(proto.Message): + r"""Request message for + [AdGroupCriterionCustomizerService.MutateAdGroupCriterionCustomizers][google.ads.googleads.v24.services.AdGroupCriterionCustomizerService.MutateAdGroupCriterionCustomizers]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose ad + group criterion customizers are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupCriterionCustomizerOperation]): + Required. The list of operations to perform + on individual ad group criterion customizers. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AdGroupCriterionCustomizerOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupCriterionCustomizerOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class AdGroupCriterionCustomizerOperation(proto.Message): + r"""A single operation (create, remove) on a customizer + attribute. + + 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: + create (google.ads.googleads.v24.resources.types.AdGroupCriterionCustomizer): + Create operation: No resource name is + expected for the new ad group criterion + customizer. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed ad group + criterion customizer is expected, in this format: + + ``customers/{customer_id}/adGroupCriterionCustomizers/{ad_group_id}~{criterion_id}~{customizer_attribute_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: gagr_ad_group_criterion_customizer.AdGroupCriterionCustomizer = ( + proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_ad_group_criterion_customizer.AdGroupCriterionCustomizer, + ) + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateAdGroupCriterionCustomizersResponse(proto.Message): + r"""Response message for an ad group criterion customizer mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAdGroupCriterionCustomizerResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateAdGroupCriterionCustomizerResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateAdGroupCriterionCustomizerResult", + ) + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateAdGroupCriterionCustomizerResult(proto.Message): + r"""The result for the ad group criterion customizer mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + ad_group_criterion_customizer (google.ads.googleads.v24.resources.types.AdGroupCriterionCustomizer): + The mutated AdGroupCriterionCustomizer with only mutable + fields after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_criterion_customizer: ( + gagr_ad_group_criterion_customizer.AdGroupCriterionCustomizer + ) = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad_group_criterion_customizer.AdGroupCriterionCustomizer, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/ad_group_criterion_label_service.py b/google/ads/googleads/v24/services/types/ad_group_criterion_label_service.py new file mode 100644 index 000000000..5503910d2 --- /dev/null +++ b/google/ads/googleads/v24/services/types/ad_group_criterion_label_service.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import ad_group_criterion_label +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAdGroupCriterionLabelsRequest", + "AdGroupCriterionLabelOperation", + "MutateAdGroupCriterionLabelsResponse", + "MutateAdGroupCriterionLabelResult", + }, +) + + +class MutateAdGroupCriterionLabelsRequest(proto.Message): + r"""Request message for + [AdGroupCriterionLabelService.MutateAdGroupCriterionLabels][google.ads.googleads.v24.services.AdGroupCriterionLabelService.MutateAdGroupCriterionLabels]. + + Attributes: + customer_id (str): + Required. ID of the customer whose ad group + criterion labels are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupCriterionLabelOperation]): + Required. The list of operations to perform + on ad group criterion labels. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AdGroupCriterionLabelOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupCriterionLabelOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class AdGroupCriterionLabelOperation(proto.Message): + r"""A single operation (create, remove) on an ad group criterion + label. + + 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: + create (google.ads.googleads.v24.resources.types.AdGroupCriterionLabel): + Create operation: No resource name is + expected for the new ad group label. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the ad group criterion + label being removed, in this format: + + ``customers/{customer_id}/adGroupCriterionLabels/{ad_group_id}~{criterion_id}~{label_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: ad_group_criterion_label.AdGroupCriterionLabel = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=ad_group_criterion_label.AdGroupCriterionLabel, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateAdGroupCriterionLabelsResponse(proto.Message): + r"""Response message for an ad group criterion labels mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAdGroupCriterionLabelResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateAdGroupCriterionLabelResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateAdGroupCriterionLabelResult", + ) + ) + + +class MutateAdGroupCriterionLabelResult(proto.Message): + r"""The result for an ad group criterion label mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/ad_group_criterion_service.py b/google/ads/googleads/v24/services/types/ad_group_criterion_service.py new file mode 100644 index 000000000..170985517 --- /dev/null +++ b/google/ads/googleads/v24/services/types/ad_group_criterion_service.py @@ -0,0 +1,225 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import policy +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_criterion as gagr_ad_group_criterion, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAdGroupCriteriaRequest", + "AdGroupCriterionOperation", + "MutateAdGroupCriteriaResponse", + "MutateAdGroupCriterionResult", + }, +) + + +class MutateAdGroupCriteriaRequest(proto.Message): + r"""Request message for + [AdGroupCriterionService.MutateAdGroupCriteria][google.ads.googleads.v24.services.AdGroupCriterionService.MutateAdGroupCriteria]. + + Attributes: + customer_id (str): + Required. ID of the customer whose criteria + are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupCriterionOperation]): + Required. The list of operations to perform + on individual criteria. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AdGroupCriterionOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupCriterionOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class AdGroupCriterionOperation(proto.Message): + r"""A single operation (create, remove, update) on an ad group + criterion. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + exempt_policy_violation_keys (MutableSequence[google.ads.googleads.v24.common.types.PolicyViolationKey]): + The list of policy violation keys that should not cause a + PolicyViolationError to be reported. Not all policy + violations are exemptable, refer to the is_exemptible field + in the returned PolicyViolationError. + + Resources violating these polices will be saved, but will + not be eligible to serve. They may begin serving at a later + time due to a change in policies, re-review of the resource, + or a change in advertiser certificates. + create (google.ads.googleads.v24.resources.types.AdGroupCriterion): + Create operation: No resource name is + expected for the new criterion. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.AdGroupCriterion): + Update operation: The criterion is expected + to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed criterion + is expected, in this format: + + ``customers/{customer_id}/adGroupCriteria/{ad_group_id}~{criterion_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + exempt_policy_violation_keys: MutableSequence[policy.PolicyViolationKey] = ( + proto.RepeatedField( + proto.MESSAGE, + number=5, + message=policy.PolicyViolationKey, + ) + ) + create: gagr_ad_group_criterion.AdGroupCriterion = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_ad_group_criterion.AdGroupCriterion, + ) + update: gagr_ad_group_criterion.AdGroupCriterion = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_ad_group_criterion.AdGroupCriterion, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateAdGroupCriteriaResponse(proto.Message): + r"""Response message for an ad group criterion mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAdGroupCriterionResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateAdGroupCriterionResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateAdGroupCriterionResult", + ) + ) + + +class MutateAdGroupCriterionResult(proto.Message): + r"""The result for the criterion mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + ad_group_criterion (google.ads.googleads.v24.resources.types.AdGroupCriterion): + The mutated ad group criterion with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_criterion: gagr_ad_group_criterion.AdGroupCriterion = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad_group_criterion.AdGroupCriterion, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/ad_group_customizer_service.py b/google/ads/googleads/v24/services/types/ad_group_customizer_service.py new file mode 100644 index 000000000..735ab1ae1 --- /dev/null +++ b/google/ads/googleads/v24/services/types/ad_group_customizer_service.py @@ -0,0 +1,188 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_customizer as gagr_ad_group_customizer, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAdGroupCustomizersRequest", + "AdGroupCustomizerOperation", + "MutateAdGroupCustomizersResponse", + "MutateAdGroupCustomizerResult", + }, +) + + +class MutateAdGroupCustomizersRequest(proto.Message): + r"""Request message for + [AdGroupCustomizerService.MutateAdGroupCustomizers][google.ads.googleads.v24.services.AdGroupCustomizerService.MutateAdGroupCustomizers]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose ad + group customizers are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupCustomizerOperation]): + Required. The list of operations to perform + on individual ad group customizers. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AdGroupCustomizerOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupCustomizerOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class AdGroupCustomizerOperation(proto.Message): + r"""A single operation (create, remove) on a customizer + attribute. + + 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: + create (google.ads.googleads.v24.resources.types.AdGroupCustomizer): + Create operation: No resource name is + expected for the new ad group customizer + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed ad group + customizer is expected, in this format: + ``customers/{customer_id}/adGroupCustomizers/{ad_group_id}~{customizer_attribute_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: gagr_ad_group_customizer.AdGroupCustomizer = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_ad_group_customizer.AdGroupCustomizer, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateAdGroupCustomizersResponse(proto.Message): + r"""Response message for an ad group customizer mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAdGroupCustomizerResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateAdGroupCustomizerResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateAdGroupCustomizerResult", + ) + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateAdGroupCustomizerResult(proto.Message): + r"""The result for the ad group customizer mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + ad_group_customizer (google.ads.googleads.v24.resources.types.AdGroupCustomizer): + The mutated AdGroupCustomizer with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_customizer: gagr_ad_group_customizer.AdGroupCustomizer = ( + proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad_group_customizer.AdGroupCustomizer, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/ad_group_label_service.py b/google/ads/googleads/v24/services/types/ad_group_label_service.py new file mode 100644 index 000000000..d6d5a155a --- /dev/null +++ b/google/ads/googleads/v24/services/types/ad_group_label_service.py @@ -0,0 +1,157 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import ad_group_label +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAdGroupLabelsRequest", + "AdGroupLabelOperation", + "MutateAdGroupLabelsResponse", + "MutateAdGroupLabelResult", + }, +) + + +class MutateAdGroupLabelsRequest(proto.Message): + r"""Request message for + [AdGroupLabelService.MutateAdGroupLabels][google.ads.googleads.v24.services.AdGroupLabelService.MutateAdGroupLabels]. + + Attributes: + customer_id (str): + Required. ID of the customer whose ad group + labels are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupLabelOperation]): + Required. The list of operations to perform + on ad group labels. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AdGroupLabelOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupLabelOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class AdGroupLabelOperation(proto.Message): + r"""A single operation (create, remove) on an ad group label. + + 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: + create (google.ads.googleads.v24.resources.types.AdGroupLabel): + Create operation: No resource name is + expected for the new ad group label. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the ad group label + being removed, in this format: + + ``customers/{customer_id}/adGroupLabels/{ad_group_id}~{label_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: ad_group_label.AdGroupLabel = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=ad_group_label.AdGroupLabel, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateAdGroupLabelsResponse(proto.Message): + r"""Response message for an ad group labels mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAdGroupLabelResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateAdGroupLabelResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateAdGroupLabelResult", + ) + + +class MutateAdGroupLabelResult(proto.Message): + r"""The result for an ad group label mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/ad_group_service.py b/google/ads/googleads/v24/services/types/ad_group_service.py new file mode 100644 index 000000000..e6bb7ac79 --- /dev/null +++ b/google/ads/googleads/v24/services/types/ad_group_service.py @@ -0,0 +1,200 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ad_group as gagr_ad_group +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAdGroupsRequest", + "AdGroupOperation", + "MutateAdGroupsResponse", + "MutateAdGroupResult", + }, +) + + +class MutateAdGroupsRequest(proto.Message): + r"""Request message for + [AdGroupService.MutateAdGroups][google.ads.googleads.v24.services.AdGroupService.MutateAdGroups]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose ad + groups are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdGroupOperation]): + Required. The list of operations to perform + on individual ad groups. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AdGroupOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class AdGroupOperation(proto.Message): + r"""A single operation (create, update, remove) on an ad group. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.AdGroup): + Create operation: No resource name is + expected for the new ad group. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.AdGroup): + Update operation: The ad group is expected to + have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed ad group + is expected, in this format: + + ``customers/{customer_id}/adGroups/{ad_group_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_ad_group.AdGroup = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_ad_group.AdGroup, + ) + update: gagr_ad_group.AdGroup = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_ad_group.AdGroup, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateAdGroupsResponse(proto.Message): + r"""Response message for an ad group mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAdGroupResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateAdGroupResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateAdGroupResult", + ) + + +class MutateAdGroupResult(proto.Message): + r"""The result for the ad group mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + ad_group (google.ads.googleads.v24.resources.types.AdGroup): + The mutated ad group with only mutable fields after mutate. + The field will only be returned when response_content_type + is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group: gagr_ad_group.AdGroup = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad_group.AdGroup, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/ad_parameter_service.py b/google/ads/googleads/v24/services/types/ad_parameter_service.py new file mode 100644 index 000000000..2893e560e --- /dev/null +++ b/google/ads/googleads/v24/services/types/ad_parameter_service.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + ad_parameter as gagr_ad_parameter, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAdParametersRequest", + "AdParameterOperation", + "MutateAdParametersResponse", + "MutateAdParameterResult", + }, +) + + +class MutateAdParametersRequest(proto.Message): + r"""Request message for + [AdParameterService.MutateAdParameters][google.ads.googleads.v24.services.AdParameterService.MutateAdParameters] + + Attributes: + customer_id (str): + Required. The ID of the customer whose ad + parameters are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdParameterOperation]): + Required. The list of operations to perform + on individual ad parameters. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AdParameterOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdParameterOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class AdParameterOperation(proto.Message): + r"""A single operation (create, update, remove) on ad parameter. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.AdParameter): + Create operation: No resource name is + expected for the new ad parameter. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.AdParameter): + Update operation: The ad parameter is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the ad parameter to + remove is expected in this format: + + ``customers/{customer_id}/adParameters/{ad_group_id}~{criterion_id}~{parameter_index}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_ad_parameter.AdParameter = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_ad_parameter.AdParameter, + ) + update: gagr_ad_parameter.AdParameter = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_ad_parameter.AdParameter, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateAdParametersResponse(proto.Message): + r"""Response message for an ad parameter mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAdParameterResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateAdParameterResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateAdParameterResult", + ) + + +class MutateAdParameterResult(proto.Message): + r"""The result for the ad parameter mutate. + + Attributes: + resource_name (str): + The resource name returned for successful + operations. + ad_parameter (google.ads.googleads.v24.resources.types.AdParameter): + The mutated AdParameter with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_parameter: gagr_ad_parameter.AdParameter = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad_parameter.AdParameter, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/ad_service.py b/google/ads/googleads/v24/services/types/ad_service.py new file mode 100644 index 000000000..ef5239b43 --- /dev/null +++ b/google/ads/googleads/v24/services/types/ad_service.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import policy +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ad as gagr_ad +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAdsRequest", + "AdOperation", + "MutateAdsResponse", + "MutateAdResult", + }, +) + + +class MutateAdsRequest(proto.Message): + r"""Request message for + [AdService.MutateAds][google.ads.googleads.v24.services.AdService.MutateAds]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose ads + are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AdOperation]): + Required. The list of operations to perform + on individual ads. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AdOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class AdOperation(proto.Message): + r"""A single update operation on an ad. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + policy_validation_parameter (google.ads.googleads.v24.common.types.PolicyValidationParameter): + Configuration for how policies are validated. + update (google.ads.googleads.v24.resources.types.Ad): + Update operation: The ad is expected to have a valid + resource name in this format: + + ``customers/{customer_id}/ads/{ad_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=2, + message=field_mask_pb2.FieldMask, + ) + policy_validation_parameter: policy.PolicyValidationParameter = proto.Field( + proto.MESSAGE, + number=3, + message=policy.PolicyValidationParameter, + ) + update: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_ad.Ad, + ) + + +class MutateAdsResponse(proto.Message): + r"""Response message for an ad mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAdResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateAdResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateAdResult", + ) + + +class MutateAdResult(proto.Message): + r"""The result for the ad mutate. + + Attributes: + resource_name (str): + The resource name returned for successful + operations. + ad (google.ads.googleads.v24.resources.types.Ad): + The mutated ad with only mutable fields after mutate. The + field will only be returned when response_content_type is + set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad.Ad, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/asset_generation_service.py b/google/ads/googleads/v24/services/types/asset_generation_service.py new file mode 100644 index 000000000..4a2c0a9e8 --- /dev/null +++ b/google/ads/googleads/v24/services/types/asset_generation_service.py @@ -0,0 +1,417 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + advertising_channel_type as gage_advertising_channel_type, +) +from google.ads.googleads.v24.enums.types import ( + asset_field_type as gage_asset_field_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "GenerateTextRequest", + "GenerateTextResponse", + "GeneratedText", + "GenerateImagesRequest", + "FinalUrlImageGenerationInput", + "FreeformImageGenerationInput", + "ProductRecontextGenerationImageInput", + "GenerateImagesResponse", + "SourceImage", + "GeneratedImage", + "AssetGenerationExistingContext", + }, +) + + +class GenerateTextRequest(proto.Message): + r"""Request message for + [AssetGenerationService.GenerateText][google.ads.googleads.v24.services.AssetGenerationService.GenerateText] + + 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: + customer_id (str): + Required. The ID of the customer to generate + assets for. Required. + asset_field_types (MutableSequence[google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType]): + Required. Which field types text is being generated for. + Supported values are: HEADLINE, LONG_HEADLINE, DESCRIPTION. + Required. + final_url (str): + Optional. Final url to use as a source for generating + assets. Required if existing_generation_context is not + provided or does not have a final url associated with it. + freeform_prompt (str): + Optional. A freeform description of what + assets should be generated. The string length + must be between 1 and 1500, inclusive. + keywords (MutableSequence[str]): + Optional. A freeform list of keywords that + are relevant, used to inform asset generation. + existing_generation_context (google.ads.googleads.v24.services.types.AssetGenerationExistingContext): + Optional. The setting for which assets are + being generated, such as an existing AssetGroup + or AdGroupAd. + + This field is a member of `oneof`_ ``context``. + advertising_channel_type (google.ads.googleads.v24.enums.types.AdvertisingChannelTypeEnum.AdvertisingChannelType): + Optional. The advertising channel for which to generate + assets. Required if existing_context is not provided. + + Supported channel types: SEARCH, PERFORMANCE_MAX, DISPLAY, + and DEMAND_GEN + + This field is a member of `oneof`_ ``context``. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + asset_field_types: MutableSequence[ + gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType + ] = proto.RepeatedField( + proto.ENUM, + number=2, + enum=gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + final_url: str = proto.Field( + proto.STRING, + number=5, + ) + freeform_prompt: str = proto.Field( + proto.STRING, + number=6, + ) + keywords: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=7, + ) + existing_generation_context: "AssetGenerationExistingContext" = proto.Field( + proto.MESSAGE, + number=3, + oneof="context", + message="AssetGenerationExistingContext", + ) + advertising_channel_type: ( + gage_advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType + ) = proto.Field( + proto.ENUM, + number=4, + oneof="context", + enum=gage_advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType, + ) + + +class GenerateTextResponse(proto.Message): + r"""Response message for + [AssetGenerationService.GenerateText][google.ads.googleads.v24.services.AssetGenerationService.GenerateText] + + Attributes: + generated_text (MutableSequence[google.ads.googleads.v24.services.types.GeneratedText]): + List of text that was generated and the field + type to use it as. + """ + + generated_text: MutableSequence["GeneratedText"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="GeneratedText", + ) + + +class GeneratedText(proto.Message): + r"""Data and metadata about a piece of generated text. + + Attributes: + text (str): + A string of text that was generated. + asset_field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + The type of asset this text is intended to be + used as. + """ + + text: str = proto.Field( + proto.STRING, + number=1, + ) + asset_field_type: ( + gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + + +class GenerateImagesRequest(proto.Message): + r"""Request message for + [AssetGenerationService.GenerateImages][google.ads.googleads.v24.services.AssetGenerationService.GenerateImages] + + 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: + customer_id (str): + Required. The ID of the customer for whom the + images are being generated. Required. + asset_field_types (MutableSequence[google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType]): + Optional. Output field types for generated images. Supported + values are MARKETING_IMAGE, SQUARE_MARKETING_IMAGE, + PORTRAIT_MARKETING_IMAGE, and TALL_PORTRAIT_MARKETING_IMAGE. + All specified field types must be compatible with the + ``advertising_channel_type`` or + ``existing_generation_context`` (whichever is set). If no + field types are provided, images will be generated for all + compatible field types. + advertising_channel_type (google.ads.googleads.v24.enums.types.AdvertisingChannelTypeEnum.AdvertisingChannelType): + Optional. The advertising channel type for which the images + are being generated. This field is required if + ``existing_generation_context`` is not provided. Supported + channel types include SEARCH, PERFORMANCE_MAX, DISPLAY, and + DEMAND_GEN. + + This field is a member of `oneof`_ ``context``. + final_url_generation (google.ads.googleads.v24.services.types.FinalUrlImageGenerationInput): + Optional. Generate images from a final url. + + This field is a member of `oneof`_ ``generation_type``. + freeform_generation (google.ads.googleads.v24.services.types.FreeformImageGenerationInput): + Optional. Generate images from a freeform + prompt. + + This field is a member of `oneof`_ ``generation_type``. + product_recontext_generation (google.ads.googleads.v24.services.types.ProductRecontextGenerationImageInput): + Optional. Generate new images by + recontextualizing existing product images. + + This field is a member of `oneof`_ ``generation_type``. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + asset_field_types: MutableSequence[ + gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType + ] = proto.RepeatedField( + proto.ENUM, + number=4, + enum=gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + advertising_channel_type: ( + gage_advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType + ) = proto.Field( + proto.ENUM, + number=2, + oneof="context", + enum=gage_advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType, + ) + final_url_generation: "FinalUrlImageGenerationInput" = proto.Field( + proto.MESSAGE, + number=5, + oneof="generation_type", + message="FinalUrlImageGenerationInput", + ) + freeform_generation: "FreeformImageGenerationInput" = proto.Field( + proto.MESSAGE, + number=6, + oneof="generation_type", + message="FreeformImageGenerationInput", + ) + product_recontext_generation: "ProductRecontextGenerationImageInput" = ( + proto.Field( + proto.MESSAGE, + number=7, + oneof="generation_type", + message="ProductRecontextGenerationImageInput", + ) + ) + + +class FinalUrlImageGenerationInput(proto.Message): + r"""Input for guiding image asset generation with a final url. + + Attributes: + final_url (str): + Required. A final url to guide the image + generation process. Required. + """ + + final_url: str = proto.Field( + proto.STRING, + number=1, + ) + + +class FreeformImageGenerationInput(proto.Message): + r"""Input for guiding image asset generation with a freeform + prompt. + + Attributes: + freeform_prompt (str): + Required. A freeform text description to + guide the image generation process. The maximum + length is 1500 characters. Required. + """ + + freeform_prompt: str = proto.Field( + proto.STRING, + number=1, + ) + + +class ProductRecontextGenerationImageInput(proto.Message): + r"""Input for generating new images by recontextualizing existing + product images. + + Attributes: + prompt (str): + Optional. A freeform description of the + assets to be generated. Maximum character limit + is 1500. + source_images (MutableSequence[google.ads.googleads.v24.services.types.SourceImage]): + Required. Product images to use for + generating new images. 1-3 images must be + provided. + """ + + prompt: str = proto.Field( + proto.STRING, + number=1, + ) + source_images: MutableSequence["SourceImage"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="SourceImage", + ) + + +class GenerateImagesResponse(proto.Message): + r"""Response message for + [AssetGenerationService.GenerateImages][google.ads.googleads.v24.services.AssetGenerationService.GenerateImages] + + Attributes: + generated_images (MutableSequence[google.ads.googleads.v24.services.types.GeneratedImage]): + Successfully generated images. + """ + + generated_images: MutableSequence["GeneratedImage"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="GeneratedImage", + ) + + +class SourceImage(proto.Message): + r"""A source image to be used in the generation process. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + image_data (bytes): + Optional. Raw bytes of the image to use. + + This field is a member of `oneof`_ ``image``. + """ + + image_data: bytes = proto.Field( + proto.BYTES, + number=1, + oneof="image", + ) + + +class GeneratedImage(proto.Message): + r"""Generated image data and metadata. + + Attributes: + image_temporary_url (str): + A temporary URL for the generated image. + asset_field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + The intended field type for this generated + image. + """ + + image_temporary_url: str = proto.Field( + proto.STRING, + number=1, + ) + asset_field_type: ( + gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + + +class AssetGenerationExistingContext(proto.Message): + r"""The context for which assets are being generated, such as an + existing AssetGroup or AdGroupAd. + + 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: + existing_asset_group (str): + Resource name of an existing AssetGroup for + which these assets are being generated. + + This field is a member of `oneof`_ ``existing_context``. + existing_ad_group_ad (str): + Resource name of an existing AdGroupAd for + which these assets are being generated. + + This field is a member of `oneof`_ ``existing_context``. + """ + + existing_asset_group: str = proto.Field( + proto.STRING, + number=1, + oneof="existing_context", + ) + existing_ad_group_ad: str = proto.Field( + proto.STRING, + number=2, + oneof="existing_context", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/asset_group_asset_service.py b/google/ads/googleads/v24/services/types/asset_group_asset_service.py new file mode 100644 index 000000000..0560c8c18 --- /dev/null +++ b/google/ads/googleads/v24/services/types/asset_group_asset_service.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import asset_group_asset +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAssetGroupAssetsRequest", + "AssetGroupAssetOperation", + "MutateAssetGroupAssetsResponse", + "MutateAssetGroupAssetResult", + }, +) + + +class MutateAssetGroupAssetsRequest(proto.Message): + r"""Request message for + [AssetGroupAssetService.MutateAssetGroupAssets][google.ads.googleads.v24.services.AssetGroupAssetService.MutateAssetGroupAssets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose asset + group assets are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AssetGroupAssetOperation]): + Required. The list of operations to perform + on individual asset group assets. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AssetGroupAssetOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AssetGroupAssetOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class AssetGroupAssetOperation(proto.Message): + r"""A single operation (create, remove) on an asset group asset. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.AssetGroupAsset): + Create operation: No resource name is + expected for the new asset group asset. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.AssetGroupAsset): + Update operation: The asset group asset is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed asset + group asset is expected, in this format: + ``customers/{customer_id}/assetGroupAssets/{asset_group_id}~{asset_id}~{field_type}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: asset_group_asset.AssetGroupAsset = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=asset_group_asset.AssetGroupAsset, + ) + update: asset_group_asset.AssetGroupAsset = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=asset_group_asset.AssetGroupAsset, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateAssetGroupAssetsResponse(proto.Message): + r"""Response message for an asset group asset mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAssetGroupAssetResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateAssetGroupAssetResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateAssetGroupAssetResult", + ) + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateAssetGroupAssetResult(proto.Message): + r"""The result for the asset group asset mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/asset_group_listing_group_filter_service.py b/google/ads/googleads/v24/services/types/asset_group_listing_group_filter_service.py new file mode 100644 index 000000000..b7bd01a1b --- /dev/null +++ b/google/ads/googleads/v24/services/types/asset_group_listing_group_filter_service.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + asset_group_listing_group_filter as gagr_asset_group_listing_group_filter, +) +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAssetGroupListingGroupFiltersRequest", + "AssetGroupListingGroupFilterOperation", + "MutateAssetGroupListingGroupFiltersResponse", + "MutateAssetGroupListingGroupFilterResult", + }, +) + + +class MutateAssetGroupListingGroupFiltersRequest(proto.Message): + r"""Request message for + [AssetGroupListingGroupFilterService.MutateAssetGroupListingGroupFilters][google.ads.googleads.v24.services.AssetGroupListingGroupFilterService.MutateAssetGroupListingGroupFilters]. + partial_failure is not supported because the tree needs to be + validated together. + + Attributes: + customer_id (str): + Required. The ID of the customer whose asset + group listing group filters are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AssetGroupListingGroupFilterOperation]): + Required. The list of operations to perform + on individual asset group listing group filters. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AssetGroupListingGroupFilterOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AssetGroupListingGroupFilterOperation", + ) + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=4, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class AssetGroupListingGroupFilterOperation(proto.Message): + r"""A single operation (create, remove) on an asset group listing + group filter. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.AssetGroupListingGroupFilter): + Create operation: No resource name is + expected for the new asset group listing group + filter. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.AssetGroupListingGroupFilter): + Update operation: The asset group listing + group filter is expected to have a valid + resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed asset + group listing group filter is expected, in this format: + ``customers/{customer_id}/assetGroupListingGroupFilters/{asset_group_id}~{listing_group_filter_id}`` + An entity can be removed only if it's not referenced by + other parent_listing_group_id. If multiple entities are + being deleted, the mutates must be in the correct order. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: ( + gagr_asset_group_listing_group_filter.AssetGroupListingGroupFilter + ) = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_asset_group_listing_group_filter.AssetGroupListingGroupFilter, + ) + update: ( + gagr_asset_group_listing_group_filter.AssetGroupListingGroupFilter + ) = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_asset_group_listing_group_filter.AssetGroupListingGroupFilter, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateAssetGroupListingGroupFiltersResponse(proto.Message): + r"""Response message for an asset group listing group filter + mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAssetGroupListingGroupFilterResult]): + All results for the mutate. + """ + + results: MutableSequence["MutateAssetGroupListingGroupFilterResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateAssetGroupListingGroupFilterResult", + ) + ) + + +class MutateAssetGroupListingGroupFilterResult(proto.Message): + r"""The result for the asset group listing group filter mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + asset_group_listing_group_filter (google.ads.googleads.v24.resources.types.AssetGroupListingGroupFilter): + The mutated AssetGroupListingGroupFilter with only mutable + fields after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + asset_group_listing_group_filter: ( + gagr_asset_group_listing_group_filter.AssetGroupListingGroupFilter + ) = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_asset_group_listing_group_filter.AssetGroupListingGroupFilter, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/asset_group_service.py b/google/ads/googleads/v24/services/types/asset_group_service.py new file mode 100644 index 000000000..fb9be6e06 --- /dev/null +++ b/google/ads/googleads/v24/services/types/asset_group_service.py @@ -0,0 +1,166 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import asset_group +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAssetGroupsRequest", + "AssetGroupOperation", + "MutateAssetGroupsResponse", + "MutateAssetGroupResult", + }, +) + + +class MutateAssetGroupsRequest(proto.Message): + r"""Request message for + [AssetGroupService.MutateAssetGroups][google.ads.googleads.v24.services.AssetGroupService.MutateAssetGroups]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose asset + groups are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AssetGroupOperation]): + Required. The list of operations to perform + on individual asset groups. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AssetGroupOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AssetGroupOperation", + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class AssetGroupOperation(proto.Message): + r"""A single operation (create, remove) on an asset group. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.AssetGroup): + Create operation: No resource name is + expected for the new asset group + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.AssetGroup): + Update operation: The asset group is expected + to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed asset + group is expected, in this format: + ``customers/{customer_id}/assetGroups/{asset_group_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: asset_group.AssetGroup = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=asset_group.AssetGroup, + ) + update: asset_group.AssetGroup = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=asset_group.AssetGroup, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateAssetGroupsResponse(proto.Message): + r"""Response message for an asset group mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAssetGroupResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateAssetGroupResult"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateAssetGroupResult", + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateAssetGroupResult(proto.Message): + r"""The result for the asset group mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/asset_group_signal_service.py b/google/ads/googleads/v24/services/types/asset_group_signal_service.py new file mode 100644 index 000000000..ef9a11f1d --- /dev/null +++ b/google/ads/googleads/v24/services/types/asset_group_signal_service.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import policy +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + asset_group_signal as gagr_asset_group_signal, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAssetGroupSignalsRequest", + "AssetGroupSignalOperation", + "MutateAssetGroupSignalsResponse", + "MutateAssetGroupSignalResult", + }, +) + + +class MutateAssetGroupSignalsRequest(proto.Message): + r"""Request message for + [AssetGroupSignalService.MutateAssetGroupSignals][google.ads.googleads.v24.services.AssetGroupSignalService.MutateAssetGroupSignals]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose asset + group signals are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AssetGroupSignalOperation]): + Required. The list of operations to perform + on individual asset group signals. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AssetGroupSignalOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AssetGroupSignalOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class AssetGroupSignalOperation(proto.Message): + r"""A single operation (create, remove) on an asset group signal. + + 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: + exempt_policy_violation_keys (MutableSequence[google.ads.googleads.v24.common.types.PolicyViolationKey]): + Optional. The list of policy violation keys that should not + cause a PolicyViolationError to be reported. Not all policy + violations are exemptable, refer to the is_exemptible field + in the returned PolicyViolationError. + + Resources violating these polices will be saved, but will + not be eligible to serve. They may begin serving at a later + time due to a change in policies, re-review of the resource, + or a change in advertiser certificates. + create (google.ads.googleads.v24.resources.types.AssetGroupSignal): + Create operation: No resource name is + expected for the new asset group signal. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed asset + group signal is expected, in this format: + ``customers/{customer_id}/assetGroupSignals/{asset_group_id}~{criterion_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + exempt_policy_violation_keys: MutableSequence[policy.PolicyViolationKey] = ( + proto.RepeatedField( + proto.MESSAGE, + number=3, + message=policy.PolicyViolationKey, + ) + ) + create: gagr_asset_group_signal.AssetGroupSignal = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_asset_group_signal.AssetGroupSignal, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateAssetGroupSignalsResponse(proto.Message): + r"""Response message for an asset group signal mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAssetGroupSignalResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateAssetGroupSignalResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateAssetGroupSignalResult", + ) + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateAssetGroupSignalResult(proto.Message): + r"""The result for the asset group signal mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + asset_group_signal (google.ads.googleads.v24.resources.types.AssetGroupSignal): + The mutated AssetGroupSignal with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + asset_group_signal: gagr_asset_group_signal.AssetGroupSignal = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_asset_group_signal.AssetGroupSignal, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/asset_service.py b/google/ads/googleads/v24/services/types/asset_service.py new file mode 100644 index 000000000..cb622c682 --- /dev/null +++ b/google/ads/googleads/v24/services/types/asset_service.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import asset as gagr_asset +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAssetsRequest", + "AssetOperation", + "MutateAssetsResponse", + "MutateAssetResult", + }, +) + + +class MutateAssetsRequest(proto.Message): + r"""Request message for + [AssetService.MutateAssets][google.ads.googleads.v24.services.AssetService.MutateAssets] + + Attributes: + customer_id (str): + Required. The ID of the customer whose assets + are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AssetOperation]): + Required. The list of operations to perform + on individual assets. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AssetOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AssetOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=5, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=3, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class AssetOperation(proto.Message): + r"""A single operation to create an asset. Supported asset types + are YoutubeVideoAsset, MediaBundleAsset, ImageAsset, + LeadFormAsset, LocationAsset, and ImageAsset. TextAsset can be + created with an Ad inline, but it can also be created apart from + an Ad like other assets. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.Asset): + Create operation: No resource name is + expected for the new asset. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.Asset): + Update operation: The asset is expected to have a valid + resource name in this format: + + ``customers/{customer_id}/assets/{asset_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=3, + message=field_mask_pb2.FieldMask, + ) + create: gagr_asset.Asset = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_asset.Asset, + ) + update: gagr_asset.Asset = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_asset.Asset, + ) + + +class MutateAssetsResponse(proto.Message): + r"""Response message for an asset mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAssetResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateAssetResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateAssetResult", + ) + + +class MutateAssetResult(proto.Message): + r"""The result for the asset mutate. + + Attributes: + resource_name (str): + The resource name returned for successful + operations. + asset (google.ads.googleads.v24.resources.types.Asset): + The mutated asset with only mutable fields after mutate. The + field will only be returned when response_content_type is + set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + asset: gagr_asset.Asset = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_asset.Asset, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/asset_set_asset_service.py b/google/ads/googleads/v24/services/types/asset_set_asset_service.py new file mode 100644 index 000000000..0a44a5d84 --- /dev/null +++ b/google/ads/googleads/v24/services/types/asset_set_asset_service.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + asset_set_asset as gagr_asset_set_asset, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAssetSetAssetsRequest", + "AssetSetAssetOperation", + "MutateAssetSetAssetsResponse", + "MutateAssetSetAssetResult", + }, +) + + +class MutateAssetSetAssetsRequest(proto.Message): + r"""Request message for + [AssetSetAssetService.MutateAssetSetAssets][google.ads.googleads.v24.services.AssetSetAssetService.MutateAssetSetAssets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose asset + set assets are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AssetSetAssetOperation]): + Required. The list of operations to perform + on individual asset set assets. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AssetSetAssetOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AssetSetAssetOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class AssetSetAssetOperation(proto.Message): + r"""A single operation (create, remove) on an asset set asset. + + 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: + create (google.ads.googleads.v24.resources.types.AssetSetAsset): + Create operation: No resource name is + expected for the new asset set asset + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed asset set + asset is expected, in this format: + ``customers/{customer_id}/assetSetAssets/{asset_set_id}~{asset_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: gagr_asset_set_asset.AssetSetAsset = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_asset_set_asset.AssetSetAsset, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateAssetSetAssetsResponse(proto.Message): + r"""Response message for an asset set asset mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAssetSetAssetResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateAssetSetAssetResult"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateAssetSetAssetResult", + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateAssetSetAssetResult(proto.Message): + r"""The result for the asset set asset mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + asset_set_asset (google.ads.googleads.v24.resources.types.AssetSetAsset): + The mutated asset set asset with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + asset_set_asset: gagr_asset_set_asset.AssetSetAsset = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_asset_set_asset.AssetSetAsset, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/asset_set_service.py b/google/ads/googleads/v24/services/types/asset_set_service.py new file mode 100644 index 000000000..4a2584be3 --- /dev/null +++ b/google/ads/googleads/v24/services/types/asset_set_service.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import asset_set as gagr_asset_set +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAssetSetsRequest", + "AssetSetOperation", + "MutateAssetSetsResponse", + "MutateAssetSetResult", + }, +) + + +class MutateAssetSetsRequest(proto.Message): + r"""Request message for + [AssetSetService.MutateAssetSets][google.ads.googleads.v24.services.AssetSetService.MutateAssetSets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose asset + sets are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AssetSetOperation]): + Required. The list of operations to perform + on individual asset sets. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AssetSetOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AssetSetOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class AssetSetOperation(proto.Message): + r"""A single operation (create, remove) on an asset set. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.AssetSet): + Create operation: No resource name is + expected for the new asset set + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.AssetSet): + Update operation: The asset set is expected + to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed asset set + is expected, in this format: + ``customers/{customer_id}/assetSets/{asset_set_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_asset_set.AssetSet = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_asset_set.AssetSet, + ) + update: gagr_asset_set.AssetSet = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_asset_set.AssetSet, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateAssetSetsResponse(proto.Message): + r"""Response message for an asset set mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAssetSetResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateAssetSetResult"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateAssetSetResult", + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateAssetSetResult(proto.Message): + r"""The result for the asset set mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + asset_set (google.ads.googleads.v24.resources.types.AssetSet): + The mutated asset set with only mutable fields after mutate. + The field will only be returned when response_content_type + is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + asset_set: gagr_asset_set.AssetSet = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_asset_set.AssetSet, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/audience_insights_service.py b/google/ads/googleads/v24/services/types/audience_insights_service.py new file mode 100644 index 000000000..18acc8acb --- /dev/null +++ b/google/ads/googleads/v24/services/types/audience_insights_service.py @@ -0,0 +1,1186 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import additional_application_info +from google.ads.googleads.v24.common.types import audience_insights_attribute +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.common.types import dates +from google.ads.googleads.v24.enums.types import audience_insights_dimension +from google.ads.googleads.v24.enums.types import ( + audience_insights_marketing_objective, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "GenerateInsightsFinderReportRequest", + "GenerateInsightsFinderReportResponse", + "GenerateAudienceCompositionInsightsRequest", + "GenerateAudienceCompositionInsightsResponse", + "GenerateSuggestedTargetingInsightsRequest", + "GenerateSuggestedTargetingInsightsResponse", + "TargetingSuggestionMetrics", + "ListAudienceInsightsAttributesRequest", + "ListAudienceInsightsAttributesResponse", + "ListInsightsEligibleDatesRequest", + "ListInsightsEligibleDatesResponse", + "GenerateAudienceOverlapInsightsRequest", + "GenerateAudienceOverlapInsightsResponse", + "DimensionOverlapResult", + "AudienceOverlapItem", + "GenerateTargetingSuggestionMetricsRequest", + "GenerateTargetingSuggestionMetricsResponse", + "GenerateAudienceDefinitionRequest", + "GenerateAudienceDefinitionResponse", + "AudienceInsightsDimensions", + "InsightsAudienceDefinition", + "InsightsAudienceDescription", + "InsightsAudience", + "AudienceCompositionSection", + "AudienceCompositionAttributeCluster", + "AudienceCompositionMetrics", + "AudienceCompositionAttribute", + }, +) + + +class GenerateInsightsFinderReportRequest(proto.Message): + r"""Request message for + [AudienceInsightsService.GenerateInsightsFinderReport][google.ads.googleads.v24.services.AudienceInsightsService.GenerateInsightsFinderReport]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + baseline_audience (google.ads.googleads.v24.services.types.InsightsAudience): + Required. A baseline audience for this + report, typically all people in a region. + specific_audience (google.ads.googleads.v24.services.types.InsightsAudience): + Required. The specific audience of interest + for this report. The insights in the report + will be based on attributes more prevalent in + this audience than in the report's baseline + audience. + customer_insights_group (str): + The name of the customer being planned for. + This is a user-defined value. + insights_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + baseline_audience: "InsightsAudience" = proto.Field( + proto.MESSAGE, + number=6, + message="InsightsAudience", + ) + specific_audience: "InsightsAudience" = proto.Field( + proto.MESSAGE, + number=7, + message="InsightsAudience", + ) + customer_insights_group: str = proto.Field( + proto.STRING, + number=4, + ) + insights_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=5, + message=additional_application_info.AdditionalApplicationInfo, + ) + + +class GenerateInsightsFinderReportResponse(proto.Message): + r"""The response message for + [AudienceInsightsService.GenerateInsightsFinderReport][google.ads.googleads.v24.services.AudienceInsightsService.GenerateInsightsFinderReport], + containing the shareable URL for the report. + + Attributes: + saved_report_url (str): + An HTTPS URL providing a deep link into the + Insights Finder UI with the report inputs filled + in according to the request. + """ + + saved_report_url: str = proto.Field( + proto.STRING, + number=1, + ) + + +class GenerateAudienceCompositionInsightsRequest(proto.Message): + r"""Request message for + [AudienceInsightsService.GenerateAudienceCompositionInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceCompositionInsights]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + audience (google.ads.googleads.v24.services.types.InsightsAudience): + Required. The audience of interest for which + insights are being requested. + baseline_audience (google.ads.googleads.v24.services.types.InsightsAudience): + The baseline audience to which the audience + of interest is being compared. + data_month (str): + The one-month range of historical data to use + for insights, in the format "yyyy-mm". If unset, + insights will be returned for the last thirty + days of data. + dimensions (MutableSequence[google.ads.googleads.v24.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension]): + Required. The audience dimensions for which composition + insights should be returned. Supported dimensions are + KNOWLEDGE_GRAPH, GEO_TARGET_COUNTRY, SUB_COUNTRY_LOCATION, + YOUTUBE_CHANNEL, YOUTUBE_LINEUP, AFFINITY_USER_INTEREST, + IN_MARKET_USER_INTEREST, LIFE_EVENT_USER_INTEREST, + PARENTAL_STATUS, INCOME_RANGE, AGE_RANGE, and GENDER. + customer_insights_group (str): + The name of the customer being planned for. + This is a user-defined value. + insights_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + audience: "InsightsAudience" = proto.Field( + proto.MESSAGE, + number=2, + message="InsightsAudience", + ) + baseline_audience: "InsightsAudience" = proto.Field( + proto.MESSAGE, + number=6, + message="InsightsAudience", + ) + data_month: str = proto.Field( + proto.STRING, + number=3, + ) + dimensions: MutableSequence[ + audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension + ] = proto.RepeatedField( + proto.ENUM, + number=4, + enum=audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension, + ) + customer_insights_group: str = proto.Field( + proto.STRING, + number=5, + ) + insights_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=7, + message=additional_application_info.AdditionalApplicationInfo, + ) + + +class GenerateAudienceCompositionInsightsResponse(proto.Message): + r"""Response message for + [AudienceInsightsService.GenerateAudienceCompositionInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceCompositionInsights]. + + Attributes: + sections (MutableSequence[google.ads.googleads.v24.services.types.AudienceCompositionSection]): + The contents of the insights report, + organized into sections. Each section is + associated with one of the + AudienceInsightsDimension values in the request. + There may be more than one section per + dimension. + """ + + sections: MutableSequence["AudienceCompositionSection"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="AudienceCompositionSection", + ) + ) + + +class GenerateSuggestedTargetingInsightsRequest(proto.Message): + r"""Request message for + [AudienceInsightsService.GenerateSuggestedTargetingInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateSuggestedTargetingInsights]. + + 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: + customer_id (str): + Required. The ID of the customer. + customer_insights_group (str): + Optional. The name of the customer being + planned for. This is a user-defined value. + insights_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + audience_definition (google.ads.googleads.v24.services.types.InsightsAudienceDefinition): + Provide a seed audience to get suggestions + for. + + This field is a member of `oneof`_ ``audience_input``. + audience_description (google.ads.googleads.v24.services.types.InsightsAudienceDescription): + Provide a text description of an audience to get + AI-generated targeting suggestions. This can take around 5 + or more seconds to complete. Supported marketing objectives + are: AWARENESS and CONSIDERATION. Supported dimensions are: + AGE_RANGE, GENDER, PARENTAL_STATUS, AFFINITY_USER_INTEREST, + IN_MARKET_USER_INTEREST and LIFE_EVENT_USER_INTEREST. + + This field is a member of `oneof`_ ``audience_input``. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + customer_insights_group: str = proto.Field( + proto.STRING, + number=5, + ) + insights_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=8, + message=additional_application_info.AdditionalApplicationInfo, + ) + audience_definition: "InsightsAudienceDefinition" = proto.Field( + proto.MESSAGE, + number=6, + oneof="audience_input", + message="InsightsAudienceDefinition", + ) + audience_description: "InsightsAudienceDescription" = proto.Field( + proto.MESSAGE, + number=7, + oneof="audience_input", + message="InsightsAudienceDescription", + ) + + +class GenerateSuggestedTargetingInsightsResponse(proto.Message): + r"""Response message for + [AudienceInsightsService.GenerateSuggestedTargetingInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateSuggestedTargetingInsights]. + + Attributes: + suggestions (MutableSequence[google.ads.googleads.v24.services.types.TargetingSuggestionMetrics]): + Suggested insights for targetable audiences. + """ + + suggestions: MutableSequence["TargetingSuggestionMetrics"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="TargetingSuggestionMetrics", + ) + ) + + +class TargetingSuggestionMetrics(proto.Message): + r"""A suggested targetable audience relevant to the requested + audience. + + Attributes: + locations (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadata]): + Suggested location targeting. These attributes all have + dimension GEO_TARGET_COUNTRY or SUB_COUNTRY_LOCATION + age_ranges (MutableSequence[google.ads.googleads.v24.common.types.AgeRangeInfo]): + Suggested age targeting; may be empty + indicating no age targeting. + gender (google.ads.googleads.v24.common.types.GenderInfo): + Suggested gender targeting. If present, this + attribute has dimension GENDER. + parental_status (google.ads.googleads.v24.common.types.ParentalStatusInfo): + A Parental Status value (parent, or not a + parent). + user_interests (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadataGroup]): + List of user interest attributes with + metadata defining the audience. The combination + has a logical AND-of-ORs structure: The + attributes within each + AudienceInsightsAttributeMetadataGroup are ORed, + and the groups themselves are ANDed. + coverage (float): + The fraction (from 0 to 1 inclusive) of the + requested audience that can be reached using the + suggested targeting. + index (float): + The ratio of coverage to the coverage of the + baseline audience or zero if this ratio is + undefined or is not meaningful. + potential_youtube_reach (int): + The approximate estimated number of people + that can be reached on YouTube using this + targeting. + """ + + locations: MutableSequence[ + audience_insights_attribute.AudienceInsightsAttributeMetadata + ] = proto.RepeatedField( + proto.MESSAGE, + number=9, + message=audience_insights_attribute.AudienceInsightsAttributeMetadata, + ) + age_ranges: MutableSequence[criteria.AgeRangeInfo] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=criteria.AgeRangeInfo, + ) + gender: criteria.GenderInfo = proto.Field( + proto.MESSAGE, + number=3, + message=criteria.GenderInfo, + ) + parental_status: criteria.ParentalStatusInfo = proto.Field( + proto.MESSAGE, + number=8, + message=criteria.ParentalStatusInfo, + ) + user_interests: MutableSequence[ + audience_insights_attribute.AudienceInsightsAttributeMetadataGroup + ] = proto.RepeatedField( + proto.MESSAGE, + number=11, + message=audience_insights_attribute.AudienceInsightsAttributeMetadataGroup, + ) + coverage: float = proto.Field( + proto.DOUBLE, + number=5, + ) + index: float = proto.Field( + proto.DOUBLE, + number=6, + ) + potential_youtube_reach: int = proto.Field( + proto.INT64, + number=7, + ) + + +class ListAudienceInsightsAttributesRequest(proto.Message): + r"""Request message for + [AudienceInsightsService.ListAudienceInsightsAttributes][google.ads.googleads.v24.services.AudienceInsightsService.ListAudienceInsightsAttributes]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + dimensions (MutableSequence[google.ads.googleads.v24.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension]): + Required. The types of attributes to be returned. Supported + dimensions are CATEGORY, KNOWLEDGE_GRAPH, DEVICE, + GEO_TARGET_COUNTRY, SUB_COUNTRY_LOCATION, YOUTUBE_LINEUP, + AFFINITY_USER_INTEREST, IN_MARKET_USER_INTEREST, + LIFE_EVENT_USER_INTEREST, PARENTAL_STATUS, INCOME_RANGE, + AGE_RANGE, and GENDER. + query_text (str): + Required. A free text query. If the requested dimensions + include Attributes CATEGORY or KNOWLEDGE_GRAPH, then the + attributes returned for those dimensions will match or be + related to this string. For other dimensions, this field is + ignored and all available attributes are returned. + customer_insights_group (str): + The name of the customer being planned for. + This is a user-defined value. + insights_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + location_country_filters (MutableSequence[google.ads.googleads.v24.common.types.LocationInfo]): + If SUB_COUNTRY_LOCATION attributes are one of the requested + dimensions and this field is present, then the + SUB_COUNTRY_LOCATION attributes returned will be located in + these countries. If this field is absent, then location + attributes are not filtered by country. Setting this field + when SUB_COUNTRY_LOCATION attributes are not requested will + return an error. + youtube_reach_location (google.ads.googleads.v24.common.types.LocationInfo): + If present, potential YouTube reach estimates within the + specified market will be returned for attributes for which + they are available. Reach is only available for the + AGE_RANGE, GENDER, AFFINITY_USER_INTEREST and + IN_MARKET_USER_INTEREST dimensions, and may not be available + for every attribute of those dimensions in every market. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + dimensions: MutableSequence[ + audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension + ] = proto.RepeatedField( + proto.ENUM, + number=2, + enum=audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension, + ) + query_text: str = proto.Field( + proto.STRING, + number=3, + ) + customer_insights_group: str = proto.Field( + proto.STRING, + number=4, + ) + insights_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=7, + message=additional_application_info.AdditionalApplicationInfo, + ) + location_country_filters: MutableSequence[criteria.LocationInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=5, + message=criteria.LocationInfo, + ) + ) + youtube_reach_location: criteria.LocationInfo = proto.Field( + proto.MESSAGE, + number=6, + message=criteria.LocationInfo, + ) + + +class ListAudienceInsightsAttributesResponse(proto.Message): + r"""Response message for + [AudienceInsightsService.ListAudienceInsightsAttributes][google.ads.googleads.v24.services.AudienceInsightsService.ListAudienceInsightsAttributes]. + + Attributes: + attributes (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadata]): + The attributes matching the search query. + """ + + attributes: MutableSequence[ + audience_insights_attribute.AudienceInsightsAttributeMetadata + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=audience_insights_attribute.AudienceInsightsAttributeMetadata, + ) + + +class ListInsightsEligibleDatesRequest(proto.Message): + r"""Request message for + [AudienceInsightsService.ListInsightsEligibleDates][google.ads.googleads.v24.services.AudienceInsightsService.ListInsightsEligibleDates]. + + Attributes: + insights_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + """ + + insights_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=1, + message=additional_application_info.AdditionalApplicationInfo, + ) + + +class ListInsightsEligibleDatesResponse(proto.Message): + r"""Response message for + [AudienceInsightsService.ListInsightsEligibleDates][google.ads.googleads.v24.services.AudienceInsightsService.ListInsightsEligibleDates]. + + Attributes: + data_months (MutableSequence[str]): + The months for which AudienceInsights data is + currently available, each represented as a + string in the form "YYYY-MM". + last_thirty_days (google.ads.googleads.v24.common.types.DateRange): + The actual dates covered by the "last 30 days" date range + that will be used implicitly for + [AudienceInsightsService.GenerateAudienceCompositionInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceCompositionInsights] + requests that have no data_month set. + """ + + data_months: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + last_thirty_days: dates.DateRange = proto.Field( + proto.MESSAGE, + number=2, + message=dates.DateRange, + ) + + +class GenerateAudienceOverlapInsightsRequest(proto.Message): + r"""Request message for + [AudienceInsightsService.GenerateAudienceOverlapInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceOverlapInsights]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + country_location (google.ads.googleads.v24.common.types.LocationInfo): + Required. The country in which to calculate + the sizes and overlaps of audiences. + primary_attribute (google.ads.googleads.v24.common.types.AudienceInsightsAttribute): + Required. The audience attribute that should + be intersected with all other eligible + audiences. This must be an Affinity or + In-Market UserInterest, an AgeRange or a Gender. + dimensions (MutableSequence[google.ads.googleads.v24.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension]): + Required. The types of attributes of which to calculate the + overlap with the primary_attribute. The values must be a + subset of AFFINITY_USER_INTEREST, IN_MARKET_USER_INTEREST, + AGE_RANGE and GENDER. + customer_insights_group (str): + The name of the customer being planned for. + This is a user-defined value. + insights_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + country_location: criteria.LocationInfo = proto.Field( + proto.MESSAGE, + number=2, + message=criteria.LocationInfo, + ) + primary_attribute: audience_insights_attribute.AudienceInsightsAttribute = ( + proto.Field( + proto.MESSAGE, + number=6, + message=audience_insights_attribute.AudienceInsightsAttribute, + ) + ) + dimensions: MutableSequence[ + audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension + ] = proto.RepeatedField( + proto.ENUM, + number=4, + enum=audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension, + ) + customer_insights_group: str = proto.Field( + proto.STRING, + number=5, + ) + insights_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=7, + message=additional_application_info.AdditionalApplicationInfo, + ) + + +class GenerateAudienceOverlapInsightsResponse(proto.Message): + r"""Response message for + [AudienceInsightsService.GenerateAudienceOverlapInsights][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceOverlapInsights]. + + Attributes: + primary_attribute_metadata (google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadata): + Metadata for the primary attribute, including + potential YouTube reach. + dimension_results (MutableSequence[google.ads.googleads.v24.services.types.DimensionOverlapResult]): + Lists of attributes and their overlap with + the primary attribute, one list per requested + dimension. + """ + + primary_attribute_metadata: ( + audience_insights_attribute.AudienceInsightsAttributeMetadata + ) = proto.Field( + proto.MESSAGE, + number=3, + message=audience_insights_attribute.AudienceInsightsAttributeMetadata, + ) + dimension_results: MutableSequence["DimensionOverlapResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="DimensionOverlapResult", + ) + ) + + +class DimensionOverlapResult(proto.Message): + r"""A list of audience attributes of a single dimension, including their + overlap with a primary attribute, returned as part of a + [GenerateAudienceOverlapInsightsResponse][google.ads.googleads.v24.services.GenerateAudienceOverlapInsightsResponse]. + + Attributes: + dimension (google.ads.googleads.v24.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension): + The dimension of all the attributes in this + section. + items (MutableSequence[google.ads.googleads.v24.services.types.AudienceOverlapItem]): + The attributes and their overlap with the + primary attribute. + """ + + dimension: ( + audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension + ) = proto.Field( + proto.ENUM, + number=1, + enum=audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension, + ) + items: MutableSequence["AudienceOverlapItem"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AudienceOverlapItem", + ) + + +class AudienceOverlapItem(proto.Message): + r"""An audience attribute, with metadata including the overlap + between this attribute's potential YouTube reach and that of a + primary attribute. + + Attributes: + attribute_metadata (google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadata): + The attribute and its metadata, including + potential YouTube reach. + potential_youtube_reach_intersection (int): + The estimated size of the intersection of + this audience attribute with the primary + attribute, that is, the number of reachable + YouTube users who match BOTH the primary + attribute and this one. + """ + + attribute_metadata: ( + audience_insights_attribute.AudienceInsightsAttributeMetadata + ) = proto.Field( + proto.MESSAGE, + number=3, + message=audience_insights_attribute.AudienceInsightsAttributeMetadata, + ) + potential_youtube_reach_intersection: int = proto.Field( + proto.INT64, + number=2, + ) + + +class GenerateTargetingSuggestionMetricsRequest(proto.Message): + r"""Request message for + [AudienceInsightsService.GenerateTargetingSuggestionMetrics][google.ads.googleads.v24.services.AudienceInsightsService.GenerateTargetingSuggestionMetrics]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + audiences (MutableSequence[google.ads.googleads.v24.services.types.InsightsAudience]): + Required. Audiences to request metrics for. + customer_insights_group (str): + Optional. The name of the customer being + planned for. This is a user-defined value. + insights_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + audiences: MutableSequence["InsightsAudience"] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="InsightsAudience", + ) + customer_insights_group: str = proto.Field( + proto.STRING, + number=3, + ) + insights_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=4, + message=additional_application_info.AdditionalApplicationInfo, + ) + + +class GenerateTargetingSuggestionMetricsResponse(proto.Message): + r"""Response message for + [AudienceInsightsService.GenerateTargetingSuggestionMetrics][google.ads.googleads.v24.services.AudienceInsightsService.GenerateTargetingSuggestionMetrics]. + + Attributes: + suggestions (MutableSequence[google.ads.googleads.v24.services.types.TargetingSuggestionMetrics]): + Suggested targetable audiences. There will be one suggestion + for each + [GenerateTargetingSuggestionMetricsRequest.audiences][google.ads.googleads.v24.services.GenerateTargetingSuggestionMetricsRequest.audiences] + requested, matching the order requested. + """ + + suggestions: MutableSequence["TargetingSuggestionMetrics"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="TargetingSuggestionMetrics", + ) + ) + + +class GenerateAudienceDefinitionRequest(proto.Message): + r"""Request message for + [AudienceInsightsService.GenerateAudienceDefinition][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceDefinition]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + audience_description (google.ads.googleads.v24.services.types.InsightsAudienceDescription): + Required. Provide a text description of an audience to get + AI-generated structured suggestions. This can take around 5 + or more seconds to complete Supported marketing objectives + are: AWARENESS, CONSIDERATION and RESEARCH. Supported + dimensions are: AGE_RANGE, GENDER, PARENTAL_STATUS, + AFFINITY_USER_INTEREST, IN_MARKET_USER_INTEREST, + LIFE_EVENT_USER_INTEREST, CATEGORY and KNOWLEDGE_GRAPH. + customer_insights_group (str): + Optional. The name of the customer being + planned for. This is a user-defined value. + insights_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + audience_description: "InsightsAudienceDescription" = proto.Field( + proto.MESSAGE, + number=2, + message="InsightsAudienceDescription", + ) + customer_insights_group: str = proto.Field( + proto.STRING, + number=3, + ) + insights_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=4, + message=additional_application_info.AdditionalApplicationInfo, + ) + + +class GenerateAudienceDefinitionResponse(proto.Message): + r"""Response message for + [AudienceInsightsService.GenerateAudienceDefinition][google.ads.googleads.v24.services.AudienceInsightsService.GenerateAudienceDefinition]. + + Attributes: + high_relevance_attributes (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadata]): + The attributes that make up the audience + definition. + medium_relevance_attributes (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadata]): + Additional attributes that are less relevant + but still related to the audience description. + Use these attributes to broaden the audience + definition to reach more users. + """ + + high_relevance_attributes: MutableSequence[ + audience_insights_attribute.AudienceInsightsAttributeMetadata + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=audience_insights_attribute.AudienceInsightsAttributeMetadata, + ) + medium_relevance_attributes: MutableSequence[ + audience_insights_attribute.AudienceInsightsAttributeMetadata + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=audience_insights_attribute.AudienceInsightsAttributeMetadata, + ) + + +class AudienceInsightsDimensions(proto.Message): + r"""A collection of dimensions to be used for generating + insights. + + Attributes: + dimensions (MutableSequence[google.ads.googleads.v24.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension]): + Required. A list of dimensions. + """ + + dimensions: MutableSequence[ + audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum=audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension, + ) + + +class InsightsAudienceDefinition(proto.Message): + r"""A structured definition of the audience of interest for which + insights are being requested in AudienceInsightsService. + + Attributes: + audience (google.ads.googleads.v24.services.types.InsightsAudience): + Required. The audience of interest for which + insights are being requested. + baseline_audience (google.ads.googleads.v24.services.types.InsightsAudience): + Optional. The baseline audience. The default, + if unspecified, is all people in the same + country as the audience of interest. + data_month (str): + Optional. The one-month range of historical + data to use for insights, in the format + "yyyy-mm". If unset, insights will be returned + for the last thirty days of data. + """ + + audience: "InsightsAudience" = proto.Field( + proto.MESSAGE, + number=1, + message="InsightsAudience", + ) + baseline_audience: "InsightsAudience" = proto.Field( + proto.MESSAGE, + number=2, + message="InsightsAudience", + ) + data_month: str = proto.Field( + proto.STRING, + number=3, + ) + + +class InsightsAudienceDescription(proto.Message): + r"""A text description of the audience of interest for which + insights are being requested in AudienceInsightsService. + + 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: + country_locations (MutableSequence[google.ads.googleads.v24.common.types.LocationInfo]): + Required. The countries for the audience. + audience_description (str): + Required. An English language text + description of an audience to get suggestions + for. Maximum length is 2000 characters. For + example, "Women in their 30s who love to + travel". + marketing_objective (google.ads.googleads.v24.enums.types.AudienceInsightsMarketingObjectiveEnum.AudienceInsightsMarketingObjective): + Optional. An optional marketing objective + which will influence the type of suggestions + produced. + + This field is a member of `oneof`_ ``output_types``. + audience_dimensions (google.ads.googleads.v24.services.types.AudienceInsightsDimensions): + Optional. An optional list of audience + dimensions to return. + + This field is a member of `oneof`_ ``output_types``. + """ + + country_locations: MutableSequence[criteria.LocationInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=criteria.LocationInfo, + ) + ) + audience_description: str = proto.Field( + proto.STRING, + number=2, + ) + marketing_objective: ( + audience_insights_marketing_objective.AudienceInsightsMarketingObjectiveEnum.AudienceInsightsMarketingObjective + ) = proto.Field( + proto.ENUM, + number=4, + oneof="output_types", + enum=audience_insights_marketing_objective.AudienceInsightsMarketingObjectiveEnum.AudienceInsightsMarketingObjective, + ) + audience_dimensions: "AudienceInsightsDimensions" = proto.Field( + proto.MESSAGE, + number=5, + oneof="output_types", + message="AudienceInsightsDimensions", + ) + + +class InsightsAudience(proto.Message): + r"""A set of users, defined by various characteristics, for which + insights can be requested in AudienceInsightsService. + + Attributes: + country_locations (MutableSequence[google.ads.googleads.v24.common.types.LocationInfo]): + Required. The countries for the audience. + sub_country_locations (MutableSequence[google.ads.googleads.v24.common.types.LocationInfo]): + Sub-country geographic location attributes. If present, each + of these must be contained in one of the countries in this + audience. If absent, the audience is geographically to the + country_locations and no further. + gender (google.ads.googleads.v24.common.types.GenderInfo): + Gender for the audience. If absent, the + audience does not restrict by gender. + age_ranges (MutableSequence[google.ads.googleads.v24.common.types.AgeRangeInfo]): + Age ranges for the audience. If absent, the + audience represents all people over 18 that + match the other attributes. + parental_status (google.ads.googleads.v24.common.types.ParentalStatusInfo): + Parental status for the audience. If absent, + the audience does not restrict by parental + status. + income_ranges (MutableSequence[google.ads.googleads.v24.common.types.IncomeRangeInfo]): + Household income percentile ranges for the + audience. If absent, the audience does not + restrict by household income range. + lineups (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsLineup]): + Lineups representing the YouTube content + viewed by the audience. + user_list (google.ads.googleads.v24.common.types.UserListInfo): + User list to be targeted by the audience. + topic_audience_combinations (MutableSequence[google.ads.googleads.v24.common.types.InsightsAudienceAttributeGroup]): + A list of audience attribute groups + consisting of one or more Knowledge Graph + entities, Product & Service Categories and user + interests that describe an audience. The groups + have a logical AND-of-ORs structure: + + 1. Attributes within each + InsightsAudienceAttributeGroup are combined + with OR. + + 2. The groups themselves are combined together + with AND. + + For example, an audience (Interest A OR Interest + B) AND (Entity C) is represented using two + groups. The first group contains the two + interests and the second group contains the + entity. + """ + + country_locations: MutableSequence[criteria.LocationInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=criteria.LocationInfo, + ) + ) + sub_country_locations: MutableSequence[criteria.LocationInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message=criteria.LocationInfo, + ) + ) + gender: criteria.GenderInfo = proto.Field( + proto.MESSAGE, + number=3, + message=criteria.GenderInfo, + ) + age_ranges: MutableSequence[criteria.AgeRangeInfo] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=criteria.AgeRangeInfo, + ) + parental_status: criteria.ParentalStatusInfo = proto.Field( + proto.MESSAGE, + number=5, + message=criteria.ParentalStatusInfo, + ) + income_ranges: MutableSequence[criteria.IncomeRangeInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=6, + message=criteria.IncomeRangeInfo, + ) + ) + lineups: MutableSequence[ + audience_insights_attribute.AudienceInsightsLineup + ] = proto.RepeatedField( + proto.MESSAGE, + number=10, + message=audience_insights_attribute.AudienceInsightsLineup, + ) + user_list: criteria.UserListInfo = proto.Field( + proto.MESSAGE, + number=11, + message=criteria.UserListInfo, + ) + topic_audience_combinations: MutableSequence[ + audience_insights_attribute.InsightsAudienceAttributeGroup + ] = proto.RepeatedField( + proto.MESSAGE, + number=12, + message=audience_insights_attribute.InsightsAudienceAttributeGroup, + ) + + +class AudienceCompositionSection(proto.Message): + r"""A collection of related attributes of the same type in an + audience composition insights report. + + Attributes: + dimension (google.ads.googleads.v24.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension): + The type of the attributes in this section. + top_attributes (MutableSequence[google.ads.googleads.v24.services.types.AudienceCompositionAttribute]): + The most relevant segments for this audience. If dimension + is GENDER, AGE_RANGE or PARENTAL_STATUS, then this list of + attributes is exhaustive. + clustered_attributes (MutableSequence[google.ads.googleads.v24.services.types.AudienceCompositionAttributeCluster]): + Additional attributes for this audience, grouped into + clusters. Only populated if dimension is YOUTUBE_CHANNEL. + """ + + dimension: ( + audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension + ) = proto.Field( + proto.ENUM, + number=1, + enum=audience_insights_dimension.AudienceInsightsDimensionEnum.AudienceInsightsDimension, + ) + top_attributes: MutableSequence["AudienceCompositionAttribute"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=3, + message="AudienceCompositionAttribute", + ) + ) + clustered_attributes: MutableSequence[ + "AudienceCompositionAttributeCluster" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="AudienceCompositionAttributeCluster", + ) + + +class AudienceCompositionAttributeCluster(proto.Message): + r"""A collection of related attributes, with metadata and + metrics, in an audience composition insights report. + + Attributes: + cluster_display_name (str): + The name of this cluster of attributes + cluster_metrics (google.ads.googleads.v24.services.types.AudienceCompositionMetrics): + If the dimension associated with this cluster is + YOUTUBE_CHANNEL, then cluster_metrics are metrics associated + with the cluster as a whole. For other dimensions, this + field is unset. + attributes (MutableSequence[google.ads.googleads.v24.services.types.AudienceCompositionAttribute]): + The individual attributes that make up this + cluster, with metadata and metrics. + """ + + cluster_display_name: str = proto.Field( + proto.STRING, + number=1, + ) + cluster_metrics: "AudienceCompositionMetrics" = proto.Field( + proto.MESSAGE, + number=3, + message="AudienceCompositionMetrics", + ) + attributes: MutableSequence["AudienceCompositionAttribute"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=4, + message="AudienceCompositionAttribute", + ) + ) + + +class AudienceCompositionMetrics(proto.Message): + r"""The share and index metrics associated with an attribute in + an audience composition insights report. + + Attributes: + baseline_audience_share (float): + The fraction (from 0 to 1 inclusive) of the + baseline audience that match the attribute. + audience_share (float): + The fraction (from 0 to 1 inclusive) of the + specific audience that match the attribute. + index (float): + The ratio of audience_share to baseline_audience_share, or + zero if this ratio is undefined or is not meaningful. + score (float): + A relevance score from 0 to 1 inclusive. + """ + + baseline_audience_share: float = proto.Field( + proto.DOUBLE, + number=1, + ) + audience_share: float = proto.Field( + proto.DOUBLE, + number=2, + ) + index: float = proto.Field( + proto.DOUBLE, + number=3, + ) + score: float = proto.Field( + proto.DOUBLE, + number=4, + ) + + +class AudienceCompositionAttribute(proto.Message): + r"""An audience attribute with metadata and metrics. + + Attributes: + attribute_metadata (google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadata): + The attribute with its metadata. + metrics (google.ads.googleads.v24.services.types.AudienceCompositionMetrics): + Share and index metrics for the attribute. + """ + + attribute_metadata: ( + audience_insights_attribute.AudienceInsightsAttributeMetadata + ) = proto.Field( + proto.MESSAGE, + number=3, + message=audience_insights_attribute.AudienceInsightsAttributeMetadata, + ) + metrics: "AudienceCompositionMetrics" = proto.Field( + proto.MESSAGE, + number=2, + message="AudienceCompositionMetrics", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/audience_service.py b/google/ads/googleads/v24/services/types/audience_service.py new file mode 100644 index 000000000..87e35eb1f --- /dev/null +++ b/google/ads/googleads/v24/services/types/audience_service.py @@ -0,0 +1,188 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import audience as gagr_audience +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateAudiencesRequest", + "MutateAudiencesResponse", + "AudienceOperation", + "MutateAudienceResult", + }, +) + + +class MutateAudiencesRequest(proto.Message): + r"""Request message for + [AudienceService.MutateAudiences][google.ads.googleads.v24.services.AudienceService.MutateAudiences]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + audiences are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.AudienceOperation]): + Required. The list of operations to perform + on individual audiences. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["AudienceOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AudienceOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class MutateAudiencesResponse(proto.Message): + r"""Response message for an audience mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateAudienceResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateAudienceResult"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateAudienceResult", + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class AudienceOperation(proto.Message): + r"""A single operation (create, update) on an audience. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.Audience): + Create operation: No resource name is + expected for the new audience + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.Audience): + Update operation: The audience is expected to + have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_audience.Audience = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_audience.Audience, + ) + update: gagr_audience.Audience = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_audience.Audience, + ) + + +class MutateAudienceResult(proto.Message): + r"""The result for the audience mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + audience (google.ads.googleads.v24.resources.types.Audience): + The mutated Audience with only mutable fields after mutate. + The field will only be returned when response_content_type + is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + audience: gagr_audience.Audience = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_audience.Audience, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/automatically_created_asset_removal_service.py b/google/ads/googleads/v24/services/types/automatically_created_asset_removal_service.py new file mode 100644 index 000000000..d20144333 --- /dev/null +++ b/google/ads/googleads/v24/services/types/automatically_created_asset_removal_service.py @@ -0,0 +1,127 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import asset_field_type +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "RemoveCampaignAutomaticallyCreatedAssetRequest", + "RemoveCampaignAutomaticallyCreatedAssetOperation", + "RemoveCampaignAutomaticallyCreatedAssetResponse", + }, +) + + +class RemoveCampaignAutomaticallyCreatedAssetRequest(proto.Message): + r"""Request message for + [AutomaticallyCreatedAssetRemovalService.RemoveCampaignAutomaticallyCreatedAsset][google.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService.RemoveCampaignAutomaticallyCreatedAsset]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose assets + are being removed. + operations (MutableSequence[google.ads.googleads.v24.services.types.RemoveCampaignAutomaticallyCreatedAssetOperation]): + Required. The list of operations. + partial_failure (bool): + Required. If true, successful operations will + be carried out and invalid operations will + return errors. If false, all operations will be + carried out in one transaction if and only if + they are all valid. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence[ + "RemoveCampaignAutomaticallyCreatedAssetOperation" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="RemoveCampaignAutomaticallyCreatedAssetOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class RemoveCampaignAutomaticallyCreatedAssetOperation(proto.Message): + r"""A single operation to remove an automatically created asset + from a campaign. + + Attributes: + campaign (str): + Required. The resource name of the campaign. + asset (str): + Required. The resource name of the asset to + remove. + field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + Required. The field type of the asset to + remove. + """ + + campaign: str = proto.Field( + proto.STRING, + number=1, + ) + asset: str = proto.Field( + proto.STRING, + number=2, + ) + field_type: asset_field_type.AssetFieldTypeEnum.AssetFieldType = ( + proto.Field( + proto.ENUM, + number=3, + enum=asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + ) + + +class RemoveCampaignAutomaticallyCreatedAssetResponse(proto.Message): + r"""Response message for + [AutomaticallyCreatedAssetRemovalService.RemoveCampaignAutomaticallyCreatedAsset][google.ads.googleads.v24.services.AutomaticallyCreatedAssetRemovalService.RemoveCampaignAutomaticallyCreatedAsset]. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to + AutomaticallyCreatedAssetRemoval failures in the + partial failure mode. Returned when all errors + occur inside the operations. If any errors occur + outside the operations (for example, auth + errors), RPC level error will be returned. See + https://developers.google.com/google-ads/api/docs/best-practices/partial-failures + for more information about partial failure. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/batch_job_service.py b/google/ads/googleads/v24/services/types/batch_job_service.py new file mode 100644 index 000000000..233dfec36 --- /dev/null +++ b/google/ads/googleads/v24/services/types/batch_job_service.py @@ -0,0 +1,335 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import batch_job +from google.ads.googleads.v24.services.types import google_ads_service +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateBatchJobRequest", + "BatchJobOperation", + "MutateBatchJobResponse", + "MutateBatchJobResult", + "RunBatchJobRequest", + "AddBatchJobOperationsRequest", + "AddBatchJobOperationsResponse", + "ListBatchJobResultsRequest", + "ListBatchJobResultsResponse", + "BatchJobResult", + }, +) + + +class MutateBatchJobRequest(proto.Message): + r"""Request message for + [BatchJobService.MutateBatchJob][google.ads.googleads.v24.services.BatchJobService.MutateBatchJob]. + + Attributes: + customer_id (str): + Required. The ID of the customer for which to + create a batch job. + operation (google.ads.googleads.v24.services.types.BatchJobOperation): + Required. The operation to perform on an + individual batch job. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: "BatchJobOperation" = proto.Field( + proto.MESSAGE, + number=2, + message="BatchJobOperation", + ) + + +class BatchJobOperation(proto.Message): + r"""A single operation on a batch job. + + 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: + create (google.ads.googleads.v24.resources.types.BatchJob): + Create operation: No resource name is + expected for the new batch job. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: The batch job must not have been run. A + resource name for the removed batch job is expected, in this + format: + + ``customers/{customer_id}/batchJobs/{batch_job_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: batch_job.BatchJob = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=batch_job.BatchJob, + ) + remove: str = proto.Field( + proto.STRING, + number=4, + oneof="operation", + ) + + +class MutateBatchJobResponse(proto.Message): + r"""Response message for + [BatchJobService.MutateBatchJob][google.ads.googleads.v24.services.BatchJobService.MutateBatchJob]. + + Attributes: + result (google.ads.googleads.v24.services.types.MutateBatchJobResult): + The result for the mutate. + """ + + result: "MutateBatchJobResult" = proto.Field( + proto.MESSAGE, + number=1, + message="MutateBatchJobResult", + ) + + +class MutateBatchJobResult(proto.Message): + r"""The result for the batch job mutate. + + Attributes: + resource_name (str): + The resource name of the batch job. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class RunBatchJobRequest(proto.Message): + r"""Request message for + [BatchJobService.RunBatchJob][google.ads.googleads.v24.services.BatchJobService.RunBatchJob]. + + Attributes: + resource_name (str): + Required. The resource name of the BatchJob + to run. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class AddBatchJobOperationsRequest(proto.Message): + r"""Request message for + [BatchJobService.AddBatchJobOperations][google.ads.googleads.v24.services.BatchJobService.AddBatchJobOperations]. + + Attributes: + resource_name (str): + Required. The resource name of the batch job. + sequence_token (str): + A token used to enforce sequencing. + + The first AddBatchJobOperations request for a batch job + should not set sequence_token. Subsequent requests must set + sequence_token to the value of next_sequence_token received + in the previous AddBatchJobOperations response. + mutate_operations (MutableSequence[google.ads.googleads.v24.services.types.MutateOperation]): + Required. The list of mutates being added. + + Operations can use negative integers as temp ids + to signify dependencies between entities created + in this batch job. For example, a customer with + id = 1234 can create a campaign and an ad group + in that same campaign by creating a campaign in + the first operation with the resource name + explicitly set to "customers/1234/campaigns/-1", + and creating an ad group in the second operation + with the campaign field also set to + "customers/1234/campaigns/-1". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + sequence_token: str = proto.Field( + proto.STRING, + number=2, + ) + mutate_operations: MutableSequence[google_ads_service.MutateOperation] = ( + proto.RepeatedField( + proto.MESSAGE, + number=3, + message=google_ads_service.MutateOperation, + ) + ) + + +class AddBatchJobOperationsResponse(proto.Message): + r"""Response message for + [BatchJobService.AddBatchJobOperations][google.ads.googleads.v24.services.BatchJobService.AddBatchJobOperations]. + + Attributes: + total_operations (int): + The total number of operations added so far + for this batch job. + next_sequence_token (str): + The sequence token to be used when calling + AddBatchJobOperations again if more operations need to be + added. The next AddBatchJobOperations request must set the + sequence_token field to the value of this field. + """ + + total_operations: int = proto.Field( + proto.INT64, + number=1, + ) + next_sequence_token: str = proto.Field( + proto.STRING, + number=2, + ) + + +class ListBatchJobResultsRequest(proto.Message): + r"""Request message for + [BatchJobService.ListBatchJobResults][google.ads.googleads.v24.services.BatchJobService.ListBatchJobResults]. + + Attributes: + resource_name (str): + Required. The resource name of the batch job + whose results are being listed. + page_token (str): + Token of the page to retrieve. If not specified, the first + page of results will be returned. Use the value obtained + from ``next_page_token`` in the previous response in order + to request the next page of results. + page_size (int): + Number of elements to retrieve in a single page. The default + and the page_size limit is 1000. A value of 0 or an unset + page size will be defaulted to 1000. A page size less than 0 + or greater than 1000 will result in an INVALID_PAGE_SIZE + error. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + page_token: str = proto.Field( + proto.STRING, + number=2, + ) + page_size: int = proto.Field( + proto.INT32, + number=3, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=4, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class ListBatchJobResultsResponse(proto.Message): + r"""Response message for + [BatchJobService.ListBatchJobResults][google.ads.googleads.v24.services.BatchJobService.ListBatchJobResults]. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.BatchJobResult]): + The list of rows that matched the query. + next_page_token (str): + Pagination token used to retrieve the next page of results. + Pass the content of this string as the ``page_token`` + attribute of the next request. ``next_page_token`` is not + returned for the last page. + """ + + @property + def raw_page(self): + return self + + results: MutableSequence["BatchJobResult"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="BatchJobResult", + ) + next_page_token: str = proto.Field( + proto.STRING, + number=2, + ) + + +class BatchJobResult(proto.Message): + r"""An individual batch job result. + + Attributes: + operation_index (int): + Index of the mutate operation. + mutate_operation_response (google.ads.googleads.v24.services.types.MutateOperationResponse): + Response for the mutate. + May be empty if errors occurred. + status (google.rpc.status_pb2.Status): + Details of the errors when processing the + operation. + """ + + operation_index: int = proto.Field( + proto.INT64, + number=1, + ) + mutate_operation_response: google_ads_service.MutateOperationResponse = ( + proto.Field( + proto.MESSAGE, + number=2, + message=google_ads_service.MutateOperationResponse, + ) + ) + status: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/benchmarks_service.py b/google/ads/googleads/v24/services/types/benchmarks_service.py new file mode 100644 index 000000000..a26405da1 --- /dev/null +++ b/google/ads/googleads/v24/services/types/benchmarks_service.py @@ -0,0 +1,770 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import additional_application_info +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.common.types import dates as gagc_dates +from google.ads.googleads.v24.enums.types import benchmarks_marketing_objective +from google.ads.googleads.v24.enums.types import ( + benchmarks_source_type as gage_benchmarks_source_type, +) +from google.ads.googleads.v24.enums.types import benchmarks_time_granularity + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "ListBenchmarksAvailableDatesRequest", + "ListBenchmarksAvailableDatesResponse", + "ListBenchmarksLocationsRequest", + "ListBenchmarksLocationsResponse", + "BenchmarksLocation", + "ListBenchmarksProductsRequest", + "ListBenchmarksProductsResponse", + "BenchmarksProductMetadata", + "ListBenchmarksSourcesRequest", + "ListBenchmarksSourcesResponse", + "BenchmarksSourceMetadata", + "IndustryVerticalInfo", + "GenerateBenchmarksMetricsRequest", + "BenchmarksSource", + "ProductFilter", + "BreakdownDefinition", + "GenerateBenchmarksMetricsResponse", + "BreakdownMetrics", + "BreakdownKey", + "Metrics", + "RateMetrics", + }, +) + + +class ListBenchmarksAvailableDatesRequest(proto.Message): + r"""Request message for + [BenchmarksService.ListBenchmarksAvailableDates][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksAvailableDates]. + + Attributes: + application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Additional information on the application + issuing the request. + """ + + application_info: additional_application_info.AdditionalApplicationInfo = ( + proto.Field( + proto.MESSAGE, + number=1, + message=additional_application_info.AdditionalApplicationInfo, + ) + ) + + +class ListBenchmarksAvailableDatesResponse(proto.Message): + r"""Response message for + [BenchmarksService.ListBenchmarksAvailableDates][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksAvailableDates]. + + Attributes: + supported_dates (google.ads.googleads.v24.common.types.DateRange): + The dates that support benchmarks metrics. + Data is supported for any dates within this date + range inclusive. + """ + + supported_dates: gagc_dates.DateRange = proto.Field( + proto.MESSAGE, + number=1, + message=gagc_dates.DateRange, + ) + + +class ListBenchmarksLocationsRequest(proto.Message): + r"""Request message for + [BenchmarksService.ListBenchmarksLocations][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksLocations]. + + Attributes: + application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Additional information on the application + issuing the request. + """ + + application_info: additional_application_info.AdditionalApplicationInfo = ( + proto.Field( + proto.MESSAGE, + number=1, + message=additional_application_info.AdditionalApplicationInfo, + ) + ) + + +class ListBenchmarksLocationsResponse(proto.Message): + r"""Response message for + [BenchmarksService.ListBenchmarksLocations][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksLocations]. + + Attributes: + benchmarks_locations (MutableSequence[google.ads.googleads.v24.services.types.BenchmarksLocation]): + The list of locations supported for + benchmarks data. + """ + + benchmarks_locations: MutableSequence["BenchmarksLocation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="BenchmarksLocation", + ) + ) + + +class BenchmarksLocation(proto.Message): + r"""A location that supports benchmarks data. + + Attributes: + location_name (str): + The unique location name in English. + location_type (str): + The location's type. Location types correspond to + target_type returned by searching location type in + GoogleAdsService.Search/SearchStream. + location_info (google.ads.googleads.v24.common.types.LocationInfo): + Information on the geographic location, + including the location ID. + """ + + location_name: str = proto.Field( + proto.STRING, + number=1, + ) + location_type: str = proto.Field( + proto.STRING, + number=2, + ) + location_info: criteria.LocationInfo = proto.Field( + proto.MESSAGE, + number=3, + message=criteria.LocationInfo, + ) + + +class ListBenchmarksProductsRequest(proto.Message): + r"""Request message for + [BenchmarksService.ListBenchmarksProducts][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksProducts]. + + Attributes: + application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Additional information on the application + issuing the request. + """ + + application_info: additional_application_info.AdditionalApplicationInfo = ( + proto.Field( + proto.MESSAGE, + number=1, + message=additional_application_info.AdditionalApplicationInfo, + ) + ) + + +class ListBenchmarksProductsResponse(proto.Message): + r"""Response message for + [BenchmarksService.ListBenchmarksProducts][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksProducts]. + + Attributes: + benchmarks_products (MutableSequence[google.ads.googleads.v24.services.types.BenchmarksProductMetadata]): + The list of products available for benchmarks + data. + """ + + benchmarks_products: MutableSequence["BenchmarksProductMetadata"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="BenchmarksProductMetadata", + ) + ) + + +class BenchmarksProductMetadata(proto.Message): + r"""The metadata associated with a product supported for + benchmarks data. + + Attributes: + product_name (str): + The name of the product. + product_code (str): + The identifier of the product. The identifier can be used as + inputs for + [BenchmarksService.GenerateBenchmarksMetrics][google.ads.googleads.v24.services.BenchmarksService.GenerateBenchmarksMetrics]. + marketing_objective (google.ads.googleads.v24.enums.types.BenchmarksMarketingObjectiveEnum.BenchmarksMarketingObjective): + The marketing objective associated with the + product. A marketing objective is a broader + classification of products. + """ + + product_name: str = proto.Field( + proto.STRING, + number=1, + ) + product_code: str = proto.Field( + proto.STRING, + number=2, + ) + marketing_objective: ( + benchmarks_marketing_objective.BenchmarksMarketingObjectiveEnum.BenchmarksMarketingObjective + ) = proto.Field( + proto.ENUM, + number=3, + enum=benchmarks_marketing_objective.BenchmarksMarketingObjectiveEnum.BenchmarksMarketingObjective, + ) + + +class ListBenchmarksSourcesRequest(proto.Message): + r"""Request message for + [BenchmarksService.ListBenchmarksSources][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksSources]. + + Attributes: + benchmarks_sources (MutableSequence[google.ads.googleads.v24.enums.types.BenchmarksSourceTypeEnum.BenchmarksSourceType]): + Required. The types of benchmarks sources to be returned + (for example, INDUSTRY_VERTICAL). + application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Additional information on the application + issuing the request. + """ + + benchmarks_sources: MutableSequence[ + gage_benchmarks_source_type.BenchmarksSourceTypeEnum.BenchmarksSourceType + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum=gage_benchmarks_source_type.BenchmarksSourceTypeEnum.BenchmarksSourceType, + ) + application_info: additional_application_info.AdditionalApplicationInfo = ( + proto.Field( + proto.MESSAGE, + number=2, + message=additional_application_info.AdditionalApplicationInfo, + ) + ) + + +class ListBenchmarksSourcesResponse(proto.Message): + r"""Response message for + [BenchmarksService.ListBenchmarksSources][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksSources]. + + Attributes: + benchmarks_sources (MutableSequence[google.ads.googleads.v24.services.types.BenchmarksSourceMetadata]): + The list of available source used to generate + benchmarks data for. + """ + + benchmarks_sources: MutableSequence["BenchmarksSourceMetadata"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="BenchmarksSourceMetadata", + ) + ) + + +class BenchmarksSourceMetadata(proto.Message): + r"""The metadata associated with a benchmarks source. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + benchmarks_source_type (google.ads.googleads.v24.enums.types.BenchmarksSourceTypeEnum.BenchmarksSourceType): + The type of benchmarks source. + industry_vertical_info (google.ads.googleads.v24.services.types.IndustryVerticalInfo): + Information on the Industry Vertical. + + This field is a member of `oneof`_ ``benchmarks_source_info``. + """ + + benchmarks_source_type: ( + gage_benchmarks_source_type.BenchmarksSourceTypeEnum.BenchmarksSourceType + ) = proto.Field( + proto.ENUM, + number=1, + enum=gage_benchmarks_source_type.BenchmarksSourceTypeEnum.BenchmarksSourceType, + ) + industry_vertical_info: "IndustryVerticalInfo" = proto.Field( + proto.MESSAGE, + number=2, + oneof="benchmarks_source_info", + message="IndustryVerticalInfo", + ) + + +class IndustryVerticalInfo(proto.Message): + r"""The information associated with an Industry Vertical. + + Attributes: + industry_vertical_name (str): + The name of the Industry Vertical. + industry_vertical_id (int): + The unique identifier of the Industry + Vertical. + parent_industry_vertical_id (int): + The unique identifier of the parent Industry + Vertical, if exists. + """ + + industry_vertical_name: str = proto.Field( + proto.STRING, + number=1, + ) + industry_vertical_id: int = proto.Field( + proto.INT64, + number=2, + ) + parent_industry_vertical_id: int = proto.Field( + proto.INT64, + number=3, + ) + + +class GenerateBenchmarksMetricsRequest(proto.Message): + r"""Request message for + [BenchmarksService.GenerateBenchmarksMetrics][google.ads.googleads.v24.services.BenchmarksService.GenerateBenchmarksMetrics]. + + Attributes: + customer_id (str): + Required. The ID of the customer. Supply a + client customer ID to generate metrics for the + customer. A manager account customer ID will not + return customer metrics since it does not have + any associated direct ad campaigns. + date_range (google.ads.googleads.v24.common.types.DateRange): + The date range to aggregate metrics over. If unset, data + will be returned for the most recent quarter for which data + is available. Dates can be retrieved using + [BenchmarksService.ListBenchmarksAvailableDates][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksAvailableDates]. + location (google.ads.googleads.v24.common.types.LocationInfo): + Required. The location to generate benchmarks + metrics for. + benchmarks_source (google.ads.googleads.v24.services.types.BenchmarksSource): + Required. The source used to generate + benchmarks metrics for. + product_filter (google.ads.googleads.v24.services.types.ProductFilter): + Required. The products to aggregate metrics + over. Product filter settings support a list of + product IDs or a list of marketing objectives. + breakdown_definition (google.ads.googleads.v24.services.types.BreakdownDefinition): + Optional. The set of dimensions to group + metrics by. If multiple dimensions are selected, + cross-dimension breakdowns are returned. + currency_code (str): + Optional. The three-character ISO 4217 + currency code. If unspecified, the default + currency for monetary values is USD. + customer_benchmarks_group (str): + The name of the customer being planned for. + This is a user-defined value. + application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Additional information on the application + issuing the request. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + date_range: gagc_dates.DateRange = proto.Field( + proto.MESSAGE, + number=2, + message=gagc_dates.DateRange, + ) + location: criteria.LocationInfo = proto.Field( + proto.MESSAGE, + number=3, + message=criteria.LocationInfo, + ) + benchmarks_source: "BenchmarksSource" = proto.Field( + proto.MESSAGE, + number=4, + message="BenchmarksSource", + ) + product_filter: "ProductFilter" = proto.Field( + proto.MESSAGE, + number=5, + message="ProductFilter", + ) + breakdown_definition: "BreakdownDefinition" = proto.Field( + proto.MESSAGE, + number=9, + message="BreakdownDefinition", + ) + currency_code: str = proto.Field( + proto.STRING, + number=6, + ) + customer_benchmarks_group: str = proto.Field( + proto.STRING, + number=7, + ) + application_info: additional_application_info.AdditionalApplicationInfo = ( + proto.Field( + proto.MESSAGE, + number=8, + message=additional_application_info.AdditionalApplicationInfo, + ) + ) + + +class BenchmarksSource(proto.Message): + r"""The source used to generate benchmarks metrics for. The ID of the + source can be obtained from + [BenchmarksService.ListBenchmarksSources][google.ads.googleads.v24.services.BenchmarksService.ListBenchmarksSources]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + industry_vertical_id (int): + The ID of the Industry Vertical. + + This field is a member of `oneof`_ ``benchmarks_source_id``. + """ + + industry_vertical_id: int = proto.Field( + proto.INT64, + number=1, + oneof="benchmarks_source_id", + ) + + +class ProductFilter(proto.Message): + r"""The type and list of products to aggregate benchmarks metrics + over. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + product_list (google.ads.googleads.v24.services.types.ProductFilter.ProductList): + The list of products. + + This field is a member of `oneof`_ ``filter_settings``. + marketing_objective_list (google.ads.googleads.v24.services.types.ProductFilter.MarketingObjectiveList): + The list of marketing goals. Marketing + objective is a broader product classification of + products. + + This field is a member of `oneof`_ ``filter_settings``. + """ + + class ProductList(proto.Message): + r"""The list of products to generate benchmarks metrics for. + + Attributes: + product_codes (MutableSequence[str]): + Required. Products to generate benchmarks + metrics for. + """ + + product_codes: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + + class MarketingObjectiveList(proto.Message): + r"""The list of marketing objectives to generate benchmarks + metrics for. + + Attributes: + marketing_objectives (MutableSequence[google.ads.googleads.v24.enums.types.BenchmarksMarketingObjectiveEnum.BenchmarksMarketingObjective]): + Required. Marketing objectives to generate + benchmarks metrics for. + """ + + marketing_objectives: MutableSequence[ + benchmarks_marketing_objective.BenchmarksMarketingObjectiveEnum.BenchmarksMarketingObjective + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum=benchmarks_marketing_objective.BenchmarksMarketingObjectiveEnum.BenchmarksMarketingObjective, + ) + + product_list: ProductList = proto.Field( + proto.MESSAGE, + number=1, + oneof="filter_settings", + message=ProductList, + ) + marketing_objective_list: MarketingObjectiveList = proto.Field( + proto.MESSAGE, + number=2, + oneof="filter_settings", + message=MarketingObjectiveList, + ) + + +class BreakdownDefinition(proto.Message): + r"""The set of dimensions to group metrics by. + + Attributes: + date_breakdown (google.ads.googleads.v24.enums.types.BenchmarksTimeGranularityEnum.BenchmarksTimeGranularity): + The granularity for segmenting metrics by date. When this + field is set, a valid date_range in the + GenerateBenchmarksMetricsRequest is required and must + precisely align with the boundaries of the selected + granularity. + + For example, a monthly breakdown must start on the first day + of a month and end on the last day of a month. A quarterly + breakdown must start on the first day of a quarter and end + on the last day of a quarter. A weekly breakdown must start + on a Sunday and end on a Saturday. This is different from + the ISO 8601 standard, where weeks start on Monday. + """ + + date_breakdown: ( + benchmarks_time_granularity.BenchmarksTimeGranularityEnum.BenchmarksTimeGranularity + ) = proto.Field( + proto.ENUM, + number=1, + enum=benchmarks_time_granularity.BenchmarksTimeGranularityEnum.BenchmarksTimeGranularity, + ) + + +class GenerateBenchmarksMetricsResponse(proto.Message): + r"""Response message for + [BenchmarksService.GenerateBenchmarksMetrics][google.ads.googleads.v24.services.BenchmarksService.GenerateBenchmarksMetrics]. + + Attributes: + customer_metrics (google.ads.googleads.v24.services.types.Metrics): + Metrics belonging to the customer. + average_benchmarks_metrics (google.ads.googleads.v24.services.types.Metrics): + Metrics for the selected benchmarks source. + breakdown_metrics (MutableSequence[google.ads.googleads.v24.services.types.BreakdownMetrics]): + Breakdown metrics grouped by dimensions. + """ + + customer_metrics: "Metrics" = proto.Field( + proto.MESSAGE, + number=1, + message="Metrics", + ) + average_benchmarks_metrics: "Metrics" = proto.Field( + proto.MESSAGE, + number=2, + message="Metrics", + ) + breakdown_metrics: MutableSequence["BreakdownMetrics"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=3, + message="BreakdownMetrics", + ) + ) + + +class BreakdownMetrics(proto.Message): + r"""Metrics for a given breakdown. + + Attributes: + breakdown_key (google.ads.googleads.v24.services.types.BreakdownKey): + Dimensions by which the breakdown metrics are + grouped by. + customer_metrics (google.ads.googleads.v24.services.types.Metrics): + Metrics belonging to the customer. + average_benchmarks_metrics (google.ads.googleads.v24.services.types.Metrics): + Metrics for the selected benchmarks source. + """ + + breakdown_key: "BreakdownKey" = proto.Field( + proto.MESSAGE, + number=1, + message="BreakdownKey", + ) + customer_metrics: "Metrics" = proto.Field( + proto.MESSAGE, + number=2, + message="Metrics", + ) + average_benchmarks_metrics: "Metrics" = proto.Field( + proto.MESSAGE, + number=3, + message="Metrics", + ) + + +class BreakdownKey(proto.Message): + r"""Dimensions by which the breakdown metrics are grouped by. + + Attributes: + dates (google.ads.googleads.v24.common.types.DateRange): + Dates used for the breakdown. For example, + this represents the start and end dates of the + week for a weekly breakdown. + """ + + dates: gagc_dates.DateRange = proto.Field( + proto.MESSAGE, + number=1, + message=gagc_dates.DateRange, + ) + + +class Metrics(proto.Message): + r"""All metrics returned against a criteria. + + Attributes: + average_rate_metrics (google.ads.googleads.v24.services.types.RateMetrics): + Average rate metrics calculated by dividing + one metric by another. + """ + + average_rate_metrics: "RateMetrics" = proto.Field( + proto.MESSAGE, + number=1, + message="RateMetrics", + ) + + +class RateMetrics(proto.Message): + r"""Average rate metrics. Metrics that represent monetary values + are returned in USD by default, if unspecified in the request. + + Attributes: + average_cpm (float): + Average cost-per-thousand impressions (CPM). + average_active_view_cpm (float): + Average cost-per-thousand viewable + impressions. + trueview_average_cpv (float): + The average TrueView cost-per-view (CPV) is + defined by the total cost of all ad TrueView + views divided by the number of TrueView views. + average_cpc (float): + The average cost-per-click (CPC) is defined + by the total cost of all clicks divided by the + total number of clicks received. + average_cpi (float): + The average cost-per-interaction (CPI) is + defined by the total cost of all interactions + divided by the total number of interactions. + average_cpe (float): + The average cost-per-engagement (CPE) is + defined by the total cost of all ad engagements + divided by the total number of ad engagements. + interaction_rate (float): + How often people interact with your ad after + it is shown to them. This is the number of + interactions divided by the number of times your + ad is shown. + engagement_rate (float): + How often people engage with your ad after + it's shown to them. This is the number of ad + expansions divided by the number of times your + ad is shown. + active_view_viewability (float): + The percentage of time when your ad appeared + on an Active View enabled site (measurable + impressions) and was viewable (viewable + impressions). + trueview_view_rate (float): + Number of completed TrueView views divided by + the number of impressions. + click_through_rate (float): + The number of clicks your ad receives + (Clicks) divided by the number of times your ad + is shown (Impressions). + video_completion_p25_rate (float): + Percentage of impressions where the viewer + watched 25% of your video. + video_completion_p50_rate (float): + Percentage of impressions where the viewer + watched 50% of your video. + video_completion_p75_rate (float): + Percentage of impressions where the viewer + watched 75% of your video. + video_completion_p100_rate (float): + Percentage of impressions where the viewer + watched all of your video. + """ + + average_cpm: float = proto.Field( + proto.DOUBLE, + number=1, + ) + average_active_view_cpm: float = proto.Field( + proto.DOUBLE, + number=2, + ) + trueview_average_cpv: float = proto.Field( + proto.DOUBLE, + number=3, + ) + average_cpc: float = proto.Field( + proto.DOUBLE, + number=4, + ) + average_cpi: float = proto.Field( + proto.DOUBLE, + number=5, + ) + average_cpe: float = proto.Field( + proto.DOUBLE, + number=6, + ) + interaction_rate: float = proto.Field( + proto.DOUBLE, + number=7, + ) + engagement_rate: float = proto.Field( + proto.DOUBLE, + number=8, + ) + active_view_viewability: float = proto.Field( + proto.DOUBLE, + number=9, + ) + trueview_view_rate: float = proto.Field( + proto.DOUBLE, + number=10, + ) + click_through_rate: float = proto.Field( + proto.DOUBLE, + number=11, + ) + video_completion_p25_rate: float = proto.Field( + proto.DOUBLE, + number=12, + ) + video_completion_p50_rate: float = proto.Field( + proto.DOUBLE, + number=13, + ) + video_completion_p75_rate: float = proto.Field( + proto.DOUBLE, + number=14, + ) + video_completion_p100_rate: float = proto.Field( + proto.DOUBLE, + number=15, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/bidding_data_exclusion_service.py b/google/ads/googleads/v24/services/types/bidding_data_exclusion_service.py new file mode 100644 index 000000000..82be0ed6d --- /dev/null +++ b/google/ads/googleads/v24/services/types/bidding_data_exclusion_service.py @@ -0,0 +1,209 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + bidding_data_exclusion as gagr_bidding_data_exclusion, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateBiddingDataExclusionsRequest", + "BiddingDataExclusionOperation", + "MutateBiddingDataExclusionsResponse", + "MutateBiddingDataExclusionsResult", + }, +) + + +class MutateBiddingDataExclusionsRequest(proto.Message): + r"""Request message for + [BiddingDataExclusionService.MutateBiddingDataExclusions][google.ads.googleads.v24.services.BiddingDataExclusionService.MutateBiddingDataExclusions]. + + Attributes: + customer_id (str): + Required. ID of the customer whose data + exclusions are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.BiddingDataExclusionOperation]): + Required. The list of operations to perform + on individual data exclusions. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["BiddingDataExclusionOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="BiddingDataExclusionOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class BiddingDataExclusionOperation(proto.Message): + r"""A single operation (create, remove, update) on a data + exclusion. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.BiddingDataExclusion): + Create operation: No resource name is + expected for the new data exclusion. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.BiddingDataExclusion): + Update operation: The data exclusion is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed data + exclusion is expected, in this format: + + ``customers/{customer_id}/biddingDataExclusions/{data_exclusion_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_bidding_data_exclusion.BiddingDataExclusion = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_bidding_data_exclusion.BiddingDataExclusion, + ) + update: gagr_bidding_data_exclusion.BiddingDataExclusion = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_bidding_data_exclusion.BiddingDataExclusion, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateBiddingDataExclusionsResponse(proto.Message): + r"""Response message for data exclusions mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateBiddingDataExclusionsResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateBiddingDataExclusionsResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateBiddingDataExclusionsResult", + ) + ) + + +class MutateBiddingDataExclusionsResult(proto.Message): + r"""The result for the data exclusion mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + bidding_data_exclusion (google.ads.googleads.v24.resources.types.BiddingDataExclusion): + The mutated bidding data exclusion with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + bidding_data_exclusion: gagr_bidding_data_exclusion.BiddingDataExclusion = ( + proto.Field( + proto.MESSAGE, + number=2, + message=gagr_bidding_data_exclusion.BiddingDataExclusion, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/bidding_seasonality_adjustment_service.py b/google/ads/googleads/v24/services/types/bidding_seasonality_adjustment_service.py new file mode 100644 index 000000000..c257fdc17 --- /dev/null +++ b/google/ads/googleads/v24/services/types/bidding_seasonality_adjustment_service.py @@ -0,0 +1,213 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + bidding_seasonality_adjustment as gagr_bidding_seasonality_adjustment, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateBiddingSeasonalityAdjustmentsRequest", + "BiddingSeasonalityAdjustmentOperation", + "MutateBiddingSeasonalityAdjustmentsResponse", + "MutateBiddingSeasonalityAdjustmentsResult", + }, +) + + +class MutateBiddingSeasonalityAdjustmentsRequest(proto.Message): + r"""Request message for + [BiddingSeasonalityAdjustmentService.MutateBiddingSeasonalityAdjustments][google.ads.googleads.v24.services.BiddingSeasonalityAdjustmentService.MutateBiddingSeasonalityAdjustments]. + + Attributes: + customer_id (str): + Required. ID of the customer whose + seasonality adjustments are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.BiddingSeasonalityAdjustmentOperation]): + Required. The list of operations to perform + on individual seasonality adjustments. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["BiddingSeasonalityAdjustmentOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="BiddingSeasonalityAdjustmentOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class BiddingSeasonalityAdjustmentOperation(proto.Message): + r"""A single operation (create, remove, update) on a seasonality + adjustment. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.BiddingSeasonalityAdjustment): + Create operation: No resource name is + expected for the new seasonality adjustment. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.BiddingSeasonalityAdjustment): + Update operation: The seasonality adjustment + is expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed + seasonality adjustment is expected, in this format: + + ``customers/{customer_id}/biddingSeasonalityAdjustments/{seasonality_adjustment_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_bidding_seasonality_adjustment.BiddingSeasonalityAdjustment = ( + proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_bidding_seasonality_adjustment.BiddingSeasonalityAdjustment, + ) + ) + update: gagr_bidding_seasonality_adjustment.BiddingSeasonalityAdjustment = ( + proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_bidding_seasonality_adjustment.BiddingSeasonalityAdjustment, + ) + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateBiddingSeasonalityAdjustmentsResponse(proto.Message): + r"""Response message for seasonality adjustments mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateBiddingSeasonalityAdjustmentsResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateBiddingSeasonalityAdjustmentsResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateBiddingSeasonalityAdjustmentsResult", + ) + ) + + +class MutateBiddingSeasonalityAdjustmentsResult(proto.Message): + r"""The result for the seasonality adjustment mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + bidding_seasonality_adjustment (google.ads.googleads.v24.resources.types.BiddingSeasonalityAdjustment): + The mutated bidding seasonality adjustment with only mutable + fields after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + bidding_seasonality_adjustment: ( + gagr_bidding_seasonality_adjustment.BiddingSeasonalityAdjustment + ) = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_bidding_seasonality_adjustment.BiddingSeasonalityAdjustment, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/bidding_strategy_service.py b/google/ads/googleads/v24/services/types/bidding_strategy_service.py new file mode 100644 index 000000000..7a9302ec0 --- /dev/null +++ b/google/ads/googleads/v24/services/types/bidding_strategy_service.py @@ -0,0 +1,207 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + bidding_strategy as gagr_bidding_strategy, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateBiddingStrategiesRequest", + "BiddingStrategyOperation", + "MutateBiddingStrategiesResponse", + "MutateBiddingStrategyResult", + }, +) + + +class MutateBiddingStrategiesRequest(proto.Message): + r"""Request message for + [BiddingStrategyService.MutateBiddingStrategies][google.ads.googleads.v24.services.BiddingStrategyService.MutateBiddingStrategies]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + bidding strategies are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.BiddingStrategyOperation]): + Required. The list of operations to perform + on individual bidding strategies. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["BiddingStrategyOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="BiddingStrategyOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class BiddingStrategyOperation(proto.Message): + r"""A single operation (create, update, remove) on a bidding + strategy. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.BiddingStrategy): + Create operation: No resource name is + expected for the new bidding strategy. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.BiddingStrategy): + Update operation: The bidding strategy is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed bidding + strategy is expected, in this format: + + ``customers/{customer_id}/biddingStrategies/{bidding_strategy_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_bidding_strategy.BiddingStrategy = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_bidding_strategy.BiddingStrategy, + ) + update: gagr_bidding_strategy.BiddingStrategy = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_bidding_strategy.BiddingStrategy, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateBiddingStrategiesResponse(proto.Message): + r"""Response message for bidding strategy mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateBiddingStrategyResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateBiddingStrategyResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateBiddingStrategyResult", + ) + ) + + +class MutateBiddingStrategyResult(proto.Message): + r"""The result for the bidding strategy mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + bidding_strategy (google.ads.googleads.v24.resources.types.BiddingStrategy): + The mutated bidding strategy with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + bidding_strategy: gagr_bidding_strategy.BiddingStrategy = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_bidding_strategy.BiddingStrategy, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/billing_setup_service.py b/google/ads/googleads/v24/services/types/billing_setup_service.py new file mode 100644 index 000000000..2cd56d952 --- /dev/null +++ b/google/ads/googleads/v24/services/types/billing_setup_service.py @@ -0,0 +1,127 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import billing_setup + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateBillingSetupRequest", + "BillingSetupOperation", + "MutateBillingSetupResponse", + "MutateBillingSetupResult", + }, +) + + +class MutateBillingSetupRequest(proto.Message): + r"""Request message for billing setup mutate operations. + + Attributes: + customer_id (str): + Required. Id of the customer to apply the + billing setup mutate operation to. + operation (google.ads.googleads.v24.services.types.BillingSetupOperation): + Required. The operation to perform. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: "BillingSetupOperation" = proto.Field( + proto.MESSAGE, + number=2, + message="BillingSetupOperation", + ) + + +class BillingSetupOperation(proto.Message): + r"""A single operation on a billing setup, which describes the + cancellation of an existing billing setup. + + 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: + create (google.ads.googleads.v24.resources.types.BillingSetup): + Creates a billing setup. No resource name is + expected for the new billing setup. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Resource name of the billing setup to remove. A setup cannot + be removed unless it is in a pending state or its scheduled + start time is in the future. The resource name looks like + ``customers/{customer_id}/billingSetups/{billing_id}``. + + This field is a member of `oneof`_ ``operation``. + """ + + create: billing_setup.BillingSetup = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=billing_setup.BillingSetup, + ) + remove: str = proto.Field( + proto.STRING, + number=1, + oneof="operation", + ) + + +class MutateBillingSetupResponse(proto.Message): + r"""Response message for a billing setup operation. + + Attributes: + result (google.ads.googleads.v24.services.types.MutateBillingSetupResult): + A result that identifies the resource + affected by the mutate request. + """ + + result: "MutateBillingSetupResult" = proto.Field( + proto.MESSAGE, + number=1, + message="MutateBillingSetupResult", + ) + + +class MutateBillingSetupResult(proto.Message): + r"""Result for a single billing setup mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/brand_suggestion_service.py b/google/ads/googleads/v24/services/types/brand_suggestion_service.py new file mode 100644 index 000000000..c71bebd6d --- /dev/null +++ b/google/ads/googleads/v24/services/types/brand_suggestion_service.py @@ -0,0 +1,124 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import brand_state + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "SuggestBrandsRequest", + "SuggestBrandsResponse", + "BrandSuggestion", + }, +) + + +class SuggestBrandsRequest(proto.Message): + r"""Request message for + [BrandSuggestionService.SuggestBrands][google.ads.googleads.v24.services.BrandSuggestionService.SuggestBrands]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer_id (str): + Required. The ID of the customer onto which + to apply the brand suggestion operation. + brand_prefix (str): + Required. The prefix of a brand name. + + This field is a member of `oneof`_ ``_brand_prefix``. + selected_brands (MutableSequence[str]): + Optional. Ids of the brands already selected + by advertisers. They will be excluded in + response. These are expected to be brand ids not + brand names. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + brand_prefix: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + selected_brands: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + + +class SuggestBrandsResponse(proto.Message): + r"""Response message for + [BrandSuggestionService.SuggestBrands][google.ads.googleads.v24.services.BrandSuggestionService.SuggestBrands]. + + Attributes: + brands (MutableSequence[google.ads.googleads.v24.services.types.BrandSuggestion]): + Generated brand suggestions of verified + brands for the given prefix. + """ + + brands: MutableSequence["BrandSuggestion"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="BrandSuggestion", + ) + + +class BrandSuggestion(proto.Message): + r"""Information of brand suggestion. + + Attributes: + id (str): + Id for the brand. It would be CKG MID for + verified/global scoped brands. + name (str): + Name of the brand. + urls (MutableSequence[str]): + Urls which uniquely identify the brand. + state (google.ads.googleads.v24.enums.types.BrandStateEnum.BrandState): + Current state of the brand. + """ + + id: str = proto.Field( + proto.STRING, + number=1, + ) + name: str = proto.Field( + proto.STRING, + number=2, + ) + urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + state: brand_state.BrandStateEnum.BrandState = proto.Field( + proto.ENUM, + number=4, + enum=brand_state.BrandStateEnum.BrandState, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/campaign_asset_service.py b/google/ads/googleads/v24/services/types/campaign_asset_service.py new file mode 100644 index 000000000..2a4431da3 --- /dev/null +++ b/google/ads/googleads/v24/services/types/campaign_asset_service.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + campaign_asset as gagr_campaign_asset, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCampaignAssetsRequest", + "CampaignAssetOperation", + "MutateCampaignAssetsResponse", + "MutateCampaignAssetResult", + }, +) + + +class MutateCampaignAssetsRequest(proto.Message): + r"""Request message for + [CampaignAssetService.MutateCampaignAssets][google.ads.googleads.v24.services.CampaignAssetService.MutateCampaignAssets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign assets are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignAssetOperation]): + Required. The list of operations to perform + on individual campaign assets. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CampaignAssetOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignAssetOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CampaignAssetOperation(proto.Message): + r"""A single operation (create, update, remove) on a campaign + asset. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.CampaignAsset): + Create operation: No resource name is + expected for the new campaign asset. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.CampaignAsset): + Update operation: The campaign asset is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed campaign + asset is expected, in this format: + + ``customers/{customer_id}/campaignAssets/{campaign_id}~{asset_id}~{field_type}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_campaign_asset.CampaignAsset = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_campaign_asset.CampaignAsset, + ) + update: gagr_campaign_asset.CampaignAsset = proto.Field( + proto.MESSAGE, + number=3, + oneof="operation", + message=gagr_campaign_asset.CampaignAsset, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateCampaignAssetsResponse(proto.Message): + r"""Response message for a campaign asset mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCampaignAssetResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + results: MutableSequence["MutateCampaignAssetResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCampaignAssetResult", + ) + + +class MutateCampaignAssetResult(proto.Message): + r"""The result for the campaign asset mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + campaign_asset (google.ads.googleads.v24.resources.types.CampaignAsset): + The mutated campaign asset with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_asset: gagr_campaign_asset.CampaignAsset = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_campaign_asset.CampaignAsset, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/campaign_asset_set_service.py b/google/ads/googleads/v24/services/types/campaign_asset_set_service.py new file mode 100644 index 000000000..2974060d7 --- /dev/null +++ b/google/ads/googleads/v24/services/types/campaign_asset_set_service.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + campaign_asset_set as gagr_campaign_asset_set, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCampaignAssetSetsRequest", + "CampaignAssetSetOperation", + "MutateCampaignAssetSetsResponse", + "MutateCampaignAssetSetResult", + }, +) + + +class MutateCampaignAssetSetsRequest(proto.Message): + r"""Request message for + [CampaignAssetSetService.MutateCampaignAssetSets][google.ads.googleads.v24.services.CampaignAssetSetService.MutateCampaignAssetSets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign asset sets are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignAssetSetOperation]): + Required. The list of operations to perform + on individual campaign asset sets. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CampaignAssetSetOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignAssetSetOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CampaignAssetSetOperation(proto.Message): + r"""A single operation (create, remove) on a campaign asset set. + + 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: + create (google.ads.googleads.v24.resources.types.CampaignAssetSet): + Create operation: No resource name is + expected for the new campaign asset set. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed campaign + asset set is expected, in this format: + ``customers/{customer_id}/campaignAssetSets/{campaign_id}~{asset_set_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: gagr_campaign_asset_set.CampaignAssetSet = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_campaign_asset_set.CampaignAssetSet, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateCampaignAssetSetsResponse(proto.Message): + r"""Response message for a campaign asset set mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCampaignAssetSetResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateCampaignAssetSetResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateCampaignAssetSetResult", + ) + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateCampaignAssetSetResult(proto.Message): + r"""The result for the campaign asset set mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + campaign_asset_set (google.ads.googleads.v24.resources.types.CampaignAssetSet): + The mutated campaign asset set with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_asset_set: gagr_campaign_asset_set.CampaignAssetSet = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_campaign_asset_set.CampaignAssetSet, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/campaign_bid_modifier_service.py b/google/ads/googleads/v24/services/types/campaign_bid_modifier_service.py new file mode 100644 index 000000000..593606439 --- /dev/null +++ b/google/ads/googleads/v24/services/types/campaign_bid_modifier_service.py @@ -0,0 +1,209 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + campaign_bid_modifier as gagr_campaign_bid_modifier, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCampaignBidModifiersRequest", + "CampaignBidModifierOperation", + "MutateCampaignBidModifiersResponse", + "MutateCampaignBidModifierResult", + }, +) + + +class MutateCampaignBidModifiersRequest(proto.Message): + r"""Request message for + [CampaignBidModifierService.MutateCampaignBidModifiers][google.ads.googleads.v24.services.CampaignBidModifierService.MutateCampaignBidModifiers]. + + Attributes: + customer_id (str): + Required. ID of the customer whose campaign + bid modifiers are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignBidModifierOperation]): + Required. The list of operations to perform + on individual campaign bid modifiers. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CampaignBidModifierOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignBidModifierOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CampaignBidModifierOperation(proto.Message): + r"""A single operation (create, remove, update) on a campaign bid + modifier. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.CampaignBidModifier): + Create operation: No resource name is + expected for the new campaign bid modifier. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.CampaignBidModifier): + Update operation: The campaign bid modifier + is expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed campaign + bid modifier is expected, in this format: + + ``customers/{customer_id}/CampaignBidModifiers/{campaign_id}~{criterion_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_campaign_bid_modifier.CampaignBidModifier = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_campaign_bid_modifier.CampaignBidModifier, + ) + update: gagr_campaign_bid_modifier.CampaignBidModifier = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_campaign_bid_modifier.CampaignBidModifier, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateCampaignBidModifiersResponse(proto.Message): + r"""Response message for campaign bid modifiers mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCampaignBidModifierResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateCampaignBidModifierResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCampaignBidModifierResult", + ) + ) + + +class MutateCampaignBidModifierResult(proto.Message): + r"""The result for the criterion mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + campaign_bid_modifier (google.ads.googleads.v24.resources.types.CampaignBidModifier): + The mutated campaign bid modifier with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_bid_modifier: gagr_campaign_bid_modifier.CampaignBidModifier = ( + proto.Field( + proto.MESSAGE, + number=2, + message=gagr_campaign_bid_modifier.CampaignBidModifier, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/campaign_budget_service.py b/google/ads/googleads/v24/services/types/campaign_budget_service.py new file mode 100644 index 000000000..346bdc34a --- /dev/null +++ b/google/ads/googleads/v24/services/types/campaign_budget_service.py @@ -0,0 +1,207 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + campaign_budget as gagr_campaign_budget, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCampaignBudgetsRequest", + "CampaignBudgetOperation", + "MutateCampaignBudgetsResponse", + "MutateCampaignBudgetResult", + }, +) + + +class MutateCampaignBudgetsRequest(proto.Message): + r"""Request message for + [CampaignBudgetService.MutateCampaignBudgets][google.ads.googleads.v24.services.CampaignBudgetService.MutateCampaignBudgets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign budgets are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignBudgetOperation]): + Required. The list of operations to perform + on individual campaign budgets. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CampaignBudgetOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignBudgetOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CampaignBudgetOperation(proto.Message): + r"""A single operation (create, update, remove) on a campaign + budget. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.CampaignBudget): + Create operation: No resource name is + expected for the new budget. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.CampaignBudget): + Update operation: The campaign budget is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed budget is + expected, in this format: + + ``customers/{customer_id}/campaignBudgets/{budget_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_campaign_budget.CampaignBudget = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_campaign_budget.CampaignBudget, + ) + update: gagr_campaign_budget.CampaignBudget = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_campaign_budget.CampaignBudget, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateCampaignBudgetsResponse(proto.Message): + r"""Response message for campaign budget mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCampaignBudgetResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateCampaignBudgetResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCampaignBudgetResult", + ) + ) + + +class MutateCampaignBudgetResult(proto.Message): + r"""The result for the campaign budget mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + campaign_budget (google.ads.googleads.v24.resources.types.CampaignBudget): + The mutated campaign budget with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_budget: gagr_campaign_budget.CampaignBudget = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_campaign_budget.CampaignBudget, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/campaign_conversion_goal_service.py b/google/ads/googleads/v24/services/types/campaign_conversion_goal_service.py new file mode 100644 index 000000000..3fd38a0cc --- /dev/null +++ b/google/ads/googleads/v24/services/types/campaign_conversion_goal_service.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import campaign_conversion_goal +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCampaignConversionGoalsRequest", + "CampaignConversionGoalOperation", + "MutateCampaignConversionGoalsResponse", + "MutateCampaignConversionGoalResult", + }, +) + + +class MutateCampaignConversionGoalsRequest(proto.Message): + r"""Request message for + [CampaignConversionGoalService.MutateCampaignConversionGoals][google.ads.googleads.v24.services.CampaignConversionGoalService.MutateCampaignConversionGoals]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign conversion goals are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignConversionGoalOperation]): + Required. The list of operations to perform + on individual campaign conversion goal. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CampaignConversionGoalOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignConversionGoalOperation", + ) + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class CampaignConversionGoalOperation(proto.Message): + r"""A single operation (update) on a campaign conversion goal. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + update (google.ads.googleads.v24.resources.types.CampaignConversionGoal): + Update operation: The customer conversion + goal is expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=2, + message=field_mask_pb2.FieldMask, + ) + update: campaign_conversion_goal.CampaignConversionGoal = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=campaign_conversion_goal.CampaignConversionGoal, + ) + + +class MutateCampaignConversionGoalsResponse(proto.Message): + r"""Response message for a campaign conversion goal mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCampaignConversionGoalResult]): + All results for the mutate. + """ + + results: MutableSequence["MutateCampaignConversionGoalResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateCampaignConversionGoalResult", + ) + ) + + +class MutateCampaignConversionGoalResult(proto.Message): + r"""The result for the campaign conversion goal mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/campaign_criterion_service.py b/google/ads/googleads/v24/services/types/campaign_criterion_service.py new file mode 100644 index 000000000..e0887459f --- /dev/null +++ b/google/ads/googleads/v24/services/types/campaign_criterion_service.py @@ -0,0 +1,209 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + campaign_criterion as gagr_campaign_criterion, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCampaignCriteriaRequest", + "CampaignCriterionOperation", + "MutateCampaignCriteriaResponse", + "MutateCampaignCriterionResult", + }, +) + + +class MutateCampaignCriteriaRequest(proto.Message): + r"""Request message for + [CampaignCriterionService.MutateCampaignCriteria][google.ads.googleads.v24.services.CampaignCriterionService.MutateCampaignCriteria]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + criteria are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignCriterionOperation]): + Required. The list of operations to perform + on individual criteria. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CampaignCriterionOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignCriterionOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CampaignCriterionOperation(proto.Message): + r"""A single operation (create, update, remove) on a campaign + criterion. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.CampaignCriterion): + Create operation: No resource name is + expected for the new criterion. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.CampaignCriterion): + Update operation: The criterion is expected + to have a valid resource name. Note that for + smart campaigns, you cannot use the update + method to edit the geolocation target. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed criterion + is expected, in this format: + + ``customers/{customer_id}/campaignCriteria/{campaign_id}~{criterion_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_campaign_criterion.CampaignCriterion = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_campaign_criterion.CampaignCriterion, + ) + update: gagr_campaign_criterion.CampaignCriterion = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_campaign_criterion.CampaignCriterion, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateCampaignCriteriaResponse(proto.Message): + r"""Response message for campaign criterion mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCampaignCriterionResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateCampaignCriterionResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCampaignCriterionResult", + ) + ) + + +class MutateCampaignCriterionResult(proto.Message): + r"""The result for the criterion mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + campaign_criterion (google.ads.googleads.v24.resources.types.CampaignCriterion): + The mutated campaign criterion with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_criterion: gagr_campaign_criterion.CampaignCriterion = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_campaign_criterion.CampaignCriterion, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/campaign_customizer_service.py b/google/ads/googleads/v24/services/types/campaign_customizer_service.py new file mode 100644 index 000000000..f5568f537 --- /dev/null +++ b/google/ads/googleads/v24/services/types/campaign_customizer_service.py @@ -0,0 +1,188 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + campaign_customizer as gagr_campaign_customizer, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCampaignCustomizersRequest", + "CampaignCustomizerOperation", + "MutateCampaignCustomizersResponse", + "MutateCampaignCustomizerResult", + }, +) + + +class MutateCampaignCustomizersRequest(proto.Message): + r"""Request message for + [CampaignCustomizerService.MutateCampaignCustomizers][google.ads.googleads.v24.services.CampaignCustomizerService.MutateCampaignCustomizers]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign customizers are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignCustomizerOperation]): + Required. The list of operations to perform + on individual campaign customizers. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CampaignCustomizerOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignCustomizerOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CampaignCustomizerOperation(proto.Message): + r"""A single operation (create, remove) on a customizer + attribute. + + 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: + create (google.ads.googleads.v24.resources.types.CampaignCustomizer): + Create operation: No resource name is + expected for the new campaign customizer + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed campaign + customizer is expected, in this format: + ``customers/{customer_id}/campaignCustomizers/{campaign_id}~{customizer_attribute_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: gagr_campaign_customizer.CampaignCustomizer = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_campaign_customizer.CampaignCustomizer, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateCampaignCustomizersResponse(proto.Message): + r"""Response message for a campaign customizer mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCampaignCustomizerResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateCampaignCustomizerResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateCampaignCustomizerResult", + ) + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateCampaignCustomizerResult(proto.Message): + r"""The result for the campaign customizer mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + campaign_customizer (google.ads.googleads.v24.resources.types.CampaignCustomizer): + The mutated CampaignCustomizer with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_customizer: gagr_campaign_customizer.CampaignCustomizer = ( + proto.Field( + proto.MESSAGE, + number=2, + message=gagr_campaign_customizer.CampaignCustomizer, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/campaign_draft_service.py b/google/ads/googleads/v24/services/types/campaign_draft_service.py new file mode 100644 index 000000000..99ade0b79 --- /dev/null +++ b/google/ads/googleads/v24/services/types/campaign_draft_service.py @@ -0,0 +1,294 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + campaign_draft as gagr_campaign_draft, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCampaignDraftsRequest", + "PromoteCampaignDraftRequest", + "CampaignDraftOperation", + "MutateCampaignDraftsResponse", + "MutateCampaignDraftResult", + "ListCampaignDraftAsyncErrorsRequest", + "ListCampaignDraftAsyncErrorsResponse", + }, +) + + +class MutateCampaignDraftsRequest(proto.Message): + r"""Request message for + [CampaignDraftService.MutateCampaignDrafts][google.ads.googleads.v24.services.CampaignDraftService.MutateCampaignDrafts]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign drafts are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignDraftOperation]): + Required. The list of operations to perform + on individual campaign drafts. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CampaignDraftOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignDraftOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class PromoteCampaignDraftRequest(proto.Message): + r"""Request message for + [CampaignDraftService.PromoteCampaignDraft][google.ads.googleads.v24.services.CampaignDraftService.PromoteCampaignDraft]. + + Attributes: + campaign_draft (str): + Required. The resource name of the campaign + draft to promote. + validate_only (bool): + If true, the request is validated but no Long + Running Operation is created. Only errors are + returned. + """ + + campaign_draft: str = proto.Field( + proto.STRING, + number=1, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=2, + ) + + +class CampaignDraftOperation(proto.Message): + r"""A single operation (create, update, remove) on a campaign + draft. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.CampaignDraft): + Create operation: No resource name is + expected for the new campaign draft. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.CampaignDraft): + Update operation: The campaign draft is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: The campaign draft is expected to have a + valid resource name, in this format: + + ``customers/{customer_id}/campaignDrafts/{base_campaign_id}~{draft_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_campaign_draft.CampaignDraft = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_campaign_draft.CampaignDraft, + ) + update: gagr_campaign_draft.CampaignDraft = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_campaign_draft.CampaignDraft, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateCampaignDraftsResponse(proto.Message): + r"""Response message for campaign draft mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCampaignDraftResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateCampaignDraftResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCampaignDraftResult", + ) + + +class MutateCampaignDraftResult(proto.Message): + r"""The result for the campaign draft mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + campaign_draft (google.ads.googleads.v24.resources.types.CampaignDraft): + The mutated campaign draft with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_draft: gagr_campaign_draft.CampaignDraft = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_campaign_draft.CampaignDraft, + ) + + +class ListCampaignDraftAsyncErrorsRequest(proto.Message): + r"""Request message for + [CampaignDraftService.ListCampaignDraftAsyncErrors][google.ads.googleads.v24.services.CampaignDraftService.ListCampaignDraftAsyncErrors]. + + Attributes: + resource_name (str): + Required. The name of the campaign draft from + which to retrieve the async errors. + page_token (str): + Token of the page to retrieve. If not specified, the first + page of results will be returned. Use the value obtained + from ``next_page_token`` in the previous response in order + to request the next page of results. + page_size (int): + Number of elements to retrieve in a single + page. When a page request is too large, the + server may decide to further limit the number of + returned resources. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + page_token: str = proto.Field( + proto.STRING, + number=2, + ) + page_size: int = proto.Field( + proto.INT32, + number=3, + ) + + +class ListCampaignDraftAsyncErrorsResponse(proto.Message): + r"""Response message for + [CampaignDraftService.ListCampaignDraftAsyncErrors][google.ads.googleads.v24.services.CampaignDraftService.ListCampaignDraftAsyncErrors]. + + Attributes: + errors (MutableSequence[google.rpc.status_pb2.Status]): + Details of the errors when performing the + asynchronous operation. + next_page_token (str): + Pagination token used to retrieve the next page of results. + Pass the content of this string as the ``page_token`` + attribute of the next request. ``next_page_token`` is not + returned for the last page. + """ + + @property + def raw_page(self): + return self + + errors: MutableSequence[status_pb2.Status] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + next_page_token: str = proto.Field( + proto.STRING, + number=2, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/campaign_goal_config_service.py b/google/ads/googleads/v24/services/types/campaign_goal_config_service.py new file mode 100644 index 000000000..e4773494e --- /dev/null +++ b/google/ads/googleads/v24/services/types/campaign_goal_config_service.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import campaign_goal_config +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCampaignGoalConfigsRequest", + "CampaignGoalConfigOperation", + "MutateCampaignGoalConfigsResponse", + "MutateCampaignGoalConfigResult", + }, +) + + +class MutateCampaignGoalConfigsRequest(proto.Message): + r"""Request message for + [CampaignGoalConfigService.MutateCampaignGoalConfigs][google.ads.googleads.v24.services.CampaignGoalConfigService.MutateCampaignGoalConfigs]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign goal configs are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignGoalConfigOperation]): + Required. The list of operations to perform + on the campaign goal configs. + partial_failure (bool): + Optional. If true, successful operations will + be carried out and invalid operations will + return errors. If false, all operations will be + carried out in one transaction if and only if + they are all valid. Default is false. + validate_only (bool): + Optional. If true, the request is validated + but not executed. Only errors are returned, not + results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CampaignGoalConfigOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignGoalConfigOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class CampaignGoalConfigOperation(proto.Message): + r"""A single mutate operation on the campaign goal config. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which fields are + modified in an update. + create (google.ads.googleads.v24.resources.types.CampaignGoalConfig): + Create a new campaign goal config. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.CampaignGoalConfig): + Update an existing campaign goal config. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove an existing campaign goal config. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: campaign_goal_config.CampaignGoalConfig = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=campaign_goal_config.CampaignGoalConfig, + ) + update: campaign_goal_config.CampaignGoalConfig = proto.Field( + proto.MESSAGE, + number=3, + oneof="operation", + message=campaign_goal_config.CampaignGoalConfig, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateCampaignGoalConfigsResponse(proto.Message): + r"""Response message for a campaign goal config mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in + the partial failure mode. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCampaignGoalConfigResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + results: MutableSequence["MutateCampaignGoalConfigResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCampaignGoalConfigResult", + ) + ) + + +class MutateCampaignGoalConfigResult(proto.Message): + r"""The result for the campaign goal config mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/campaign_group_service.py b/google/ads/googleads/v24/services/types/campaign_group_service.py new file mode 100644 index 000000000..121ea890f --- /dev/null +++ b/google/ads/googleads/v24/services/types/campaign_group_service.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + campaign_group as gagr_campaign_group, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCampaignGroupsRequest", + "CampaignGroupOperation", + "MutateCampaignGroupsResponse", + "MutateCampaignGroupResult", + }, +) + + +class MutateCampaignGroupsRequest(proto.Message): + r"""Request message for + [CampaignGroupService.MutateCampaignGroups][google.ads.googleads.v24.services.CampaignGroupService.MutateCampaignGroups]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign groups are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignGroupOperation]): + Required. The list of operations to perform + on individual campaign groups. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CampaignGroupOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignGroupOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CampaignGroupOperation(proto.Message): + r"""A single operation (create, update, remove) on a campaign + group. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.CampaignGroup): + Create operation: No resource name is + expected for the new campaign group. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.CampaignGroup): + Update operation: The campaign group is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed campaign + group is expected, in this format: + + ``customers/{customer_id}/campaignGroups/{campaign_group_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_campaign_group.CampaignGroup = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_campaign_group.CampaignGroup, + ) + update: gagr_campaign_group.CampaignGroup = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_campaign_group.CampaignGroup, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateCampaignGroupsResponse(proto.Message): + r"""Response message for campaign group mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCampaignGroupResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateCampaignGroupResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCampaignGroupResult", + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + + +class MutateCampaignGroupResult(proto.Message): + r"""The result for the campaign group mutate. + + Attributes: + resource_name (str): + Required. Returned for successful operations. + campaign_group (google.ads.googleads.v24.resources.types.CampaignGroup): + The mutated campaign group with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_group: gagr_campaign_group.CampaignGroup = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_campaign_group.CampaignGroup, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/campaign_label_service.py b/google/ads/googleads/v24/services/types/campaign_label_service.py new file mode 100644 index 000000000..e9aef44d2 --- /dev/null +++ b/google/ads/googleads/v24/services/types/campaign_label_service.py @@ -0,0 +1,159 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import campaign_label +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCampaignLabelsRequest", + "CampaignLabelOperation", + "MutateCampaignLabelsResponse", + "MutateCampaignLabelResult", + }, +) + + +class MutateCampaignLabelsRequest(proto.Message): + r"""Request message for + [CampaignLabelService.MutateCampaignLabels][google.ads.googleads.v24.services.CampaignLabelService.MutateCampaignLabels]. + + Attributes: + customer_id (str): + Required. ID of the customer whose + campaign-label relationships are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignLabelOperation]): + Required. The list of operations to perform + on campaign-label relationships. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CampaignLabelOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignLabelOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class CampaignLabelOperation(proto.Message): + r"""A single operation (create, remove) on a campaign-label + relationship. + + 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: + create (google.ads.googleads.v24.resources.types.CampaignLabel): + Create operation: No resource name is + expected for the new campaign-label + relationship. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the campaign-label + relationship being removed, in this format: + + ``customers/{customer_id}/campaignLabels/{campaign_id}~{label_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: campaign_label.CampaignLabel = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=campaign_label.CampaignLabel, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateCampaignLabelsResponse(proto.Message): + r"""Response message for a campaign labels mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCampaignLabelResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateCampaignLabelResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCampaignLabelResult", + ) + + +class MutateCampaignLabelResult(proto.Message): + r"""The result for a campaign label mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/campaign_lifecycle_goal_service.py b/google/ads/googleads/v24/services/types/campaign_lifecycle_goal_service.py new file mode 100644 index 000000000..2801c68df --- /dev/null +++ b/google/ads/googleads/v24/services/types/campaign_lifecycle_goal_service.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import campaign_lifecycle_goal +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "ConfigureCampaignLifecycleGoalsRequest", + "CampaignLifecycleGoalOperation", + "ConfigureCampaignLifecycleGoalsResponse", + "ConfigureCampaignLifecycleGoalsResult", + }, +) + + +class ConfigureCampaignLifecycleGoalsRequest(proto.Message): + r"""Request message for + [CampaignLifecycleGoalService.ConfigureCampaignLifecycleGoals][google.ads.googleads.v24.services.CampaignLifecycleGoalService.ConfigureCampaignLifecycleGoals]. + + Attributes: + customer_id (str): + Required. The ID of the customer performing + the upload. + operation (google.ads.googleads.v24.services.types.CampaignLifecycleGoalOperation): + Required. The operation to perform campaign + lifecycle goal update. + validate_only (bool): + Optional. If true, the request is validated + but not executed. Only errors are returned, not + results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: "CampaignLifecycleGoalOperation" = proto.Field( + proto.MESSAGE, + number=2, + message="CampaignLifecycleGoalOperation", + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class CampaignLifecycleGoalOperation(proto.Message): + r"""A single operation on a campaign lifecycle goal. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. FieldMask that determines which + resource fields are modified in an update. + create (google.ads.googleads.v24.resources.types.CampaignLifecycleGoal): + Create operation: Create a new campaign + lifecycle goal. The campaign field should be set + for this operation. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.CampaignLifecycleGoal): + Update operation: Update an existing campaign + lifecycle goal. The campaign field should not be + set for this operation. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=2, + message=field_mask_pb2.FieldMask, + ) + create: campaign_lifecycle_goal.CampaignLifecycleGoal = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=campaign_lifecycle_goal.CampaignLifecycleGoal, + ) + update: campaign_lifecycle_goal.CampaignLifecycleGoal = proto.Field( + proto.MESSAGE, + number=3, + oneof="operation", + message=campaign_lifecycle_goal.CampaignLifecycleGoal, + ) + + +class ConfigureCampaignLifecycleGoalsResponse(proto.Message): + r"""Response message for + [CampaignLifecycleGoalService.ConfigureCampaignLifecycleGoals][google.ads.googleads.v24.services.CampaignLifecycleGoalService.ConfigureCampaignLifecycleGoals]. + + Attributes: + result (google.ads.googleads.v24.services.types.ConfigureCampaignLifecycleGoalsResult): + Result for the campaign lifecycle goal + configuration. + """ + + result: "ConfigureCampaignLifecycleGoalsResult" = proto.Field( + proto.MESSAGE, + number=1, + message="ConfigureCampaignLifecycleGoalsResult", + ) + + +class ConfigureCampaignLifecycleGoalsResult(proto.Message): + r"""The result for the campaign lifecycle goal configuration. + + Attributes: + resource_name (str): + Returned for the successful operation. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/campaign_service.py b/google/ads/googleads/v24/services/types/campaign_service.py new file mode 100644 index 000000000..af6e3bca0 --- /dev/null +++ b/google/ads/googleads/v24/services/types/campaign_service.py @@ -0,0 +1,362 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import campaign as gagr_campaign +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCampaignsRequest", + "CampaignOperation", + "MutateCampaignsResponse", + "MutateCampaignResult", + "EnablePMaxBrandGuidelinesRequest", + "EnableOperation", + "BrandCampaignAssets", + "EnablePMaxBrandGuidelinesResponse", + "EnablementResult", + }, +) + + +class MutateCampaignsRequest(proto.Message): + r"""Request message for + [CampaignService.MutateCampaigns][google.ads.googleads.v24.services.CampaignService.MutateCampaigns]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaigns are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignOperation]): + Required. The list of operations to perform + on individual campaigns. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CampaignOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CampaignOperation(proto.Message): + r"""A single operation (create, update, remove) on a campaign. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.Campaign): + Create operation: No resource name is + expected for the new campaign. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.Campaign): + Update operation: The campaign is expected to + have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed campaign + is expected, in this format: + + ``customers/{customer_id}/campaigns/{campaign_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_campaign.Campaign = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_campaign.Campaign, + ) + update: gagr_campaign.Campaign = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_campaign.Campaign, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateCampaignsResponse(proto.Message): + r"""Response message for campaign mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCampaignResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateCampaignResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCampaignResult", + ) + + +class MutateCampaignResult(proto.Message): + r"""The result for the campaign mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + campaign (google.ads.googleads.v24.resources.types.Campaign): + The mutated campaign with only mutable fields after mutate. + The field will only be returned when response_content_type + is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: gagr_campaign.Campaign = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_campaign.Campaign, + ) + + +class EnablePMaxBrandGuidelinesRequest(proto.Message): + r"""Request to enable Brand Guidelines for a Performance Max + campaign. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaigns are being enabled. + operations (MutableSequence[google.ads.googleads.v24.services.types.EnableOperation]): + Required. The list of individual campaign + operations. A maximum of 10 enable operations + can be executed in a request. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["EnableOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="EnableOperation", + ) + + +class EnableOperation(proto.Message): + r"""A single enable operation of a campaign. + + Attributes: + campaign (str): + Required. The resource name of the campaign + to enable. + auto_populate_brand_assets (bool): + Required. The switch to automatically populate + top-performing brand assets. This field is required. If + true, top-performing brand assets will be automatically + populated. If false, the brand_assets field is required. + brand_assets (google.ads.googleads.v24.services.types.BrandCampaignAssets): + Optional. The brand assets linked to the campaign. This + field is required when the value of + auto_populate_brand_assets is false. + final_uri_domain (str): + Optional. The domain of the final uri. + main_color (str): + Optional. Hex code representation of the main brand color, + for example #00ff00. main_color is required when accent + color is specified. + accent_color (str): + Optional. Hex code representation of the accent brand color, + for example #00ff00. accent_color is required when + main_color is specified. + font_family (str): + Optional. The font family is specified as a + string, and must be one of the following: "Open + Sans", "Roboto", "Roboto Slab", "Montserrat", + "Poppins", "Lato", "Oswald", or "Playfair + Display". + """ + + campaign: str = proto.Field( + proto.STRING, + number=1, + ) + auto_populate_brand_assets: bool = proto.Field( + proto.BOOL, + number=2, + ) + brand_assets: "BrandCampaignAssets" = proto.Field( + proto.MESSAGE, + number=3, + message="BrandCampaignAssets", + ) + final_uri_domain: str = proto.Field( + proto.STRING, + number=4, + ) + main_color: str = proto.Field( + proto.STRING, + number=5, + ) + accent_color: str = proto.Field( + proto.STRING, + number=6, + ) + font_family: str = proto.Field( + proto.STRING, + number=7, + ) + + +class BrandCampaignAssets(proto.Message): + r"""Assets linked at the campaign level. A business_name and at least + one logo_asset are required. + + Attributes: + business_name_asset (str): + Required. The resource name of the business + name text asset. + logo_asset (MutableSequence[str]): + Required. The resource name of square logo + assets. + landscape_logo_asset (MutableSequence[str]): + Optional. The resource name of landscape logo + assets. + """ + + business_name_asset: str = proto.Field( + proto.STRING, + number=1, + ) + logo_asset: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + landscape_logo_asset: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + + +class EnablePMaxBrandGuidelinesResponse(proto.Message): + r"""Brand Guidelines campaign enablement response. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.EnablementResult]): + Campaign enablement results per campaign. + """ + + results: MutableSequence["EnablementResult"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="EnablementResult", + ) + + +class EnablementResult(proto.Message): + r"""A single enablement result of a campaign. + + Attributes: + campaign (str): + This indicates the campaign for which + enablement was tried, regardless of the outcome. + enablement_error (google.rpc.status_pb2.Status): + Details of the error when enablement fails. + """ + + campaign: str = proto.Field( + proto.STRING, + number=1, + ) + enablement_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/campaign_shared_set_service.py b/google/ads/googleads/v24/services/types/campaign_shared_set_service.py new file mode 100644 index 000000000..10a5f4182 --- /dev/null +++ b/google/ads/googleads/v24/services/types/campaign_shared_set_service.py @@ -0,0 +1,188 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + campaign_shared_set as gagr_campaign_shared_set, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCampaignSharedSetsRequest", + "CampaignSharedSetOperation", + "MutateCampaignSharedSetsResponse", + "MutateCampaignSharedSetResult", + }, +) + + +class MutateCampaignSharedSetsRequest(proto.Message): + r"""Request message for + [CampaignSharedSetService.MutateCampaignSharedSets][google.ads.googleads.v24.services.CampaignSharedSetService.MutateCampaignSharedSets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign shared sets are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CampaignSharedSetOperation]): + Required. The list of operations to perform + on individual campaign shared sets. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CampaignSharedSetOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignSharedSetOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CampaignSharedSetOperation(proto.Message): + r"""A single operation (create, remove) on a campaign shared set. + + 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: + create (google.ads.googleads.v24.resources.types.CampaignSharedSet): + Create operation: No resource name is + expected for the new campaign shared set. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed campaign + shared set is expected, in this format: + + ``customers/{customer_id}/campaignSharedSets/{campaign_id}~{shared_set_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: gagr_campaign_shared_set.CampaignSharedSet = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_campaign_shared_set.CampaignSharedSet, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateCampaignSharedSetsResponse(proto.Message): + r"""Response message for a campaign shared set mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCampaignSharedSetResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateCampaignSharedSetResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCampaignSharedSetResult", + ) + ) + + +class MutateCampaignSharedSetResult(proto.Message): + r"""The result for the campaign shared set mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + campaign_shared_set (google.ads.googleads.v24.resources.types.CampaignSharedSet): + The mutated campaign shared set with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_shared_set: gagr_campaign_shared_set.CampaignSharedSet = ( + proto.Field( + proto.MESSAGE, + number=2, + message=gagr_campaign_shared_set.CampaignSharedSet, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/content_creator_insights_service.py b/google/ads/googleads/v24/services/types/content_creator_insights_service.py new file mode 100644 index 000000000..c9a527209 --- /dev/null +++ b/google/ads/googleads/v24/services/types/content_creator_insights_service.py @@ -0,0 +1,882 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import additional_application_info +from google.ads.googleads.v24.common.types import audience_insights_attribute +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.enums.types import insights_trend +from google.ads.googleads.v24.enums.types import partnership_opportunity + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "GenerateCreatorInsightsRequest", + "GenerateCreatorInsightsResponse", + "GenerateTrendingInsightsRequest", + "GenerateTrendingInsightsResponse", + "YouTubeCreatorInsights", + "YouTubeMetrics", + "YouTubeChannelInsights", + "SearchAudience", + "SearchTopics", + "TrendInsight", + "TrendInsightMetrics", + "TrendInsightDataPoint", + "LanguageDistribution", + }, +) + + +class GenerateCreatorInsightsRequest(proto.Message): + r"""Request message for + [ContentCreatorInsightsService.GenerateCreatorInsights][google.ads.googleads.v24.services.ContentCreatorInsightsService.GenerateCreatorInsights]. + + 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: + customer_id (str): + Required. The ID of the customer. + customer_insights_group (str): + Required. The name of the customer being + planned for. This is a user-defined value. + insights_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + country_locations (MutableSequence[google.ads.googleads.v24.common.types.LocationInfo]): + Required. The countries to search that apply + to the criteria. + sub_country_locations (MutableSequence[google.ads.googleads.v24.common.types.LocationInfo]): + The sub-country geographic locations to search that apply to + the criteria. Only supported for + [SearchAttributes][google.ads.googleads.v24.services.GenerateCreatorInsightsRequest.SearchAttributes] + criteria. + search_attributes (google.ads.googleads.v24.services.types.GenerateCreatorInsightsRequest.SearchAttributes): + The attributes used to identify top creators. Data fetched + is based on the list of countries or sub-country locations + specified in + [country_locations][google.ads.googleads.v24.services.GenerateCreatorInsightsRequest.country_locations] + or + [sub_country_locations][google.ads.googleads.v24.services.GenerateCreatorInsightsRequest.sub_country_locations]. + + This field is a member of `oneof`_ ``criteria``. + search_brand (google.ads.googleads.v24.services.types.GenerateCreatorInsightsRequest.SearchBrand): + A brand used to search for top creators. Data fetched is + based on the list of countries specified in + [country_locations][google.ads.googleads.v24.services.GenerateCreatorInsightsRequest.country_locations]. + + This field is a member of `oneof`_ ``criteria``. + search_channels (google.ads.googleads.v24.services.types.GenerateCreatorInsightsRequest.YouTubeChannels): + YouTube Channel IDs for Creator Insights. Data fetched for + channels is based on the list of countries specified in + [country_locations][google.ads.googleads.v24.services.GenerateCreatorInsightsRequest.country_locations]. + + This field is a member of `oneof`_ ``criteria``. + """ + + class SearchAttributes(proto.Message): + r"""The audience attributes (such as Age, Gender, Affinity, and + In-Market) and creator attributes (such as creator's content + topics) used to search for top creators. The returned creators + are sorted based on likelihood that your audience watches the + creator, relative to the general population (most likely is + returned first). + + Attributes: + audience_attributes (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttribute]): + Optional. Audience attributes that describe an audience of + viewers. This is used to search for creators whose own + viewers match the input audience. Attributes age_range, + gender, user_interest, entity, category, device, + parental_status, and income_range are supported. Attribute + location is not supported. Attributes user_interest, entity, + and category can only be set in audience_attributes when + audience_combinations is unused. + audience_combinations (MutableSequence[google.ads.googleads.v24.common.types.InsightsAudienceAttributeGroup]): + Optional. A list of audience attribute groups consisting of + one or more Knowledge Graph entities, Product & Service + Categories and user interests that describes an audience. + The groups have a logical AND-of-ORs structure: + + 1. Attributes within each InsightsAudienceAttributeGroup are + combined with OR. + + 2. The groups themselves are combined together with AND. + + For example, an audience (Interest A OR Interest B) AND + (Entity C) is represented using two groups. The first group + contains the two interests and the second group contains the + entity. + + This field cannot be set if any Knowledge Graph entities, + Product & Service Categories, or user interests are + specified in audience_attributes. + creator_attributes (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttribute]): + Optional. Creator attributes that describe a collection of + types of content. This is used to search for creators whose + content matches the input creator attributes. Only Knowledge + Graph Entities tagged with + [CREATOR_ATTRIBUTE][google.ads.googleads.v24.enums.InsightsKnowledgeGraphEntityCapabilitiesEnum.InsightsKnowledgeGraphEntityCapabilities.CREATOR_ATTRIBUTE] + are supported. Use + [AudienceInsightsService.ListAudienceInsightsAttributes][google.ads.googleads.v24.services.AudienceInsightsService.ListAudienceInsightsAttributes] + to get the list of supported entities. Other attributes + including location are not supported. + """ + + audience_attributes: MutableSequence[ + audience_insights_attribute.AudienceInsightsAttribute + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=audience_insights_attribute.AudienceInsightsAttribute, + ) + audience_combinations: MutableSequence[ + audience_insights_attribute.InsightsAudienceAttributeGroup + ] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=audience_insights_attribute.InsightsAudienceAttributeGroup, + ) + creator_attributes: MutableSequence[ + audience_insights_attribute.AudienceInsightsAttribute + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=audience_insights_attribute.AudienceInsightsAttribute, + ) + + class SearchBrand(proto.Message): + r"""The brand used to search for top creators. + + Attributes: + brand_entities (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttribute]): + Optional. One or more Knowledge Graph + Entities that represent the brand for which to + find insights. + include_related_topics (bool): + Optional. When true, we will expand the search to beyond + just the entities specified in + [brand_entities][google.ads.googleads.v24.services.GenerateCreatorInsightsRequest.SearchBrand.brand_entities] + to other related knowledge graph entities similar to the + brand. The default value is ``false``. + """ + + brand_entities: MutableSequence[ + audience_insights_attribute.AudienceInsightsAttribute + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=audience_insights_attribute.AudienceInsightsAttribute, + ) + include_related_topics: bool = proto.Field( + proto.BOOL, + number=2, + ) + + class YouTubeChannels(proto.Message): + r"""A collection of YouTube Channels. + + Attributes: + youtube_channels (MutableSequence[google.ads.googleads.v24.common.types.YouTubeChannelInfo]): + Optional. The YouTube Channel IDs to fetch + creator insights for. + """ + + youtube_channels: MutableSequence[criteria.YouTubeChannelInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=criteria.YouTubeChannelInfo, + ) + ) + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + customer_insights_group: str = proto.Field( + proto.STRING, + number=2, + ) + insights_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=8, + message=additional_application_info.AdditionalApplicationInfo, + ) + country_locations: MutableSequence[criteria.LocationInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=6, + message=criteria.LocationInfo, + ) + ) + sub_country_locations: MutableSequence[criteria.LocationInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=7, + message=criteria.LocationInfo, + ) + ) + search_attributes: SearchAttributes = proto.Field( + proto.MESSAGE, + number=3, + oneof="criteria", + message=SearchAttributes, + ) + search_brand: SearchBrand = proto.Field( + proto.MESSAGE, + number=5, + oneof="criteria", + message=SearchBrand, + ) + search_channels: YouTubeChannels = proto.Field( + proto.MESSAGE, + number=4, + oneof="criteria", + message=YouTubeChannels, + ) + + +class GenerateCreatorInsightsResponse(proto.Message): + r"""Response message for + [ContentCreatorInsightsService.GenerateCreatorInsights][google.ads.googleads.v24.services.ContentCreatorInsightsService.GenerateCreatorInsights]. + + Attributes: + creator_insights (MutableSequence[google.ads.googleads.v24.services.types.YouTubeCreatorInsights]): + A collection of YouTube Creators, each + containing a collection of YouTube Channels + maintained by the YouTube Creator. + """ + + creator_insights: MutableSequence["YouTubeCreatorInsights"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="YouTubeCreatorInsights", + ) + ) + + +class GenerateTrendingInsightsRequest(proto.Message): + r"""Request message for + [ContentCreatorInsightsService.GenerateTrendingInsights][google.ads.googleads.v24.services.ContentCreatorInsightsService.GenerateTrendingInsights]. + + 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: + customer_id (str): + Required. The ID of the customer. + customer_insights_group (str): + Required. The name of the customer being + planned for. This is a user-defined value. + insights_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + country_location (google.ads.googleads.v24.common.types.LocationInfo): + Required. The country to find trends in. + search_audience (google.ads.googleads.v24.services.types.SearchAudience): + An audience to search for trending content + in. + + This field is a member of `oneof`_ ``criteria``. + search_topics (google.ads.googleads.v24.services.types.SearchTopics): + Content topics to return trend information + for. + + This field is a member of `oneof`_ ``criteria``. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + customer_insights_group: str = proto.Field( + proto.STRING, + number=2, + ) + insights_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=6, + message=additional_application_info.AdditionalApplicationInfo, + ) + country_location: criteria.LocationInfo = proto.Field( + proto.MESSAGE, + number=3, + message=criteria.LocationInfo, + ) + search_audience: "SearchAudience" = proto.Field( + proto.MESSAGE, + number=4, + oneof="criteria", + message="SearchAudience", + ) + search_topics: "SearchTopics" = proto.Field( + proto.MESSAGE, + number=5, + oneof="criteria", + message="SearchTopics", + ) + + +class GenerateTrendingInsightsResponse(proto.Message): + r"""Response message for + [ContentCreatorInsightsService.GenerateTrendingInsights][google.ads.googleads.v24.services.ContentCreatorInsightsService.GenerateTrendingInsights]. + + Attributes: + trend_insights (MutableSequence[google.ads.googleads.v24.services.types.TrendInsight]): + The list of trending insights for the given + criteria. + """ + + trend_insights: MutableSequence["TrendInsight"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="TrendInsight", + ) + + +class YouTubeCreatorInsights(proto.Message): + r"""A YouTube creator and the insights for this creator. + + Attributes: + creator_name (str): + The name of the creator. + creator_channels (MutableSequence[google.ads.googleads.v24.services.types.YouTubeChannelInsights]): + The list of YouTube Channels + """ + + creator_name: str = proto.Field( + proto.STRING, + number=1, + ) + creator_channels: MutableSequence["YouTubeChannelInsights"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="YouTubeChannelInsights", + ) + ) + + +class YouTubeMetrics(proto.Message): + r"""YouTube Channel metrics. + + Attributes: + subscriber_count (int): + The number of subscribers. + views_count (int): + The total number of views. + video_count (int): + The total number of videos. + likes_count (int): + The total number of likes across all videos + of this channel. + shares_count (int): + The total number of shares across all videos + of this channel. + comments_count (int): + The total number of comments across all + videos of this channel. + engagement_rate (float): + The lifetime engagement rate of this channel. + The value is computed as the total number of + likes, shares, and comments across all videos + divided by the total number of video views. + average_views_per_video (float): + The average number of views per video in the + last 28 days. + average_likes_per_video (float): + The average number of likes per video in the + last 28 days. + average_shares_per_video (float): + The average number of shares per video in the + last 28 days. + average_comments_per_video (float): + The average number of comments per video in + the last 28 days. + shorts_views_count (int): + The total number of views across all Shorts + videos of this channel. + shorts_video_count (int): + The total number of Shorts videos. + is_active_shorts_creator (bool): + When true, this channel has published a + Shorts video in the last 90 days. + is_active_live_stream_creator (bool): + When true, this channel has published a live + stream in the last 90 days. + partnership_opportunities (MutableSequence[google.ads.googleads.v24.enums.types.PartnershipOpportunityEnum.PartnershipOpportunity]): + Partnership opportunities available for this + creator. + """ + + subscriber_count: int = proto.Field( + proto.INT64, + number=1, + ) + views_count: int = proto.Field( + proto.INT64, + number=2, + ) + video_count: int = proto.Field( + proto.INT64, + number=3, + ) + likes_count: int = proto.Field( + proto.INT64, + number=5, + ) + shares_count: int = proto.Field( + proto.INT64, + number=6, + ) + comments_count: int = proto.Field( + proto.INT64, + number=7, + ) + engagement_rate: float = proto.Field( + proto.DOUBLE, + number=8, + ) + average_views_per_video: float = proto.Field( + proto.DOUBLE, + number=9, + ) + average_likes_per_video: float = proto.Field( + proto.DOUBLE, + number=10, + ) + average_shares_per_video: float = proto.Field( + proto.DOUBLE, + number=11, + ) + average_comments_per_video: float = proto.Field( + proto.DOUBLE, + number=12, + ) + shorts_views_count: int = proto.Field( + proto.INT64, + number=13, + ) + shorts_video_count: int = proto.Field( + proto.INT64, + number=14, + ) + is_active_shorts_creator: bool = proto.Field( + proto.BOOL, + number=4, + ) + is_active_live_stream_creator: bool = proto.Field( + proto.BOOL, + number=16, + ) + partnership_opportunities: MutableSequence[ + partnership_opportunity.PartnershipOpportunityEnum.PartnershipOpportunity + ] = proto.RepeatedField( + proto.ENUM, + number=17, + enum=partnership_opportunity.PartnershipOpportunityEnum.PartnershipOpportunity, + ) + + +class YouTubeChannelInsights(proto.Message): + r"""YouTube Channel insights, and its metadata (such as channel + name and channel ID), returned for a creator insights response. + + Attributes: + display_name (str): + The name of the YouTube Channel. + youtube_channel (google.ads.googleads.v24.common.types.YouTubeChannelInfo): + The YouTube Channel ID. + channel_url (str): + URL for the channel in the form of + https://www.youtube.com/channel/{channel_id}. + channel_description (str): + Description of the channel. + handle (str): + The unique, short, and user-visible + identifier for the channel starting with an "@" + symbol (such as "@youtubecreators"). See + https://support.google.com/youtube/answer/11585688 + for more information. + thumbnail_url (str): + URL for a 240px by 240px thumbnail image of + the channel. + publish_date (str): + The date that the channel was created. + Formatted as "yyyy-mm-dd". + country_location (google.ads.googleads.v24.common.types.LocationInfo): + The country with which the channel is + associated. + channel_metrics (google.ads.googleads.v24.services.types.YouTubeMetrics): + The metrics for a YouTube Channel. + channel_audience_attributes (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadata]): + The types of audiences and demographics + linked to the channel's main audience. Audiences + and demographics have a breakdown of subscriber + share across dimensions of the same value, such + as Age Range, Gender, and User Interest. + channel_attributes (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadata]): + The attributes associated with the content + made by a channel. + top_videos (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadata]): + The top 10 videos for the channel. + language_distributions (MutableSequence[google.ads.googleads.v24.services.types.LanguageDistribution]): + The languages associated with the content + made by a channel. + channel_type (str): + Metadata string associated with the type of + channel. + relevance_score (float): + The relevance score of the channel to the topic being + searched for weighted by views. The value is between 0 and + 1, with 1 being the most relevant. Only populated for trends + using search_topics. + """ + + display_name: str = proto.Field( + proto.STRING, + number=1, + ) + youtube_channel: criteria.YouTubeChannelInfo = proto.Field( + proto.MESSAGE, + number=2, + message=criteria.YouTubeChannelInfo, + ) + channel_url: str = proto.Field( + proto.STRING, + number=9, + ) + channel_description: str = proto.Field( + proto.STRING, + number=10, + ) + handle: str = proto.Field( + proto.STRING, + number=11, + ) + thumbnail_url: str = proto.Field( + proto.STRING, + number=12, + ) + publish_date: str = proto.Field( + proto.STRING, + number=13, + ) + country_location: criteria.LocationInfo = proto.Field( + proto.MESSAGE, + number=14, + message=criteria.LocationInfo, + ) + channel_metrics: "YouTubeMetrics" = proto.Field( + proto.MESSAGE, + number=3, + message="YouTubeMetrics", + ) + channel_audience_attributes: MutableSequence[ + audience_insights_attribute.AudienceInsightsAttributeMetadata + ] = proto.RepeatedField( + proto.MESSAGE, + number=7, + message=audience_insights_attribute.AudienceInsightsAttributeMetadata, + ) + channel_attributes: MutableSequence[ + audience_insights_attribute.AudienceInsightsAttributeMetadata + ] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message=audience_insights_attribute.AudienceInsightsAttributeMetadata, + ) + top_videos: MutableSequence[ + audience_insights_attribute.AudienceInsightsAttributeMetadata + ] = proto.RepeatedField( + proto.MESSAGE, + number=8, + message=audience_insights_attribute.AudienceInsightsAttributeMetadata, + ) + language_distributions: MutableSequence["LanguageDistribution"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=15, + message="LanguageDistribution", + ) + ) + channel_type: str = proto.Field( + proto.STRING, + number=6, + ) + relevance_score: float = proto.Field( + proto.DOUBLE, + number=16, + ) + + +class SearchAudience(proto.Message): + r"""A collection of audience attributes that describe an audience + of viewers. This is used to search for topics trending for the + defined audience. + + Attributes: + audience_attributes (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttribute]): + Required. Audience attributes that describe an audience of + viewers. This is used to search for topics trending for the + defined audience. Attributes age_range, gender, + user_interest, entity, category, parental_status, and + income_range are supported. Attributes user_interest, + entity, and category can only be set in audience_attributes + when audience_combinations is unused. + audience_combinations (MutableSequence[google.ads.googleads.v24.common.types.InsightsAudienceAttributeGroup]): + Optional. A list of audience attribute groups consisting of + one or more Knowledge Graph entities, Product & Service + Categories and user interests that describes an audience. + The groups have a logical AND-of-ORs structure: + + 1. Attributes within each InsightsAudienceAttributeGroup are + combined with OR. + + 2. The groups themselves are combined together with AND. + + For example, an audience (Interest A OR Interest B) AND + (Entity C) is represented using two groups. The first group + contains the two interests and the second group contains the + entity. + + This field cannot be set if any Knowledge Graph entities, + Product & Service Categories, or user interests are + specified in audience_attributes. + """ + + audience_attributes: MutableSequence[ + audience_insights_attribute.AudienceInsightsAttribute + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=audience_insights_attribute.AudienceInsightsAttribute, + ) + audience_combinations: MutableSequence[ + audience_insights_attribute.InsightsAudienceAttributeGroup + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=audience_insights_attribute.InsightsAudienceAttributeGroup, + ) + + +class SearchTopics(proto.Message): + r"""A collection of content topics to return trend information + for. + + Attributes: + entities (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsEntity]): + Required. A list of knowledge graph entities to retrieve + trend information for. Supported entities are tagged with + [CONTENT_TRENDING_INSIGHTS][google.ads.googleads.v24.enums.InsightsKnowledgeGraphEntityCapabilitiesEnum.InsightsKnowledgeGraphEntityCapabilities.CONTENT_TRENDING_INSIGHTS]. + Use + [AudienceInsightsService.ListAudienceInsightsAttributes][google.ads.googleads.v24.services.AudienceInsightsService.ListAudienceInsightsAttributes] + to get the list of supported entities. + """ + + entities: MutableSequence[ + audience_insights_attribute.AudienceInsightsEntity + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=audience_insights_attribute.AudienceInsightsEntity, + ) + + +class TrendInsight(proto.Message): + r"""A trend insight for a given attribute. + + Attributes: + trend_attribute (google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadata): + The attribute this trend is for. + trend_metrics (google.ads.googleads.v24.services.types.TrendInsightMetrics): + Metrics associated with this trend. These + metrics are for the latest available month and + the comparison period is 3 months. + trend (google.ads.googleads.v24.enums.types.InsightsTrendEnum.InsightsTrend): + Indicate if a trend is sustained or emerging. Use + trend_metrics.trend_change_percent to determine the + direction of the trend. + trend_data_points (MutableSequence[google.ads.googleads.v24.services.types.TrendInsightDataPoint]): + 3 years of historical data for the trend, including the most + recent month the TrendInsight represents. Each data point + represents 1 month of data and the comparison period is 1 + month. The data points are ordered from most recent month to + least recent month. Only populated for trends using + search_topics. + related_videos (MutableSequence[google.ads.googleads.v24.common.types.AudienceInsightsAttributeMetadata]): + Related videos for this topic. Only populated for trends + using search_topics. + related_creators (MutableSequence[google.ads.googleads.v24.services.types.YouTubeCreatorInsights]): + Related creators for this topic. Only populated for trends + using search_topics. + """ + + trend_attribute: ( + audience_insights_attribute.AudienceInsightsAttributeMetadata + ) = proto.Field( + proto.MESSAGE, + number=1, + message=audience_insights_attribute.AudienceInsightsAttributeMetadata, + ) + trend_metrics: "TrendInsightMetrics" = proto.Field( + proto.MESSAGE, + number=2, + message="TrendInsightMetrics", + ) + trend: insights_trend.InsightsTrendEnum.InsightsTrend = proto.Field( + proto.ENUM, + number=3, + enum=insights_trend.InsightsTrendEnum.InsightsTrend, + ) + trend_data_points: MutableSequence["TrendInsightDataPoint"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=6, + message="TrendInsightDataPoint", + ) + ) + related_videos: MutableSequence[ + audience_insights_attribute.AudienceInsightsAttributeMetadata + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=audience_insights_attribute.AudienceInsightsAttributeMetadata, + ) + related_creators: MutableSequence["YouTubeCreatorInsights"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=5, + message="YouTubeCreatorInsights", + ) + ) + + +class TrendInsightMetrics(proto.Message): + r"""Metrics associated with a trend insight. + + Attributes: + views_count (int): + The number of views for this trend. This is + only populated for the latest month of data for + SearchTopics requests. + views_indexed_value (int): + Views value normalized to be in the range + 0-100. This is only populated for SearchTopics + requests. + audience_share (float): + The fraction (from 0 to 1 inclusive) of the + requested audience that has has searched or + viewed this trend. This is only populated for + SearchAudience requests. + trend_change_percent (float): + The percentage of the change in the trend's + value over the comparison period, where 1.0 + represents 100%. If this is 0, it means that the + trend is emerging (new) or sustained (existing + but unchanged). + """ + + views_count: int = proto.Field( + proto.INT64, + number=1, + ) + views_indexed_value: int = proto.Field( + proto.INT64, + number=4, + ) + audience_share: float = proto.Field( + proto.DOUBLE, + number=2, + ) + trend_change_percent: float = proto.Field( + proto.DOUBLE, + number=3, + ) + + +class TrendInsightDataPoint(proto.Message): + r"""Trend data for a specific month. + + Attributes: + month (str): + The month that the trend data point + represents in the string format "YYYY-MM". + trend_metrics (google.ads.googleads.v24.services.types.TrendInsightMetrics): + Metrics associated with this trend and month. + The comparison period for these metrics is 1 + month. + """ + + month: str = proto.Field( + proto.STRING, + number=1, + ) + trend_metrics: "TrendInsightMetrics" = proto.Field( + proto.MESSAGE, + number=2, + message="TrendInsightMetrics", + ) + + +class LanguageDistribution(proto.Message): + r"""Languages that pertain to a YouTube channel based on the + channel content. Only languages above a certain proportion + threshold are included. + + Attributes: + language_code (str): + `Language + code `__ + of the language for the YouTube channel. + proportion (float): + The proportion (between 0 and 1) of the + channel's videos in the language. + """ + + language_code: str = proto.Field( + proto.STRING, + number=1, + ) + proportion: float = proto.Field( + proto.DOUBLE, + number=2, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/conversion_action_service.py b/google/ads/googleads/v24/services/types/conversion_action_service.py new file mode 100644 index 000000000..00b18e5fe --- /dev/null +++ b/google/ads/googleads/v24/services/types/conversion_action_service.py @@ -0,0 +1,208 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + conversion_action as gagr_conversion_action, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateConversionActionsRequest", + "ConversionActionOperation", + "MutateConversionActionsResponse", + "MutateConversionActionResult", + }, +) + + +class MutateConversionActionsRequest(proto.Message): + r"""Request message for + [ConversionActionService.MutateConversionActions][google.ads.googleads.v24.services.ConversionActionService.MutateConversionActions]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + conversion actions are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.ConversionActionOperation]): + Required. The list of operations to perform + on individual conversion actions. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["ConversionActionOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ConversionActionOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class ConversionActionOperation(proto.Message): + r"""A single operation (create, update, remove) on a conversion + action. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.ConversionAction): + Create operation: No resource name is + expected for the new conversion action. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.ConversionAction): + Update operation: The conversion action is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed conversion + action is expected, in this format: + + ``customers/{customer_id}/conversionActions/{conversion_action_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_conversion_action.ConversionAction = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_conversion_action.ConversionAction, + ) + update: gagr_conversion_action.ConversionAction = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_conversion_action.ConversionAction, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateConversionActionsResponse(proto.Message): + r"""Response message for + [ConversionActionService.MutateConversionActions][google.ads.googleads.v24.services.ConversionActionService.MutateConversionActions]. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateConversionActionResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateConversionActionResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateConversionActionResult", + ) + ) + + +class MutateConversionActionResult(proto.Message): + r"""The result for the conversion action mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + conversion_action (google.ads.googleads.v24.resources.types.ConversionAction): + The mutated conversion action with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + conversion_action: gagr_conversion_action.ConversionAction = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_conversion_action.ConversionAction, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/conversion_adjustment_upload_service.py b/google/ads/googleads/v24/services/types/conversion_adjustment_upload_service.py new file mode 100644 index 000000000..507b5b82d --- /dev/null +++ b/google/ads/googleads/v24/services/types/conversion_adjustment_upload_service.py @@ -0,0 +1,392 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import offline_user_data +from google.ads.googleads.v24.enums.types import conversion_adjustment_type +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "UploadConversionAdjustmentsRequest", + "UploadConversionAdjustmentsResponse", + "ConversionAdjustment", + "RestatementValue", + "GclidDateTimePair", + "ConversionAdjustmentResult", + }, +) + + +class UploadConversionAdjustmentsRequest(proto.Message): + r"""Request message for + [ConversionAdjustmentUploadService.UploadConversionAdjustments][google.ads.googleads.v24.services.ConversionAdjustmentUploadService.UploadConversionAdjustments]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer_id (str): + Required. The ID of the customer performing + the upload. + conversion_adjustments (MutableSequence[google.ads.googleads.v24.services.types.ConversionAdjustment]): + Required. The conversion adjustments that are + being uploaded. + partial_failure (bool): + Required. If true, successful operations will + be carried out and invalid operations will + return errors. If false, all operations will be + carried out in one transaction if and only if + they are all valid. This should always be set to + true. + See + https://developers.google.com/google-ads/api/docs/best-practices/partial-failures + for more information about partial failure. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + job_id (int): + Optional. Optional input to set job ID. Must be a + non-negative number that is less than 2^31 if provided. If + this field is not provided, the API will generate a job ID + in the range [2^31, (2^63)-1]. The API will return the value + for this request in the ``job_id`` field of the + ``UploadConversionAdjustmentsResponse``. + + This field is a member of `oneof`_ ``_job_id``. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + conversion_adjustments: MutableSequence["ConversionAdjustment"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ConversionAdjustment", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + job_id: int = proto.Field( + proto.INT32, + number=5, + optional=True, + ) + + +class UploadConversionAdjustmentsResponse(proto.Message): + r"""Response message for + [ConversionAdjustmentUploadService.UploadConversionAdjustments][google.ads.googleads.v24.services.ConversionAdjustmentUploadService.UploadConversionAdjustments]. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to conversion adjustment + failures in the partial failure mode. Returned + when all errors occur inside the adjustments. If + any errors occur outside the adjustments (for + example, auth errors), we return an RPC level + error. See + https://developers.google.com/google-ads/api/docs/best-practices/partial-failures + for more information about partial failure. + results (MutableSequence[google.ads.googleads.v24.services.types.ConversionAdjustmentResult]): + Returned for successfully processed conversion adjustments. + Proto will be empty for rows that received an error. Results + are not returned when validate_only is true. + job_id (int): + Job ID for the upload batch. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + results: MutableSequence["ConversionAdjustmentResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ConversionAdjustmentResult", + ) + ) + job_id: int = proto.Field( + proto.INT64, + number=3, + ) + + +class ConversionAdjustment(proto.Message): + r"""A conversion adjustment. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + gclid_date_time_pair (google.ads.googleads.v24.services.types.GclidDateTimePair): + For adjustments, uniquely identifies a conversion that was + reported without an order ID specified. If the + adjustment_type is ENHANCEMENT, this value is optional but + may be set in addition to the order_id. + order_id (str): + The order ID of the conversion to be + adjusted. If the conversion was reported with an + order ID specified, that order ID must be used + as the identifier here. The order ID is required + for enhancements. + + This field is a member of `oneof`_ ``_order_id``. + conversion_action (str): + Resource name of the conversion action + associated with this conversion adjustment. + Note: Although this resource name consists of a + customer id and a conversion action id, + validation will ignore the customer id and use + the conversion action id as the sole identifier + of the conversion action. + + This field is a member of `oneof`_ ``_conversion_action``. + adjustment_date_time (str): + The date time at which the adjustment occurred. Must be + after the conversion_date_time. The timezone must be + specified. The format is "yyyy-mm-dd hh:mm:ss+\|-hh:mm", for + example, "2019-01-01 12:32:45-08:00". + + This field is a member of `oneof`_ ``_adjustment_date_time``. + adjustment_type (google.ads.googleads.v24.enums.types.ConversionAdjustmentTypeEnum.ConversionAdjustmentType): + The adjustment type. + restatement_value (google.ads.googleads.v24.services.types.RestatementValue): + Information needed to restate the + conversion's value. Required for restatements. + Should not be supplied for retractions. An error + will be returned if provided for a retraction. + NOTE: If you want to upload a second restatement + with a different adjusted value, it must have a + new, more recent, adjustment occurrence time. + Otherwise, it will be treated as a duplicate of + the previous restatement and ignored. + user_identifiers (MutableSequence[google.ads.googleads.v24.common.types.UserIdentifier]): + The user identifiers to enhance the original + conversion. ConversionAdjustmentUploadService + only accepts user identifiers in enhancements. + The maximum number of user identifiers for each + enhancement is 5. + user_agent (str): + The user agent to enhance the original conversion. This can + be found in your user's HTTP request header when they + convert on your web page. Example, "Mozilla/5.0 (iPhone; CPU + iPhone OS 12_2 like Mac OS X)". User agent can only be + specified in enhancements with user identifiers. This should + match the user agent of the request that sent the original + conversion so the conversion and its enhancement are either + both attributed as same-device or both attributed as + cross-device. + + This field is a member of `oneof`_ ``_user_agent``. + """ + + gclid_date_time_pair: "GclidDateTimePair" = proto.Field( + proto.MESSAGE, + number=12, + message="GclidDateTimePair", + ) + order_id: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + conversion_action: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + adjustment_date_time: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + adjustment_type: ( + conversion_adjustment_type.ConversionAdjustmentTypeEnum.ConversionAdjustmentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=conversion_adjustment_type.ConversionAdjustmentTypeEnum.ConversionAdjustmentType, + ) + restatement_value: "RestatementValue" = proto.Field( + proto.MESSAGE, + number=6, + message="RestatementValue", + ) + user_identifiers: MutableSequence[offline_user_data.UserIdentifier] = ( + proto.RepeatedField( + proto.MESSAGE, + number=10, + message=offline_user_data.UserIdentifier, + ) + ) + user_agent: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + + +class RestatementValue(proto.Message): + r"""Contains information needed to restate a conversion's value. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + adjusted_value (float): + The restated conversion value. This is the + value of the conversion after restatement. For + example, to change the value of a conversion + from 100 to 70, an adjusted value of 70 should + be reported. NOTE: If you want to upload a + second restatement with a different adjusted + value, it must have a new, more recent, + adjustment occurrence time. Otherwise, it will + be treated as a duplicate of the previous + restatement and ignored. + + This field is a member of `oneof`_ ``_adjusted_value``. + currency_code (str): + The currency of the restated value. If not + provided, then the default currency from the + conversion action is used, and if that is not + set then the account currency is used. This is + the ISO 4217 3-character currency code for + example, USD or EUR. + + This field is a member of `oneof`_ ``_currency_code``. + """ + + adjusted_value: float = proto.Field( + proto.DOUBLE, + number=3, + optional=True, + ) + currency_code: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + + +class GclidDateTimePair(proto.Message): + r"""Uniquely identifies a conversion that was reported without an + order ID specified. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + gclid (str): + Google click ID (gclid) associated with the + original conversion for this adjustment. + + This field is a member of `oneof`_ ``_gclid``. + conversion_date_time (str): + The date time at which the original conversion for this + adjustment occurred. The timezone must be specified. The + format is "yyyy-mm-dd hh:mm:ss+\|-hh:mm", for example, + "2019-01-01 12:32:45-08:00". + + This field is a member of `oneof`_ ``_conversion_date_time``. + """ + + gclid: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + conversion_date_time: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + + +class ConversionAdjustmentResult(proto.Message): + r"""Information identifying a successfully processed + ConversionAdjustment. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + gclid_date_time_pair (google.ads.googleads.v24.services.types.GclidDateTimePair): + The gclid and conversion date time of the + conversion. + order_id (str): + The order ID of the conversion to be + adjusted. + conversion_action (str): + Resource name of the conversion action + associated with this conversion adjustment. + + This field is a member of `oneof`_ ``_conversion_action``. + adjustment_date_time (str): + The date time at which the adjustment occurred. The format + is "yyyy-mm-dd hh:mm:ss+\|-hh:mm", for example, "2019-01-01 + 12:32:45-08:00". + + This field is a member of `oneof`_ ``_adjustment_date_time``. + adjustment_type (google.ads.googleads.v24.enums.types.ConversionAdjustmentTypeEnum.ConversionAdjustmentType): + The adjustment type. + """ + + gclid_date_time_pair: "GclidDateTimePair" = proto.Field( + proto.MESSAGE, + number=9, + message="GclidDateTimePair", + ) + order_id: str = proto.Field( + proto.STRING, + number=10, + ) + conversion_action: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + adjustment_date_time: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + adjustment_type: ( + conversion_adjustment_type.ConversionAdjustmentTypeEnum.ConversionAdjustmentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=conversion_adjustment_type.ConversionAdjustmentTypeEnum.ConversionAdjustmentType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/conversion_custom_variable_service.py b/google/ads/googleads/v24/services/types/conversion_custom_variable_service.py new file mode 100644 index 000000000..834b39baa --- /dev/null +++ b/google/ads/googleads/v24/services/types/conversion_custom_variable_service.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + conversion_custom_variable as gagr_conversion_custom_variable, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateConversionCustomVariablesRequest", + "ConversionCustomVariableOperation", + "MutateConversionCustomVariablesResponse", + "MutateConversionCustomVariableResult", + }, +) + + +class MutateConversionCustomVariablesRequest(proto.Message): + r"""Request message for + [ConversionCustomVariableService.MutateConversionCustomVariables][google.ads.googleads.v24.services.ConversionCustomVariableService.MutateConversionCustomVariables]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + conversion custom variables are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.ConversionCustomVariableOperation]): + Required. The list of operations to perform + on individual conversion custom variables. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["ConversionCustomVariableOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ConversionCustomVariableOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class ConversionCustomVariableOperation(proto.Message): + r"""A single operation (create, update) on a conversion custom + variable. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.ConversionCustomVariable): + Create operation: No resource name is + expected for the new conversion custom variable. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.ConversionCustomVariable): + Update operation: The conversion custom + variable is expected to have a valid resource + name. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=3, + message=field_mask_pb2.FieldMask, + ) + create: gagr_conversion_custom_variable.ConversionCustomVariable = ( + proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_conversion_custom_variable.ConversionCustomVariable, + ) + ) + update: gagr_conversion_custom_variable.ConversionCustomVariable = ( + proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_conversion_custom_variable.ConversionCustomVariable, + ) + ) + + +class MutateConversionCustomVariablesResponse(proto.Message): + r"""Response message for + [ConversionCustomVariableService.MutateConversionCustomVariables][google.ads.googleads.v24.services.ConversionCustomVariableService.MutateConversionCustomVariables]. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateConversionCustomVariableResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + results: MutableSequence["MutateConversionCustomVariableResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateConversionCustomVariableResult", + ) + ) + + +class MutateConversionCustomVariableResult(proto.Message): + r"""The result for the conversion custom variable mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + conversion_custom_variable (google.ads.googleads.v24.resources.types.ConversionCustomVariable): + The mutated conversion custom variable with only mutable + fields after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + conversion_custom_variable: ( + gagr_conversion_custom_variable.ConversionCustomVariable + ) = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_conversion_custom_variable.ConversionCustomVariable, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/conversion_goal_campaign_config_service.py b/google/ads/googleads/v24/services/types/conversion_goal_campaign_config_service.py new file mode 100644 index 000000000..5dd29aa2f --- /dev/null +++ b/google/ads/googleads/v24/services/types/conversion_goal_campaign_config_service.py @@ -0,0 +1,164 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + conversion_goal_campaign_config as gagr_conversion_goal_campaign_config, +) +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateConversionGoalCampaignConfigsRequest", + "ConversionGoalCampaignConfigOperation", + "MutateConversionGoalCampaignConfigsResponse", + "MutateConversionGoalCampaignConfigResult", + }, +) + + +class MutateConversionGoalCampaignConfigsRequest(proto.Message): + r"""Request message for + [ConversionGoalCampaignConfigService.MutateConversionGoalCampaignConfigs][google.ads.googleads.v24.services.ConversionGoalCampaignConfigService.MutateConversionGoalCampaignConfigs]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose custom + conversion goals are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.ConversionGoalCampaignConfigOperation]): + Required. The list of operations to perform + on individual conversion goal campaign config. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["ConversionGoalCampaignConfigOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ConversionGoalCampaignConfigOperation", + ) + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=4, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class ConversionGoalCampaignConfigOperation(proto.Message): + r"""A single operation (update) on a conversion goal campaign + config. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + update (google.ads.googleads.v24.resources.types.ConversionGoalCampaignConfig): + Update operation: The conversion goal + campaign config is expected to have a valid + resource name. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=2, + message=field_mask_pb2.FieldMask, + ) + update: ( + gagr_conversion_goal_campaign_config.ConversionGoalCampaignConfig + ) = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_conversion_goal_campaign_config.ConversionGoalCampaignConfig, + ) + + +class MutateConversionGoalCampaignConfigsResponse(proto.Message): + r"""Response message for a conversion goal campaign config + mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateConversionGoalCampaignConfigResult]): + All results for the mutate. + """ + + results: MutableSequence["MutateConversionGoalCampaignConfigResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateConversionGoalCampaignConfigResult", + ) + ) + + +class MutateConversionGoalCampaignConfigResult(proto.Message): + r"""The result for the conversion goal campaign config mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + conversion_goal_campaign_config (google.ads.googleads.v24.resources.types.ConversionGoalCampaignConfig): + The mutated ConversionGoalCampaignConfig with only mutable + fields after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + conversion_goal_campaign_config: ( + gagr_conversion_goal_campaign_config.ConversionGoalCampaignConfig + ) = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_conversion_goal_campaign_config.ConversionGoalCampaignConfig, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/conversion_upload_service.py b/google/ads/googleads/v24/services/types/conversion_upload_service.py new file mode 100644 index 000000000..e19347b16 --- /dev/null +++ b/google/ads/googleads/v24/services/types/conversion_upload_service.py @@ -0,0 +1,837 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import consent as gagc_consent +from google.ads.googleads.v24.common.types import offline_user_data +from google.ads.googleads.v24.enums.types import conversion_customer_type +from google.ads.googleads.v24.enums.types import conversion_environment_enum +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "UploadClickConversionsRequest", + "UploadClickConversionsResponse", + "UploadCallConversionsRequest", + "UploadCallConversionsResponse", + "ClickConversion", + "CallConversion", + "ExternalAttributionData", + "ClickConversionResult", + "CallConversionResult", + "CustomVariable", + "CartData", + "SessionAttributeKeyValuePair", + "SessionAttributesKeyValuePairs", + }, +) + + +class UploadClickConversionsRequest(proto.Message): + r"""Request message for + [ConversionUploadService.UploadClickConversions][google.ads.googleads.v24.services.ConversionUploadService.UploadClickConversions]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer_id (str): + Required. The ID of the customer performing + the upload. + conversions (MutableSequence[google.ads.googleads.v24.services.types.ClickConversion]): + Required. The conversions that are being + uploaded. + partial_failure (bool): + Required. If ``true``, successful operations will be carried + out and invalid operations will return errors. If ``false``, + all operations will be carried out in one transaction if and + only if they are all valid. This should always be set to + ``true``. + + See `Best practices for partial + failures `__. + validate_only (bool): + If ``true``, the request is validated but not executed. Only + errors are returned, not results. + job_id (int): + Optional. Optional input to set job ID. Must be a + non-negative number that is less than 2^31 if provided. If + this field is not provided, the API will generate a job ID + in the range [2^31, (2^63)-1]. The API will return the value + for this request in the ``job_id`` field of the + ``UploadClickConversionsResponse``. + + This field is a member of `oneof`_ ``_job_id``. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + conversions: MutableSequence["ClickConversion"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ClickConversion", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + job_id: int = proto.Field( + proto.INT32, + number=6, + optional=True, + ) + + +class UploadClickConversionsResponse(proto.Message): + r"""Response message for + [ConversionUploadService.UploadClickConversions][google.ads.googleads.v24.services.ConversionUploadService.UploadClickConversions]. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to conversion failures in the partial + failure mode. Returned when all errors occur inside the + conversions. If any errors occur outside the conversions + (for example, auth errors), we return an RPC level error. + + See `Best practices for partial + failures `__. + results (MutableSequence[google.ads.googleads.v24.services.types.ClickConversionResult]): + Returned for successfully processed conversions. Proto will + be empty for rows that received an error. Results are not + returned when ``validate_only`` is ``true``. + job_id (int): + Job ID for the upload batch. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + results: MutableSequence["ClickConversionResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ClickConversionResult", + ) + job_id: int = proto.Field( + proto.INT64, + number=3, + ) + + +class UploadCallConversionsRequest(proto.Message): + r"""Request message for + [ConversionUploadService.UploadCallConversions][google.ads.googleads.v24.services.ConversionUploadService.UploadCallConversions]. + + Attributes: + customer_id (str): + Required. The ID of the customer performing + the upload. + conversions (MutableSequence[google.ads.googleads.v24.services.types.CallConversion]): + Required. The conversions that are being + uploaded. + partial_failure (bool): + Required. If ``true``, successful operations will be carried + out and invalid operations will return errors. If ``false``, + all operations will be carried out in one transaction if and + only if they are all valid. + + This should always be set to ``true``. + + See `Best practices for partial + failures `__. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + conversions: MutableSequence["CallConversion"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CallConversion", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class UploadCallConversionsResponse(proto.Message): + r"""Response message for + [ConversionUploadService.UploadCallConversions][google.ads.googleads.v24.services.ConversionUploadService.UploadCallConversions]. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to conversion failures in the partial + failure mode. Returned when all errors occur inside the + conversions. If any errors occur outside the conversions + (for example, auth errors), we return an RPC level error. + + See `Best practices for partial + failures `__. + results (MutableSequence[google.ads.googleads.v24.services.types.CallConversionResult]): + Returned for successfully processed conversions. Proto will + be empty for rows that received an error. Results are not + returned when ``validate_only`` is ``true``. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + results: MutableSequence["CallConversionResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CallConversionResult", + ) + + +class ClickConversion(proto.Message): + r"""A click conversion. + + 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: + gclid (str): + The Google click ID (gclid) associated with + this conversion. + + This field is a member of `oneof`_ ``_gclid``. + gbraid (str): + The URL parameter for clicks associated with + app conversions. + wbraid (str): + The URL parameter for clicks associated with + web conversions. + conversion_action (str): + Resource name of the conversion action + associated with this conversion. + Note: Although this resource name consists of a + customer id and a conversion action id, + validation will ignore the customer id and use + the conversion action id as the sole identifier + of the conversion action. + + This field is a member of `oneof`_ ``_conversion_action``. + conversion_date_time (str): + The date time at which the conversion occurred. Must be + after the click time. The timezone must be specified. The + format is "yyyy-mm-dd hh:mm:ss+\|-hh:mm", for example, + "2019-01-01 12:32:45-08:00". + + This field is a member of `oneof`_ ``_conversion_date_time``. + conversion_value (float): + The value of the conversion for the + advertiser. + + This field is a member of `oneof`_ ``_conversion_value``. + currency_code (str): + Currency associated with the conversion + value. This is the ISO 4217 3-character currency + code. For example: USD, EUR. + + This field is a member of `oneof`_ ``_currency_code``. + order_id (str): + The order ID associated with the conversion. + An order id can only be used for one conversion + per conversion action. + + This field is a member of `oneof`_ ``_order_id``. + external_attribution_data (google.ads.googleads.v24.services.types.ExternalAttributionData): + Additional data about externally attributed + conversions. This field is required for + conversions with an externally attributed + conversion action, but should not be set + otherwise. + custom_variables (MutableSequence[google.ads.googleads.v24.services.types.CustomVariable]): + The custom variables associated with this + conversion. + cart_data (google.ads.googleads.v24.services.types.CartData): + The cart data associated with this + conversion. + user_identifiers (MutableSequence[google.ads.googleads.v24.common.types.UserIdentifier]): + The user identifiers associated with this conversion. Only + hashed_email and hashed_phone_number are supported for + conversion uploads. The maximum number of user identifiers + for each conversion is 5. + conversion_environment (google.ads.googleads.v24.enums.types.ConversionEnvironmentEnum.ConversionEnvironment): + The environment this conversion was recorded + on, for example, App or Web. + consent (google.ads.googleads.v24.common.types.Consent): + The consent setting for the event. + customer_type (google.ads.googleads.v24.enums.types.ConversionCustomerTypeEnum.ConversionCustomerType): + Type of the customer associated with the + conversion (new or returning). + user_ip_address (str): + The IP address of the customer when they arrived on the + landing page after an ad click but before a conversion + event. This is the IP address of the customer's device, not + the advertiser's server. Google Ads does not support IP + address matching for end users in the European Economic Area + (EEA), United Kingdom (UK), or Switzerland (CH). Add logic + to conditionally exclude sharing IP addresses from users + from these regions and ensure that you provide users with + clear and comprehensive information about the data you + collect on your sites, apps, and other properties and get + consent where required by law or any applicable Google + policies. See `About offline conversion + imports `__ + page for more details. + + This field is only available to allowlisted users. To + include this field in conversion imports, upgrade to the + Data Manager API. + + This field is a member of `oneof`_ ``_user_ip_address``. + session_attributes_encoded (bytes): + The session attributes for the event, represented as a + base64-encoded JSON string. The content should be generated + by Google-provided library. To set session attributes + individually, use session_attributes_key_value_pairs + instead. This field is only available to allowlisted users. + To include this field in conversion imports, upgrade to the + Data Manager API. + + This field is a member of `oneof`_ ``session_attributes``. + session_attributes_key_value_pairs (google.ads.googleads.v24.services.types.SessionAttributesKeyValuePairs): + The session attributes for the event, + represented as key-value pairs. This field is + only available to allowlisted users. To include + this field in conversion imports, upgrade to the + Data Manager API. + + This field is a member of `oneof`_ ``session_attributes``. + """ + + gclid: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + gbraid: str = proto.Field( + proto.STRING, + number=18, + ) + wbraid: str = proto.Field( + proto.STRING, + number=19, + ) + conversion_action: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + conversion_date_time: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + conversion_value: float = proto.Field( + proto.DOUBLE, + number=12, + optional=True, + ) + currency_code: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + order_id: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + external_attribution_data: "ExternalAttributionData" = proto.Field( + proto.MESSAGE, + number=7, + message="ExternalAttributionData", + ) + custom_variables: MutableSequence["CustomVariable"] = proto.RepeatedField( + proto.MESSAGE, + number=15, + message="CustomVariable", + ) + cart_data: "CartData" = proto.Field( + proto.MESSAGE, + number=16, + message="CartData", + ) + user_identifiers: MutableSequence[offline_user_data.UserIdentifier] = ( + proto.RepeatedField( + proto.MESSAGE, + number=17, + message=offline_user_data.UserIdentifier, + ) + ) + conversion_environment: ( + conversion_environment_enum.ConversionEnvironmentEnum.ConversionEnvironment + ) = proto.Field( + proto.ENUM, + number=20, + enum=conversion_environment_enum.ConversionEnvironmentEnum.ConversionEnvironment, + ) + consent: gagc_consent.Consent = proto.Field( + proto.MESSAGE, + number=23, + message=gagc_consent.Consent, + ) + customer_type: ( + conversion_customer_type.ConversionCustomerTypeEnum.ConversionCustomerType + ) = proto.Field( + proto.ENUM, + number=26, + enum=conversion_customer_type.ConversionCustomerTypeEnum.ConversionCustomerType, + ) + user_ip_address: str = proto.Field( + proto.STRING, + number=27, + optional=True, + ) + session_attributes_encoded: bytes = proto.Field( + proto.BYTES, + number=24, + oneof="session_attributes", + ) + session_attributes_key_value_pairs: "SessionAttributesKeyValuePairs" = ( + proto.Field( + proto.MESSAGE, + number=25, + oneof="session_attributes", + message="SessionAttributesKeyValuePairs", + ) + ) + + +class CallConversion(proto.Message): + r"""A call conversion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + caller_id (str): + The caller id from which this call was + placed. Caller id is expected to be in E.164 + format with preceding '+' sign, for example, + "+16502531234". + + This field is a member of `oneof`_ ``_caller_id``. + call_start_date_time (str): + The date time at which the call occurred. The timezone must + be specified. The format is "yyyy-mm-dd hh:mm:ss+\|-hh:mm", + for example, "2019-01-01 12:32:45-08:00". + + This field is a member of `oneof`_ ``_call_start_date_time``. + conversion_action (str): + Resource name of the conversion action + associated with this conversion. + Note: Although this resource name consists of a + customer id and a conversion action id, + validation will ignore the customer id and use + the conversion action id as the sole identifier + of the conversion action. + + This field is a member of `oneof`_ ``_conversion_action``. + conversion_date_time (str): + The date time at which the conversion occurred. Must be + after the call time. The timezone must be specified. The + format is "yyyy-mm-dd hh:mm:ss+\|-hh:mm", for example, + "2019-01-01 12:32:45-08:00". + + This field is a member of `oneof`_ ``_conversion_date_time``. + conversion_value (float): + The value of the conversion for the + advertiser. + + This field is a member of `oneof`_ ``_conversion_value``. + currency_code (str): + Currency associated with the conversion + value. This is the ISO 4217 3-character currency + code. For example: USD, EUR. + + This field is a member of `oneof`_ ``_currency_code``. + custom_variables (MutableSequence[google.ads.googleads.v24.services.types.CustomVariable]): + The custom variables associated with this + conversion. + consent (google.ads.googleads.v24.common.types.Consent): + The consent setting for the event. + """ + + caller_id: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + call_start_date_time: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + conversion_action: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + conversion_date_time: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + conversion_value: float = proto.Field( + proto.DOUBLE, + number=11, + optional=True, + ) + currency_code: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + custom_variables: MutableSequence["CustomVariable"] = proto.RepeatedField( + proto.MESSAGE, + number=13, + message="CustomVariable", + ) + consent: gagc_consent.Consent = proto.Field( + proto.MESSAGE, + number=14, + message=gagc_consent.Consent, + ) + + +class ExternalAttributionData(proto.Message): + r"""Contains additional information about externally attributed + conversions. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + external_attribution_credit (float): + Represents the fraction of the conversion + that is attributed to the Google Ads click. + + This field is a member of `oneof`_ ``_external_attribution_credit``. + external_attribution_model (str): + Specifies the attribution model name. + + This field is a member of `oneof`_ ``_external_attribution_model``. + """ + + external_attribution_credit: float = proto.Field( + proto.DOUBLE, + number=3, + optional=True, + ) + external_attribution_model: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + + +class ClickConversionResult(proto.Message): + r"""Identifying information for a successfully processed + ``ClickConversion``. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + gclid (str): + The Google Click ID (gclid) associated with + this conversion. + + This field is a member of `oneof`_ ``_gclid``. + gbraid (str): + The URL parameter for clicks associated with + app conversions. + wbraid (str): + The URL parameter for clicks associated with + web conversions. + conversion_action (str): + Resource name of the conversion action + associated with this conversion. + + This field is a member of `oneof`_ ``_conversion_action``. + conversion_date_time (str): + The date time at which the conversion occurred. The format + is "yyyy-mm-dd hh:mm:ss+\|-hh:mm", for example, "2019-01-01 + 12:32:45-08:00". + + This field is a member of `oneof`_ ``_conversion_date_time``. + user_identifiers (MutableSequence[google.ads.googleads.v24.common.types.UserIdentifier]): + The user identifiers associated with this conversion. Only + hashed_email and hashed_phone_number are supported for + conversion uploads. The maximum number of user identifiers + for each conversion is 5. + """ + + gclid: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + gbraid: str = proto.Field( + proto.STRING, + number=8, + ) + wbraid: str = proto.Field( + proto.STRING, + number=9, + ) + conversion_action: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + conversion_date_time: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + user_identifiers: MutableSequence[offline_user_data.UserIdentifier] = ( + proto.RepeatedField( + proto.MESSAGE, + number=7, + message=offline_user_data.UserIdentifier, + ) + ) + + +class CallConversionResult(proto.Message): + r"""Identifying information for a successfully processed + CallConversionUpload. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + caller_id (str): + The caller id from which this call was + placed. Caller id is expected to be in E.164 + format with preceding '+' sign. + + This field is a member of `oneof`_ ``_caller_id``. + call_start_date_time (str): + The date time at which the call occurred. The format is + "yyyy-mm-dd hh:mm:ss+\|-hh:mm", for example, "2019-01-01 + 12:32:45-08:00". + + This field is a member of `oneof`_ ``_call_start_date_time``. + conversion_action (str): + Resource name of the conversion action + associated with this conversion. + + This field is a member of `oneof`_ ``_conversion_action``. + conversion_date_time (str): + The date time at which the conversion occurred. The format + is "yyyy-mm-dd hh:mm:ss+\|-hh:mm", for example, "2019-01-01 + 12:32:45-08:00". + + This field is a member of `oneof`_ ``_conversion_date_time``. + """ + + caller_id: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + call_start_date_time: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + conversion_action: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + conversion_date_time: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + + +class CustomVariable(proto.Message): + r"""A custom variable. + + Attributes: + conversion_custom_variable (str): + Resource name of the custom variable + associated with this conversion. + Note: Although this resource name consists of a + customer id and a conversion custom variable id, + validation will ignore the customer id and use + the conversion custom variable id as the sole + identifier of the conversion custom variable. + value (str): + The value string of this custom variable. + The value of the custom variable should not + contain private customer data, such as email + addresses or phone numbers. + """ + + conversion_custom_variable: str = proto.Field( + proto.STRING, + number=1, + ) + value: str = proto.Field( + proto.STRING, + number=2, + ) + + +class CartData(proto.Message): + r"""Contains additional information about cart data. + + Attributes: + merchant_id (int): + The Merchant Center ID where the items are + uploaded. + feed_country_code (str): + The country code associated with the feed + where the items are uploaded. + feed_language_code (str): + The language code associated with the feed + where the items are uploaded. + local_transaction_cost (float): + Sum of all transaction level discounts, such as free + shipping and coupon discounts for the whole cart. The + currency code is the same as that in the ``ClickConversion`` + message. + items (MutableSequence[google.ads.googleads.v24.services.types.CartData.Item]): + Data of the items purchased. + """ + + class Item(proto.Message): + r"""Contains data of the items purchased. + + Attributes: + product_id (str): + The shopping id of the item. Must be equal to + the Merchant Center product identifier. + quantity (int): + Number of items sold. + unit_price (float): + Unit price excluding tax, shipping, and any transaction + level discounts. The currency code is the same as that in + the ``ClickConversion`` message. + """ + + product_id: str = proto.Field( + proto.STRING, + number=1, + ) + quantity: int = proto.Field( + proto.INT32, + number=2, + ) + unit_price: float = proto.Field( + proto.DOUBLE, + number=3, + ) + + merchant_id: int = proto.Field( + proto.INT64, + number=6, + ) + feed_country_code: str = proto.Field( + proto.STRING, + number=2, + ) + feed_language_code: str = proto.Field( + proto.STRING, + number=3, + ) + local_transaction_cost: float = proto.Field( + proto.DOUBLE, + number=4, + ) + items: MutableSequence[Item] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message=Item, + ) + + +class SessionAttributeKeyValuePair(proto.Message): + r"""Contains one session attribute of the conversion. + + Attributes: + session_attribute_key (str): + Required. The name of the session attribute. + session_attribute_value (str): + Required. The value of the session attribute. + """ + + session_attribute_key: str = proto.Field( + proto.STRING, + number=1, + ) + session_attribute_value: str = proto.Field( + proto.STRING, + number=2, + ) + + +class SessionAttributesKeyValuePairs(proto.Message): + r"""Contains session attributes of the conversion, represented as + key-value pairs. + + Attributes: + key_value_pairs (MutableSequence[google.ads.googleads.v24.services.types.SessionAttributeKeyValuePair]): + Required. The session attributes for the + conversion. + """ + + key_value_pairs: MutableSequence["SessionAttributeKeyValuePair"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="SessionAttributeKeyValuePair", + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/conversion_value_rule_service.py b/google/ads/googleads/v24/services/types/conversion_value_rule_service.py new file mode 100644 index 000000000..b96c42c9c --- /dev/null +++ b/google/ads/googleads/v24/services/types/conversion_value_rule_service.py @@ -0,0 +1,210 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + conversion_value_rule as gagr_conversion_value_rule, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateConversionValueRulesRequest", + "ConversionValueRuleOperation", + "MutateConversionValueRulesResponse", + "MutateConversionValueRuleResult", + }, +) + + +class MutateConversionValueRulesRequest(proto.Message): + r"""Request message for + [ConversionValueRuleService.MutateConversionValueRules][google.ads.googleads.v24.services.ConversionValueRuleService.MutateConversionValueRules]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + conversion value rules are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.ConversionValueRuleOperation]): + Required. The list of operations to perform + on individual conversion value rules. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["ConversionValueRuleOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ConversionValueRuleOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=5, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=4, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class ConversionValueRuleOperation(proto.Message): + r"""A single operation (create, update, remove) on a conversion + value 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.ConversionValueRule): + Create operation: No resource name is + expected for the new conversion value rule. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.ConversionValueRule): + Update operation: The conversion value rule + is expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed conversion + value rule is expected, in this format: + + ``customers/{customer_id}/conversionValueRules/{conversion_value_rule_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_conversion_value_rule.ConversionValueRule = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_conversion_value_rule.ConversionValueRule, + ) + update: gagr_conversion_value_rule.ConversionValueRule = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_conversion_value_rule.ConversionValueRule, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateConversionValueRulesResponse(proto.Message): + r"""Response message for + [ConversionValueRuleService.MutateConversionValueRules][google.ads.googleads.v24.services.ConversionValueRuleService.MutateConversionValueRules]. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateConversionValueRuleResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateConversionValueRuleResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateConversionValueRuleResult", + ) + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + + +class MutateConversionValueRuleResult(proto.Message): + r"""The result for the conversion value rule mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + conversion_value_rule (google.ads.googleads.v24.resources.types.ConversionValueRule): + The mutated conversion value rule with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + conversion_value_rule: gagr_conversion_value_rule.ConversionValueRule = ( + proto.Field( + proto.MESSAGE, + number=2, + message=gagr_conversion_value_rule.ConversionValueRule, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/conversion_value_rule_set_service.py b/google/ads/googleads/v24/services/types/conversion_value_rule_set_service.py new file mode 100644 index 000000000..3115afafc --- /dev/null +++ b/google/ads/googleads/v24/services/types/conversion_value_rule_set_service.py @@ -0,0 +1,210 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + conversion_value_rule_set as gagr_conversion_value_rule_set, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateConversionValueRuleSetsRequest", + "ConversionValueRuleSetOperation", + "MutateConversionValueRuleSetsResponse", + "MutateConversionValueRuleSetResult", + }, +) + + +class MutateConversionValueRuleSetsRequest(proto.Message): + r"""Request message for + [ConversionValueRuleSetService.MutateConversionValueRuleSets][google.ads.googleads.v24.services.ConversionValueRuleSetService.MutateConversionValueRuleSets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + conversion value rule sets are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.ConversionValueRuleSetOperation]): + Required. The list of operations to perform + on individual conversion value rule sets. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["ConversionValueRuleSetOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ConversionValueRuleSetOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=5, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=4, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class ConversionValueRuleSetOperation(proto.Message): + r"""A single operation (create, update, remove) on a conversion + value rule set. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.ConversionValueRuleSet): + Create operation: No resource name is + expected for the new conversion value rule set. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.ConversionValueRuleSet): + Update operation: The conversion value rule + set is expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed conversion + value rule set is expected, in this format: + + ``customers/{customer_id}/conversionValueRuleSets/{conversion_value_rule_set_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_conversion_value_rule_set.ConversionValueRuleSet = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_conversion_value_rule_set.ConversionValueRuleSet, + ) + update: gagr_conversion_value_rule_set.ConversionValueRuleSet = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_conversion_value_rule_set.ConversionValueRuleSet, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateConversionValueRuleSetsResponse(proto.Message): + r"""Response message for + [ConversionValueRuleSetService.MutateConversionValueRuleSets][google.ads.googleads.v24.services.ConversionValueRuleSetService.MutateConversionValueRuleSets]. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateConversionValueRuleSetResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateConversionValueRuleSetResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateConversionValueRuleSetResult", + ) + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateConversionValueRuleSetResult(proto.Message): + r"""The result for the conversion value rule set mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + conversion_value_rule_set (google.ads.googleads.v24.resources.types.ConversionValueRuleSet): + The mutated conversion value rule set with only mutable + fields after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + conversion_value_rule_set: ( + gagr_conversion_value_rule_set.ConversionValueRuleSet + ) = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_conversion_value_rule_set.ConversionValueRuleSet, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/custom_audience_service.py b/google/ads/googleads/v24/services/types/custom_audience_service.py new file mode 100644 index 000000000..ee231b539 --- /dev/null +++ b/google/ads/googleads/v24/services/types/custom_audience_service.py @@ -0,0 +1,159 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import custom_audience +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomAudiencesRequest", + "CustomAudienceOperation", + "MutateCustomAudiencesResponse", + "MutateCustomAudienceResult", + }, +) + + +class MutateCustomAudiencesRequest(proto.Message): + r"""Request message for + [CustomAudienceService.MutateCustomAudiences][google.ads.googleads.v24.services.CustomAudienceService.MutateCustomAudiences]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose custom + audiences are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomAudienceOperation]): + Required. The list of operations to perform + on individual custom audiences. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CustomAudienceOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CustomAudienceOperation", + ) + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class CustomAudienceOperation(proto.Message): + r"""A single operation (create, update) on a custom audience. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.CustomAudience): + Create operation: No resource name is + expected for the new custom audience. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.CustomAudience): + Update operation: The custom audience is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed custom + audience is expected, in this format: + + ``customers/{customer_id}/customAudiences/{custom_audience_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: custom_audience.CustomAudience = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=custom_audience.CustomAudience, + ) + update: custom_audience.CustomAudience = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=custom_audience.CustomAudience, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateCustomAudiencesResponse(proto.Message): + r"""Response message for custom audience mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCustomAudienceResult]): + All results for the mutate. + """ + + results: MutableSequence["MutateCustomAudienceResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateCustomAudienceResult", + ) + ) + + +class MutateCustomAudienceResult(proto.Message): + r"""The result for the custom audience mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/custom_conversion_goal_service.py b/google/ads/googleads/v24/services/types/custom_conversion_goal_service.py new file mode 100644 index 000000000..dfd1566ab --- /dev/null +++ b/google/ads/googleads/v24/services/types/custom_conversion_goal_service.py @@ -0,0 +1,187 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + custom_conversion_goal as gagr_custom_conversion_goal, +) +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomConversionGoalsRequest", + "CustomConversionGoalOperation", + "MutateCustomConversionGoalsResponse", + "MutateCustomConversionGoalResult", + }, +) + + +class MutateCustomConversionGoalsRequest(proto.Message): + r"""Request message for + [CustomConversionGoalService.MutateCustomConversionGoals][google.ads.googleads.v24.services.CustomConversionGoalService.MutateCustomConversionGoals]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose custom + conversion goals are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomConversionGoalOperation]): + Required. The list of operations to perform + on individual custom conversion goal. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CustomConversionGoalOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CustomConversionGoalOperation", + ) + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=4, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CustomConversionGoalOperation(proto.Message): + r"""A single operation (create, remove) on a custom conversion + goal. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.CustomConversionGoal): + Create operation: No resource name is + expected for the new custom conversion goal + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.CustomConversionGoal): + Update operation: The custom conversion goal + is expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed custom + conversion goal is expected, in this format: + + 'customers/{customer_id}/customConversionGoals/{goal_id}' + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_custom_conversion_goal.CustomConversionGoal = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_custom_conversion_goal.CustomConversionGoal, + ) + update: gagr_custom_conversion_goal.CustomConversionGoal = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_custom_conversion_goal.CustomConversionGoal, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateCustomConversionGoalsResponse(proto.Message): + r"""Response message for a custom conversion goal mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCustomConversionGoalResult]): + All results for the mutate. + """ + + results: MutableSequence["MutateCustomConversionGoalResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateCustomConversionGoalResult", + ) + ) + + +class MutateCustomConversionGoalResult(proto.Message): + r"""The result for the custom conversion goal mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + custom_conversion_goal (google.ads.googleads.v24.resources.types.CustomConversionGoal): + The mutated CustomConversionGoal with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + custom_conversion_goal: gagr_custom_conversion_goal.CustomConversionGoal = ( + proto.Field( + proto.MESSAGE, + number=2, + message=gagr_custom_conversion_goal.CustomConversionGoal, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/custom_interest_service.py b/google/ads/googleads/v24/services/types/custom_interest_service.py new file mode 100644 index 000000000..c7a373e96 --- /dev/null +++ b/google/ads/googleads/v24/services/types/custom_interest_service.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import custom_interest +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomInterestsRequest", + "CustomInterestOperation", + "MutateCustomInterestsResponse", + "MutateCustomInterestResult", + }, +) + + +class MutateCustomInterestsRequest(proto.Message): + r"""Request message for + [CustomInterestService.MutateCustomInterests][google.ads.googleads.v24.services.CustomInterestService.MutateCustomInterests]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose custom + interests are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomInterestOperation]): + Required. The list of operations to perform + on individual custom interests. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CustomInterestOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CustomInterestOperation", + ) + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class CustomInterestOperation(proto.Message): + r"""A single operation (create, update) on a custom interest. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.CustomInterest): + Create operation: No resource name is + expected for the new custom interest. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.CustomInterest): + Update operation: The custom interest is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: custom_interest.CustomInterest = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=custom_interest.CustomInterest, + ) + update: custom_interest.CustomInterest = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=custom_interest.CustomInterest, + ) + + +class MutateCustomInterestsResponse(proto.Message): + r"""Response message for custom interest mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCustomInterestResult]): + All results for the mutate. + """ + + results: MutableSequence["MutateCustomInterestResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCustomInterestResult", + ) + ) + + +class MutateCustomInterestResult(proto.Message): + r"""The result for the custom interest mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/customer_asset_service.py b/google/ads/googleads/v24/services/types/customer_asset_service.py new file mode 100644 index 000000000..5e37cd341 --- /dev/null +++ b/google/ads/googleads/v24/services/types/customer_asset_service.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + customer_asset as gagr_customer_asset, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomerAssetsRequest", + "CustomerAssetOperation", + "MutateCustomerAssetsResponse", + "MutateCustomerAssetResult", + }, +) + + +class MutateCustomerAssetsRequest(proto.Message): + r"""Request message for + [CustomerAssetService.MutateCustomerAssets][google.ads.googleads.v24.services.CustomerAssetService.MutateCustomerAssets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + customer assets are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomerAssetOperation]): + Required. The list of operations to perform + on individual customer assets. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CustomerAssetOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CustomerAssetOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CustomerAssetOperation(proto.Message): + r"""A single operation (create, update, remove) on a customer + asset. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.CustomerAsset): + Create operation: No resource name is + expected for the new customer asset. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.CustomerAsset): + Update operation: The customer asset is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed customer + asset is expected, in this format: + + ``customers/{customer_id}/customerAssets/{asset_id}~{field_type}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_customer_asset.CustomerAsset = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_customer_asset.CustomerAsset, + ) + update: gagr_customer_asset.CustomerAsset = proto.Field( + proto.MESSAGE, + number=3, + oneof="operation", + message=gagr_customer_asset.CustomerAsset, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateCustomerAssetsResponse(proto.Message): + r"""Response message for a customer asset mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCustomerAssetResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + results: MutableSequence["MutateCustomerAssetResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCustomerAssetResult", + ) + + +class MutateCustomerAssetResult(proto.Message): + r"""The result for the customer asset mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + customer_asset (google.ads.googleads.v24.resources.types.CustomerAsset): + The mutated customer asset with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + customer_asset: gagr_customer_asset.CustomerAsset = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_customer_asset.CustomerAsset, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/customer_asset_set_service.py b/google/ads/googleads/v24/services/types/customer_asset_set_service.py new file mode 100644 index 000000000..3697fb36f --- /dev/null +++ b/google/ads/googleads/v24/services/types/customer_asset_set_service.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + customer_asset_set as gagr_customer_asset_set, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomerAssetSetsRequest", + "CustomerAssetSetOperation", + "MutateCustomerAssetSetsResponse", + "MutateCustomerAssetSetResult", + }, +) + + +class MutateCustomerAssetSetsRequest(proto.Message): + r"""Request message for + [CustomerAssetSetService.MutateCustomerAssetSets][google.ads.googleads.v24.services.CustomerAssetSetService.MutateCustomerAssetSets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + customer asset sets are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomerAssetSetOperation]): + Required. The list of operations to perform + on individual customer asset sets. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CustomerAssetSetOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CustomerAssetSetOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CustomerAssetSetOperation(proto.Message): + r"""A single operation (create, remove) on a customer asset set. + + 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: + create (google.ads.googleads.v24.resources.types.CustomerAssetSet): + Create operation: No resource name is + expected for the new customer asset set. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed customer + asset set is expected, in this format: + ``customers/{customer_id}/customerAssetSets/{asset_set_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: gagr_customer_asset_set.CustomerAssetSet = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_customer_asset_set.CustomerAssetSet, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateCustomerAssetSetsResponse(proto.Message): + r"""Response message for a customer asset set mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCustomerAssetSetResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (e.g. auth errors), we return an RPC + level error. + """ + + results: MutableSequence["MutateCustomerAssetSetResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateCustomerAssetSetResult", + ) + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateCustomerAssetSetResult(proto.Message): + r"""The result for the customer asset set mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + customer_asset_set (google.ads.googleads.v24.resources.types.CustomerAssetSet): + The mutated customer asset set with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + customer_asset_set: gagr_customer_asset_set.CustomerAssetSet = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_customer_asset_set.CustomerAssetSet, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/customer_client_link_service.py b/google/ads/googleads/v24/services/types/customer_client_link_service.py new file mode 100644 index 000000000..ff921835a --- /dev/null +++ b/google/ads/googleads/v24/services/types/customer_client_link_service.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import customer_client_link +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomerClientLinkRequest", + "CustomerClientLinkOperation", + "MutateCustomerClientLinkResponse", + "MutateCustomerClientLinkResult", + }, +) + + +class MutateCustomerClientLinkRequest(proto.Message): + r"""Request message for + [CustomerClientLinkService.MutateCustomerClientLink][google.ads.googleads.v24.services.CustomerClientLinkService.MutateCustomerClientLink]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + customer link are being modified. + operation (google.ads.googleads.v24.services.types.CustomerClientLinkOperation): + Required. The operation to perform on the + individual CustomerClientLink. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: "CustomerClientLinkOperation" = proto.Field( + proto.MESSAGE, + number=2, + message="CustomerClientLinkOperation", + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class CustomerClientLinkOperation(proto.Message): + r"""A single operation (create, update) on a CustomerClientLink. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.CustomerClientLink): + Create operation: No resource name is + expected for the new link. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.CustomerClientLink): + Update operation: The link is expected to + have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: customer_client_link.CustomerClientLink = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=customer_client_link.CustomerClientLink, + ) + update: customer_client_link.CustomerClientLink = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=customer_client_link.CustomerClientLink, + ) + + +class MutateCustomerClientLinkResponse(proto.Message): + r"""Response message for a CustomerClientLink mutate. + + Attributes: + result (google.ads.googleads.v24.services.types.MutateCustomerClientLinkResult): + A result that identifies the resource + affected by the mutate request. + """ + + result: "MutateCustomerClientLinkResult" = proto.Field( + proto.MESSAGE, + number=1, + message="MutateCustomerClientLinkResult", + ) + + +class MutateCustomerClientLinkResult(proto.Message): + r"""The result for a single customer client link mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/customer_conversion_goal_service.py b/google/ads/googleads/v24/services/types/customer_conversion_goal_service.py new file mode 100644 index 000000000..145bbdd0a --- /dev/null +++ b/google/ads/googleads/v24/services/types/customer_conversion_goal_service.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import customer_conversion_goal +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomerConversionGoalsRequest", + "CustomerConversionGoalOperation", + "MutateCustomerConversionGoalsResponse", + "MutateCustomerConversionGoalResult", + }, +) + + +class MutateCustomerConversionGoalsRequest(proto.Message): + r"""Request message for + [CustomerConversionGoalService.MutateCustomerConversionGoals][google.ads.googleads.v24.services.CustomerConversionGoalService.MutateCustomerConversionGoals]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + customer conversion goals are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomerConversionGoalOperation]): + Required. The list of operations to perform + on individual customer conversion goal. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CustomerConversionGoalOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CustomerConversionGoalOperation", + ) + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class CustomerConversionGoalOperation(proto.Message): + r"""A single operation (update) on a customer conversion goal. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + update (google.ads.googleads.v24.resources.types.CustomerConversionGoal): + Update operation: The customer conversion + goal is expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=2, + message=field_mask_pb2.FieldMask, + ) + update: customer_conversion_goal.CustomerConversionGoal = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=customer_conversion_goal.CustomerConversionGoal, + ) + + +class MutateCustomerConversionGoalsResponse(proto.Message): + r"""Response message for a customer conversion goal mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCustomerConversionGoalResult]): + All results for the mutate. + """ + + results: MutableSequence["MutateCustomerConversionGoalResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateCustomerConversionGoalResult", + ) + ) + + +class MutateCustomerConversionGoalResult(proto.Message): + r"""The result for the customer conversion goal mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/customer_customizer_service.py b/google/ads/googleads/v24/services/types/customer_customizer_service.py new file mode 100644 index 000000000..5b64e3765 --- /dev/null +++ b/google/ads/googleads/v24/services/types/customer_customizer_service.py @@ -0,0 +1,188 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + customer_customizer as gagr_customer_customizer, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomerCustomizersRequest", + "CustomerCustomizerOperation", + "MutateCustomerCustomizersResponse", + "MutateCustomerCustomizerResult", + }, +) + + +class MutateCustomerCustomizersRequest(proto.Message): + r"""Request message for + [CustomerCustomizerService.MutateCustomerCustomizers][google.ads.googleads.v24.services.CustomerCustomizerService.MutateCustomerCustomizers]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + customer customizers are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomerCustomizerOperation]): + Required. The list of operations to perform + on individual customer customizers. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CustomerCustomizerOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CustomerCustomizerOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CustomerCustomizerOperation(proto.Message): + r"""A single operation (create, remove) on a customizer + attribute. + + 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: + create (google.ads.googleads.v24.resources.types.CustomerCustomizer): + Create operation: No resource name is + expected for the new customer customizer + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed customer + customizer is expected, in this format: + ``customers/{customer_id}/customerCustomizers/{customizer_attribute_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: gagr_customer_customizer.CustomerCustomizer = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_customer_customizer.CustomerCustomizer, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateCustomerCustomizersResponse(proto.Message): + r"""Response message for a customizer attribute mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCustomerCustomizerResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateCustomerCustomizerResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateCustomerCustomizerResult", + ) + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateCustomerCustomizerResult(proto.Message): + r"""The result for the customizer attribute mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + customer_customizer (google.ads.googleads.v24.resources.types.CustomerCustomizer): + The mutated CustomerCustomizer with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + customer_customizer: gagr_customer_customizer.CustomerCustomizer = ( + proto.Field( + proto.MESSAGE, + number=2, + message=gagr_customer_customizer.CustomerCustomizer, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/customer_label_service.py b/google/ads/googleads/v24/services/types/customer_label_service.py new file mode 100644 index 000000000..55f63c040 --- /dev/null +++ b/google/ads/googleads/v24/services/types/customer_label_service.py @@ -0,0 +1,164 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import customer_label +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomerLabelsRequest", + "CustomerLabelOperation", + "MutateCustomerLabelsResponse", + "MutateCustomerLabelResult", + }, +) + + +class MutateCustomerLabelsRequest(proto.Message): + r"""Request message for + [CustomerLabelService.MutateCustomerLabels][google.ads.googleads.v24.services.CustomerLabelService.MutateCustomerLabels]. + + A single ``MutateCustomerLabelsRequest`` can only modify labels for + the single customer account specified in the request. To apply a + label to multiple different accounts, separate + ``MutateCustomerLabelsRequest`` calls must be made. + + Attributes: + customer_id (str): + Required. ID of the customer whose + customer-label relationships are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomerLabelOperation]): + Required. The list of operations to perform + on customer-label relationships. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CustomerLabelOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CustomerLabelOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class CustomerLabelOperation(proto.Message): + r"""A single operation (create, remove) on a customer-label + relationship. + + 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: + create (google.ads.googleads.v24.resources.types.CustomerLabel): + Create operation: No resource name is + expected for the new customer-label + relationship. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the customer-label + relationship being removed, in this format: + + ``customers/{customer_id}/customerLabels/{label_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: customer_label.CustomerLabel = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=customer_label.CustomerLabel, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateCustomerLabelsResponse(proto.Message): + r"""Response message for a customer labels mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCustomerLabelResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateCustomerLabelResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCustomerLabelResult", + ) + + +class MutateCustomerLabelResult(proto.Message): + r"""The result for a customer label mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/customer_lifecycle_goal_service.py b/google/ads/googleads/v24/services/types/customer_lifecycle_goal_service.py new file mode 100644 index 000000000..99d9278e8 --- /dev/null +++ b/google/ads/googleads/v24/services/types/customer_lifecycle_goal_service.py @@ -0,0 +1,145 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import customer_lifecycle_goal +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "ConfigureCustomerLifecycleGoalsRequest", + "CustomerLifecycleGoalOperation", + "ConfigureCustomerLifecycleGoalsResponse", + "ConfigureCustomerLifecycleGoalsResult", + }, +) + + +class ConfigureCustomerLifecycleGoalsRequest(proto.Message): + r"""Request message for + [CustomerLifecycleGoalService.ConfigureCustomerLifecycleGoals][google.ads.googleads.v24.services.CustomerLifecycleGoalService.ConfigureCustomerLifecycleGoals]. + + Attributes: + customer_id (str): + Required. The ID of the customer performing + the upload. + operation (google.ads.googleads.v24.services.types.CustomerLifecycleGoalOperation): + Required. The operation to perform customer + lifecycle goal update. + validate_only (bool): + Optional. If true, the request is validated + but not executed. Only errors are returned, not + results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: "CustomerLifecycleGoalOperation" = proto.Field( + proto.MESSAGE, + number=2, + message="CustomerLifecycleGoalOperation", + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class CustomerLifecycleGoalOperation(proto.Message): + r"""A single operation on a customer lifecycle goal. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. FieldMask that determines which + resource fields are modified in an update. + create (google.ads.googleads.v24.resources.types.CustomerLifecycleGoal): + Create operation: Create a new customer + lifecycle goal. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.CustomerLifecycleGoal): + Update operation: Update an existing customer + lifecycle goal. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=2, + message=field_mask_pb2.FieldMask, + ) + create: customer_lifecycle_goal.CustomerLifecycleGoal = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=customer_lifecycle_goal.CustomerLifecycleGoal, + ) + update: customer_lifecycle_goal.CustomerLifecycleGoal = proto.Field( + proto.MESSAGE, + number=3, + oneof="operation", + message=customer_lifecycle_goal.CustomerLifecycleGoal, + ) + + +class ConfigureCustomerLifecycleGoalsResponse(proto.Message): + r"""Response message for + [CustomerLifecycleGoalService.ConfigureCustomerLifecycleGoals][google.ads.googleads.v24.services.CustomerLifecycleGoalService.ConfigureCustomerLifecycleGoals]. + + Attributes: + result (google.ads.googleads.v24.services.types.ConfigureCustomerLifecycleGoalsResult): + result for the customer lifecycle goal + configuration. + """ + + result: "ConfigureCustomerLifecycleGoalsResult" = proto.Field( + proto.MESSAGE, + number=1, + message="ConfigureCustomerLifecycleGoalsResult", + ) + + +class ConfigureCustomerLifecycleGoalsResult(proto.Message): + r"""The result for the customer lifecycle goal configuration. + + Attributes: + resource_name (str): + Returned for the successful operation. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/customer_manager_link_service.py b/google/ads/googleads/v24/services/types/customer_manager_link_service.py new file mode 100644 index 000000000..20df4c94b --- /dev/null +++ b/google/ads/googleads/v24/services/types/customer_manager_link_service.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import customer_manager_link +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomerManagerLinkRequest", + "MoveManagerLinkRequest", + "CustomerManagerLinkOperation", + "MutateCustomerManagerLinkResponse", + "MoveManagerLinkResponse", + "MutateCustomerManagerLinkResult", + }, +) + + +class MutateCustomerManagerLinkRequest(proto.Message): + r"""Request message for + [CustomerManagerLinkService.MutateCustomerManagerLink][google.ads.googleads.v24.services.CustomerManagerLinkService.MutateCustomerManagerLink]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + customer manager links are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomerManagerLinkOperation]): + Required. The list of operations to perform + on individual customer manager links. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CustomerManagerLinkOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CustomerManagerLinkOperation", + ) + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class MoveManagerLinkRequest(proto.Message): + r"""Request message for + [CustomerManagerLinkService.MoveManagerLink][google.ads.googleads.v24.services.CustomerManagerLinkService.MoveManagerLink]. + + Attributes: + customer_id (str): + Required. The ID of the client customer that + is being moved. + previous_customer_manager_link (str): + Required. The resource name of the previous + CustomerManagerLink. The resource name has the form: + ``customers/{customer_id}/customerManagerLinks/{manager_customer_id}~{manager_link_id}`` + new_manager (str): + Required. The resource name of the new manager customer that + the client wants to move to. Customer resource names have + the format: "customers/{customer_id}". + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + previous_customer_manager_link: str = proto.Field( + proto.STRING, + number=2, + ) + new_manager: str = proto.Field( + proto.STRING, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class CustomerManagerLinkOperation(proto.Message): + r"""Updates the status of a CustomerManagerLink. + The following actions are possible: + + 1. Update operation with status ACTIVE accepts a pending + invitation. + 2. Update operation with status REFUSED declines a pending + invitation. + 3. Update operation with status INACTIVE terminates link to + manager. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + update (google.ads.googleads.v24.resources.types.CustomerManagerLink): + Update operation: The link is expected to + have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + update: customer_manager_link.CustomerManagerLink = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=customer_manager_link.CustomerManagerLink, + ) + + +class MutateCustomerManagerLinkResponse(proto.Message): + r"""Response message for a CustomerManagerLink mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCustomerManagerLinkResult]): + A result that identifies the resource + affected by the mutate request. + """ + + results: MutableSequence["MutateCustomerManagerLinkResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateCustomerManagerLinkResult", + ) + ) + + +class MoveManagerLinkResponse(proto.Message): + r"""Response message for a CustomerManagerLink moveManagerLink. + + Attributes: + resource_name (str): + Returned for successful operations. + Represents a CustomerManagerLink resource of the + newly created link between client customer and + new manager customer. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class MutateCustomerManagerLinkResult(proto.Message): + r"""The result for the customer manager link mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/customer_negative_criterion_service.py b/google/ads/googleads/v24/services/types/customer_negative_criterion_service.py new file mode 100644 index 000000000..a442c88d6 --- /dev/null +++ b/google/ads/googleads/v24/services/types/customer_negative_criterion_service.py @@ -0,0 +1,191 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + customer_negative_criterion as gagr_customer_negative_criterion, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomerNegativeCriteriaRequest", + "CustomerNegativeCriterionOperation", + "MutateCustomerNegativeCriteriaResponse", + "MutateCustomerNegativeCriteriaResult", + }, +) + + +class MutateCustomerNegativeCriteriaRequest(proto.Message): + r"""Request message for + [CustomerNegativeCriterionService.MutateCustomerNegativeCriteria][google.ads.googleads.v24.services.CustomerNegativeCriterionService.MutateCustomerNegativeCriteria]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + criteria are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomerNegativeCriterionOperation]): + Required. The list of operations to perform + on individual criteria. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CustomerNegativeCriterionOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CustomerNegativeCriterionOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CustomerNegativeCriterionOperation(proto.Message): + r"""A single operation (create or remove) on a customer level + negative criterion. + + 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: + create (google.ads.googleads.v24.resources.types.CustomerNegativeCriterion): + Create operation: No resource name is + expected for the new criterion. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed criterion + is expected, in this format: + + ``customers/{customer_id}/customerNegativeCriteria/{criterion_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: gagr_customer_negative_criterion.CustomerNegativeCriterion = ( + proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_customer_negative_criterion.CustomerNegativeCriterion, + ) + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateCustomerNegativeCriteriaResponse(proto.Message): + r"""Response message for customer negative criterion mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCustomerNegativeCriteriaResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateCustomerNegativeCriteriaResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCustomerNegativeCriteriaResult", + ) + ) + + +class MutateCustomerNegativeCriteriaResult(proto.Message): + r"""The result for the criterion mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + customer_negative_criterion (google.ads.googleads.v24.resources.types.CustomerNegativeCriterion): + The mutated criterion with only mutable fields after mutate. + The field will only be returned when response_content_type + is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + customer_negative_criterion: ( + gagr_customer_negative_criterion.CustomerNegativeCriterion + ) = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_customer_negative_criterion.CustomerNegativeCriterion, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/customer_service.py b/google/ads/googleads/v24/services/types/customer_service.py new file mode 100644 index 000000000..36045b375 --- /dev/null +++ b/google/ads/googleads/v24/services/types/customer_service.py @@ -0,0 +1,251 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import access_role as gage_access_role +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import customer as gagr_customer +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomerRequest", + "CreateCustomerClientRequest", + "CustomerOperation", + "CreateCustomerClientResponse", + "MutateCustomerResponse", + "MutateCustomerResult", + "ListAccessibleCustomersRequest", + "ListAccessibleCustomersResponse", + }, +) + + +class MutateCustomerRequest(proto.Message): + r"""Request message for + [CustomerService.MutateCustomer][google.ads.googleads.v24.services.CustomerService.MutateCustomer]. + + Attributes: + customer_id (str): + Required. The ID of the customer being + modified. + operation (google.ads.googleads.v24.services.types.CustomerOperation): + Required. The operation to perform on the + customer + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: "CustomerOperation" = proto.Field( + proto.MESSAGE, + number=4, + message="CustomerOperation", + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=5, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=6, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CreateCustomerClientRequest(proto.Message): + r"""Request message for + [CustomerService.CreateCustomerClient][google.ads.googleads.v24.services.CustomerService.CreateCustomerClient]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer_id (str): + Required. The ID of the Manager under whom + client customer is being created. + customer_client (google.ads.googleads.v24.resources.types.Customer): + Required. The new client customer to create. + The resource name on this customer will be + ignored. + email_address (str): + Email address of the user who should be + invited on the created client customer. + Accessible only to customers on the allow-list. + + This field is a member of `oneof`_ ``_email_address``. + access_role (google.ads.googleads.v24.enums.types.AccessRoleEnum.AccessRole): + The proposed role of user on the created + client customer. Accessible only to customers on + the allow-list. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + customer_client: gagr_customer.Customer = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_customer.Customer, + ) + email_address: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + access_role: gage_access_role.AccessRoleEnum.AccessRole = proto.Field( + proto.ENUM, + number=4, + enum=gage_access_role.AccessRoleEnum.AccessRole, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=6, + ) + + +class CustomerOperation(proto.Message): + r"""A single update on a customer. + + Attributes: + update (google.ads.googleads.v24.resources.types.Customer): + Mutate operation. Only updates are supported + for customer. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + """ + + update: gagr_customer.Customer = proto.Field( + proto.MESSAGE, + number=1, + message=gagr_customer.Customer, + ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=2, + message=field_mask_pb2.FieldMask, + ) + + +class CreateCustomerClientResponse(proto.Message): + r"""Response message for CreateCustomerClient mutate. + + Attributes: + resource_name (str): + The resource name of the newly created customer. Customer + resource names have the form: ``customers/{customer_id}``. + invitation_link (str): + Link for inviting user to access the created + customer. Accessible to allowlisted customers + only. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=2, + ) + invitation_link: str = proto.Field( + proto.STRING, + number=3, + ) + + +class MutateCustomerResponse(proto.Message): + r"""Response message for customer mutate. + + Attributes: + result (google.ads.googleads.v24.services.types.MutateCustomerResult): + Result for the mutate. + """ + + result: "MutateCustomerResult" = proto.Field( + proto.MESSAGE, + number=2, + message="MutateCustomerResult", + ) + + +class MutateCustomerResult(proto.Message): + r"""The result for the customer mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + customer (google.ads.googleads.v24.resources.types.Customer): + The mutated customer with only mutable fields after mutate. + The fields will only be returned when response_content_type + is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + customer: gagr_customer.Customer = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_customer.Customer, + ) + + +class ListAccessibleCustomersRequest(proto.Message): + r"""Request message for + [CustomerService.ListAccessibleCustomers][google.ads.googleads.v24.services.CustomerService.ListAccessibleCustomers]. + + """ + + +class ListAccessibleCustomersResponse(proto.Message): + r"""Response message for + [CustomerService.ListAccessibleCustomers][google.ads.googleads.v24.services.CustomerService.ListAccessibleCustomers]. + + Attributes: + resource_names (MutableSequence[str]): + Resource name of customers directly + accessible by the user authenticating the call. + """ + + resource_names: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/customer_sk_ad_network_conversion_value_schema_service.py b/google/ads/googleads/v24/services/types/customer_sk_ad_network_conversion_value_schema_service.py new file mode 100644 index 000000000..941ab5f8e --- /dev/null +++ b/google/ads/googleads/v24/services/types/customer_sk_ad_network_conversion_value_schema_service.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import ( + customer_sk_ad_network_conversion_value_schema, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "CustomerSkAdNetworkConversionValueSchemaOperation", + "MutateCustomerSkAdNetworkConversionValueSchemaRequest", + "MutateCustomerSkAdNetworkConversionValueSchemaResult", + "MutateCustomerSkAdNetworkConversionValueSchemaResponse", + }, +) + + +class CustomerSkAdNetworkConversionValueSchemaOperation(proto.Message): + r"""A single update operation for a + CustomerSkAdNetworkConversionValueSchema. + + Attributes: + update (google.ads.googleads.v24.resources.types.CustomerSkAdNetworkConversionValueSchema): + Update operation: The schema is expected to + have a valid resource name. + """ + + update: ( + customer_sk_ad_network_conversion_value_schema.CustomerSkAdNetworkConversionValueSchema + ) = proto.Field( + proto.MESSAGE, + number=1, + message=customer_sk_ad_network_conversion_value_schema.CustomerSkAdNetworkConversionValueSchema, + ) + + +class MutateCustomerSkAdNetworkConversionValueSchemaRequest(proto.Message): + r"""Request message for + [CustomerSkAdNetworkConversionValueSchemaService.MutateCustomerSkAdNetworkConversionValueSchema][google.ads.googleads.v24.services.CustomerSkAdNetworkConversionValueSchemaService.MutateCustomerSkAdNetworkConversionValueSchema]. + + Attributes: + customer_id (str): + The ID of the customer whose shared sets are + being modified. + operation (google.ads.googleads.v24.services.types.CustomerSkAdNetworkConversionValueSchemaOperation): + The operation to perform. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + enable_warnings (bool): + Optional. If true, enables returning + warnings. Warnings return error messages and + error codes without blocking the execution of + the mutate operation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: "CustomerSkAdNetworkConversionValueSchemaOperation" = ( + proto.Field( + proto.MESSAGE, + number=2, + message="CustomerSkAdNetworkConversionValueSchemaOperation", + ) + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + enable_warnings: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class MutateCustomerSkAdNetworkConversionValueSchemaResult(proto.Message): + r"""The result for the CustomerSkAdNetworkConversionValueSchema + mutate. + + Attributes: + resource_name (str): + Resource name of the customer that was + modified. + app_id (str): + App ID of the SkanConversionValue modified. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + app_id: str = proto.Field( + proto.STRING, + number=2, + ) + + +class MutateCustomerSkAdNetworkConversionValueSchemaResponse(proto.Message): + r"""Response message for + MutateCustomerSkAdNetworkConversionValueSchema. + + Attributes: + result (google.ads.googleads.v24.services.types.MutateCustomerSkAdNetworkConversionValueSchemaResult): + All results for the mutate. + warning (google.rpc.status_pb2.Status): + Non blocking errors that provides schema validation failure + details. Returned only when enable_warnings = true. + """ + + result: "MutateCustomerSkAdNetworkConversionValueSchemaResult" = ( + proto.Field( + proto.MESSAGE, + number=1, + message="MutateCustomerSkAdNetworkConversionValueSchemaResult", + ) + ) + warning: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/customer_user_access_invitation_service.py b/google/ads/googleads/v24/services/types/customer_user_access_invitation_service.py new file mode 100644 index 000000000..ffc65ea23 --- /dev/null +++ b/google/ads/googleads/v24/services/types/customer_user_access_invitation_service.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import ( + customer_user_access_invitation, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomerUserAccessInvitationRequest", + "CustomerUserAccessInvitationOperation", + "MutateCustomerUserAccessInvitationResponse", + "MutateCustomerUserAccessInvitationResult", + }, +) + + +class MutateCustomerUserAccessInvitationRequest(proto.Message): + r"""Request message for + [CustomerUserAccessInvitationService.MutateCustomerUserAccessInvitation][google.ads.googleads.v24.services.CustomerUserAccessInvitationService.MutateCustomerUserAccessInvitation] + + Attributes: + customer_id (str): + Required. The ID of the customer whose access + invitation is being modified. + operation (google.ads.googleads.v24.services.types.CustomerUserAccessInvitationOperation): + Required. The operation to perform on the + access invitation + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: "CustomerUserAccessInvitationOperation" = proto.Field( + proto.MESSAGE, + number=2, + message="CustomerUserAccessInvitationOperation", + ) + + +class CustomerUserAccessInvitationOperation(proto.Message): + r"""A single operation (create or remove) on customer user access + invitation. + + 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: + create (google.ads.googleads.v24.resources.types.CustomerUserAccessInvitation): + Create operation: No resource name is + expected for the new access invitation. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the revoke invitation + is expected, in this format: + + ``customers/{customer_id}/customerUserAccessInvitations/{invitation_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: customer_user_access_invitation.CustomerUserAccessInvitation = ( + proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=customer_user_access_invitation.CustomerUserAccessInvitation, + ) + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateCustomerUserAccessInvitationResponse(proto.Message): + r"""Response message for access invitation mutate. + + Attributes: + result (google.ads.googleads.v24.services.types.MutateCustomerUserAccessInvitationResult): + Result for the mutate. + """ + + result: "MutateCustomerUserAccessInvitationResult" = proto.Field( + proto.MESSAGE, + number=1, + message="MutateCustomerUserAccessInvitationResult", + ) + + +class MutateCustomerUserAccessInvitationResult(proto.Message): + r"""The result for the access invitation mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/customer_user_access_service.py b/google/ads/googleads/v24/services/types/customer_user_access_service.py new file mode 100644 index 000000000..0be6a5411 --- /dev/null +++ b/google/ads/googleads/v24/services/types/customer_user_access_service.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import customer_user_access +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomerUserAccessRequest", + "CustomerUserAccessOperation", + "MutateCustomerUserAccessResponse", + "MutateCustomerUserAccessResult", + }, +) + + +class MutateCustomerUserAccessRequest(proto.Message): + r"""Mutate Request for + [CustomerUserAccessService.MutateCustomerUserAccess][google.ads.googleads.v24.services.CustomerUserAccessService.MutateCustomerUserAccess]. + + Attributes: + customer_id (str): + Required. The ID of the customer being + modified. + operation (google.ads.googleads.v24.services.types.CustomerUserAccessOperation): + Required. The operation to perform on the + customer + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: "CustomerUserAccessOperation" = proto.Field( + proto.MESSAGE, + number=2, + message="CustomerUserAccessOperation", + ) + + +class CustomerUserAccessOperation(proto.Message): + r"""A single operation (update, remove) on customer user access. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + update (google.ads.googleads.v24.resources.types.CustomerUserAccess): + Update operation: The customer user access is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed access is + expected, in this format: + + ``customers/{customer_id}/customerUserAccesses/{CustomerUserAccess.user_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=3, + message=field_mask_pb2.FieldMask, + ) + update: customer_user_access.CustomerUserAccess = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=customer_user_access.CustomerUserAccess, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateCustomerUserAccessResponse(proto.Message): + r"""Response message for customer user access mutate. + + Attributes: + result (google.ads.googleads.v24.services.types.MutateCustomerUserAccessResult): + Result for the mutate. + """ + + result: "MutateCustomerUserAccessResult" = proto.Field( + proto.MESSAGE, + number=1, + message="MutateCustomerUserAccessResult", + ) + + +class MutateCustomerUserAccessResult(proto.Message): + r"""The result for the customer user access mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/customizer_attribute_service.py b/google/ads/googleads/v24/services/types/customizer_attribute_service.py new file mode 100644 index 000000000..6cbfcef34 --- /dev/null +++ b/google/ads/googleads/v24/services/types/customizer_attribute_service.py @@ -0,0 +1,197 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + customizer_attribute as gagr_customizer_attribute, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateCustomizerAttributesRequest", + "CustomizerAttributeOperation", + "MutateCustomizerAttributesResponse", + "MutateCustomizerAttributeResult", + }, +) + + +class MutateCustomizerAttributesRequest(proto.Message): + r"""Request message for + [CustomizerAttributeService.MutateCustomizerAttributes][google.ads.googleads.v24.services.CustomizerAttributeService.MutateCustomizerAttributes]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + customizer attributes are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.CustomizerAttributeOperation]): + Required. The list of operations to perform + on individual customizer attributes. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["CustomizerAttributeOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CustomizerAttributeOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class CustomizerAttributeOperation(proto.Message): + r"""A single operation (create, remove) on a customizer + attribute. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.CustomizerAttribute): + Create operation: No resource name is + expected for the new customizer attribute + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed customizer + attribute is expected, in this format: + ``customers/{customer_id}/customizerAttributes/{customizer_attribute_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_customizer_attribute.CustomizerAttribute = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_customizer_attribute.CustomizerAttribute, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateCustomizerAttributesResponse(proto.Message): + r"""Response message for a customizer attribute mutate. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateCustomizerAttributeResult]): + All results for the mutate. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + """ + + results: MutableSequence["MutateCustomizerAttributeResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateCustomizerAttributeResult", + ) + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateCustomizerAttributeResult(proto.Message): + r"""The result for the customizer attribute mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + customizer_attribute (google.ads.googleads.v24.resources.types.CustomizerAttribute): + The mutated CustomizerAttribute with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + customizer_attribute: gagr_customizer_attribute.CustomizerAttribute = ( + proto.Field( + proto.MESSAGE, + number=2, + message=gagr_customizer_attribute.CustomizerAttribute, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/data_link_service.py b/google/ads/googleads/v24/services/types/data_link_service.py new file mode 100644 index 000000000..b1d231d47 --- /dev/null +++ b/google/ads/googleads/v24/services/types/data_link_service.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + data_link_status as gage_data_link_status, +) +from google.ads.googleads.v24.resources.types import data_link as gagr_data_link + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "CreateDataLinkRequest", + "CreateDataLinkResponse", + "RemoveDataLinkRequest", + "RemoveDataLinkResponse", + "UpdateDataLinkRequest", + "UpdateDataLinkResponse", + }, +) + + +class CreateDataLinkRequest(proto.Message): + r"""Request message for + [DataLinkService.CreateDataLink][google.ads.googleads.v24.services.DataLinkService.CreateDataLink]. + + Attributes: + customer_id (str): + Required. The ID of the customer for which + the data link is created. + data_link (google.ads.googleads.v24.resources.types.DataLink): + Required. The data link to be created. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + data_link: gagr_data_link.DataLink = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_data_link.DataLink, + ) + + +class CreateDataLinkResponse(proto.Message): + r"""Response message for + [DataLinkService.CreateDataLink][google.ads.googleads.v24.services.DataLinkService.CreateDataLink]. + + Attributes: + resource_name (str): + Returned for successful operations. Resource + name of the data link. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class RemoveDataLinkRequest(proto.Message): + r"""Request message for + [DataLinkService.RemoveDataLink][google.ads.googleads.v24.services.DataLinkService.RemoveDataLink]. + + Attributes: + customer_id (str): + Required. The ID of the customer for which + the data link is updated. + resource_name (str): + Required. The data link is expected to have a + valid resource name. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + resource_name: str = proto.Field( + proto.STRING, + number=2, + ) + + +class RemoveDataLinkResponse(proto.Message): + r"""Response message for + [DataLinkService.RemoveDataLink][google.ads.googleads.v24.services.DataLinkService.RemoveDataLink]. + + Attributes: + resource_name (str): + Result for the remove request. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class UpdateDataLinkRequest(proto.Message): + r"""Request message for + [DataLinkService.UpdateDataLink][google.ads.googleads.v24.services.DataLinkService.UpdateDataLink]. + + Attributes: + customer_id (str): + Required. The ID of the customer for which + the data link is created. + data_link_status (google.ads.googleads.v24.enums.types.DataLinkStatusEnum.DataLinkStatus): + Required. The data link status to be updated + to. + resource_name (str): + Required. The data link is expected to have a + valid resource name. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + data_link_status: ( + gage_data_link_status.DataLinkStatusEnum.DataLinkStatus + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_data_link_status.DataLinkStatusEnum.DataLinkStatus, + ) + resource_name: str = proto.Field( + proto.STRING, + number=3, + ) + + +class UpdateDataLinkResponse(proto.Message): + r"""Response message for + [DataLinkService.UpdateDataLink][google.ads.googleads.v24.services.DataLinkService.UpdateDataLink]. + + Attributes: + resource_name (str): + Returned for successful operations. Resource + name of the data link. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/experiment_arm_service.py b/google/ads/googleads/v24/services/types/experiment_arm_service.py new file mode 100644 index 000000000..06c3cfc13 --- /dev/null +++ b/google/ads/googleads/v24/services/types/experiment_arm_service.py @@ -0,0 +1,201 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + experiment_arm as gagr_experiment_arm, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateExperimentArmsRequest", + "ExperimentArmOperation", + "MutateExperimentArmsResponse", + "MutateExperimentArmResult", + }, +) + + +class MutateExperimentArmsRequest(proto.Message): + r"""Request message for + [ExperimentArmService.MutateExperimentArms][google.ads.googleads.v24.services.ExperimentArmService.MutateExperimentArms]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + experiments are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.ExperimentArmOperation]): + Required. The list of operations to perform + on individual experiment arm. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["ExperimentArmOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ExperimentArmOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class ExperimentArmOperation(proto.Message): + r"""A single operation on an experiment arm. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.ExperimentArm): + Create operation + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.ExperimentArm): + Update operation: The experiment arm is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: The experiment arm is expected to have a + valid resource name, in this format: + + ``customers/{customer_id}/experiments/{campaign_experiment_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_experiment_arm.ExperimentArm = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_experiment_arm.ExperimentArm, + ) + update: gagr_experiment_arm.ExperimentArm = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_experiment_arm.ExperimentArm, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateExperimentArmsResponse(proto.Message): + r"""Response message for experiment arm mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateExperimentArmResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + results: MutableSequence["MutateExperimentArmResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateExperimentArmResult", + ) + + +class MutateExperimentArmResult(proto.Message): + r"""The result for the experiment arm mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + experiment_arm (google.ads.googleads.v24.resources.types.ExperimentArm): + The mutated experiment arm with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + experiment_arm: gagr_experiment_arm.ExperimentArm = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_experiment_arm.ExperimentArm, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/experiment_service.py b/google/ads/googleads/v24/services/types/experiment_service.py new file mode 100644 index 000000000..f14a34c86 --- /dev/null +++ b/google/ads/googleads/v24/services/types/experiment_service.py @@ -0,0 +1,406 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import ( + experiment as gagr_experiment, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateExperimentsRequest", + "ExperimentOperation", + "MutateExperimentsResponse", + "MutateExperimentResult", + "EndExperimentRequest", + "ListExperimentAsyncErrorsRequest", + "ListExperimentAsyncErrorsResponse", + "GraduateExperimentRequest", + "CampaignBudgetMapping", + "ScheduleExperimentRequest", + "ScheduleExperimentMetadata", + "PromoteExperimentRequest", + "PromoteExperimentMetadata", + }, +) + + +class MutateExperimentsRequest(proto.Message): + r"""Request message for + [ExperimentService.MutateExperiments][google.ads.googleads.v24.services.ExperimentService.MutateExperiments]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + experiments are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.ExperimentOperation]): + Required. The list of operations to perform + on individual experiments. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["ExperimentOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ExperimentOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class ExperimentOperation(proto.Message): + r"""A single operation on an experiment. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.Experiment): + Create operation + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.Experiment): + Update operation: The experiment is expected + to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: The experiment is expected to have a valid + resource name, in this format: + + ``customers/{customer_id}/experiments/{campaign_experiment_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_experiment.Experiment = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_experiment.Experiment, + ) + update: gagr_experiment.Experiment = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_experiment.Experiment, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateExperimentsResponse(proto.Message): + r"""Response message for experiment mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateExperimentResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + results: MutableSequence["MutateExperimentResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateExperimentResult", + ) + + +class MutateExperimentResult(proto.Message): + r"""The result for the campaign experiment mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class EndExperimentRequest(proto.Message): + r"""Request message for + [ExperimentService.EndExperiment][google.ads.googleads.v24.services.ExperimentService.EndExperiment]. + + Attributes: + experiment (str): + Required. The resource name of the campaign + experiment to end. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + experiment: str = proto.Field( + proto.STRING, + number=1, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=2, + ) + + +class ListExperimentAsyncErrorsRequest(proto.Message): + r"""Request message for + [ExperimentService.ListExperimentAsyncErrors][google.ads.googleads.v24.services.ExperimentService.ListExperimentAsyncErrors]. + + Attributes: + resource_name (str): + Required. The name of the experiment from + which to retrieve the async errors. + page_token (str): + Token of the page to retrieve. If not specified, the first + page of results will be returned. Use the value obtained + from ``next_page_token`` in the previous response in order + to request the next page of results. + page_size (int): + Number of elements to retrieve in a single + page. When a page request is too large, the + server may decide to further limit the number of + returned resources. The maximum page size is + 1000. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + page_token: str = proto.Field( + proto.STRING, + number=2, + ) + page_size: int = proto.Field( + proto.INT32, + number=3, + ) + + +class ListExperimentAsyncErrorsResponse(proto.Message): + r"""Response message for + [ExperimentService.ListExperimentAsyncErrors][google.ads.googleads.v24.services.ExperimentService.ListExperimentAsyncErrors]. + + Attributes: + errors (MutableSequence[google.rpc.status_pb2.Status]): + details of the errors when performing the + asynchronous operation. + next_page_token (str): + Pagination token used to retrieve the next page of results. + Pass the content of this string as the ``page_token`` + attribute of the next request. ``next_page_token`` is not + returned for the last page. + """ + + @property + def raw_page(self): + return self + + errors: MutableSequence[status_pb2.Status] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + next_page_token: str = proto.Field( + proto.STRING, + number=2, + ) + + +class GraduateExperimentRequest(proto.Message): + r"""Request message for + [ExperimentService.GraduateExperiment][google.ads.googleads.v24.services.ExperimentService.GraduateExperiment]. + + Attributes: + experiment (str): + Required. The experiment to be graduated. + campaign_budget_mappings (MutableSequence[google.ads.googleads.v24.services.types.CampaignBudgetMapping]): + Required. List of campaign budget mappings + for graduation. Each campaign that appears here + will graduate, and will be assigned a new budget + that is paired with it in the mapping. The + maximum size is one. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + experiment: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_budget_mappings: MutableSequence["CampaignBudgetMapping"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignBudgetMapping", + ) + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class CampaignBudgetMapping(proto.Message): + r"""The mapping of experiment campaign and budget to be + graduated. + + Attributes: + experiment_campaign (str): + Required. The experiment campaign to + graduate. + campaign_budget (str): + Required. The budget that should be attached + to the graduating experiment campaign. + """ + + experiment_campaign: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_budget: str = proto.Field( + proto.STRING, + number=2, + ) + + +class ScheduleExperimentRequest(proto.Message): + r"""Request message for + [ExperimentService.ScheduleExperiment][google.ads.googleads.v24.services.ExperimentService.ScheduleExperiment]. + + Attributes: + resource_name (str): + Required. The scheduled experiment. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=2, + ) + + +class ScheduleExperimentMetadata(proto.Message): + r"""The metadata of the scheduled experiment. + + Attributes: + experiment (str): + Required. The scheduled experiment. + """ + + experiment: str = proto.Field( + proto.STRING, + number=1, + ) + + +class PromoteExperimentRequest(proto.Message): + r"""Request message for + [ExperimentService.PromoteExperiment][google.ads.googleads.v24.services.ExperimentService.PromoteExperiment]. + + Attributes: + resource_name (str): + Required. The resource name of the experiment + to promote. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=2, + ) + + +class PromoteExperimentMetadata(proto.Message): + r"""The metadata of the promoted experiment. + + Attributes: + experiment (str): + Required. The promoted experiment. + """ + + experiment: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/geo_target_constant_service.py b/google/ads/googleads/v24/services/types/geo_target_constant_service.py new file mode 100644 index 000000000..2632596a8 --- /dev/null +++ b/google/ads/googleads/v24/services/types/geo_target_constant_service.py @@ -0,0 +1,207 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import ( + geo_target_constant as gagr_geo_target_constant, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "SuggestGeoTargetConstantsRequest", + "SuggestGeoTargetConstantsResponse", + "GeoTargetConstantSuggestion", + }, +) + + +class SuggestGeoTargetConstantsRequest(proto.Message): + r"""Request message for + [GeoTargetConstantService.SuggestGeoTargetConstants][google.ads.googleads.v24.services.GeoTargetConstantService.SuggestGeoTargetConstants]. + + 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: + locale (str): + If possible, returned geo targets are + translated using this locale. If not, en is used + by default. This is also used as a hint for + returned geo targets. + + This field is a member of `oneof`_ ``_locale``. + country_code (str): + Returned geo targets are restricted to this + country code. + + This field is a member of `oneof`_ ``_country_code``. + location_names (google.ads.googleads.v24.services.types.SuggestGeoTargetConstantsRequest.LocationNames): + The location names to search by. At most 25 + names can be set. + + This field is a member of `oneof`_ ``query``. + geo_targets (google.ads.googleads.v24.services.types.SuggestGeoTargetConstantsRequest.GeoTargets): + The geo target constant resource names to + filter by. + + This field is a member of `oneof`_ ``query``. + """ + + class LocationNames(proto.Message): + r"""A list of location names. + + Attributes: + names (MutableSequence[str]): + A list of location names. + """ + + names: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + + class GeoTargets(proto.Message): + r"""A list of geo target constant resource names. + + Attributes: + geo_target_constants (MutableSequence[str]): + A list of geo target constant resource names. + """ + + geo_target_constants: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + + locale: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + country_code: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + location_names: LocationNames = proto.Field( + proto.MESSAGE, + number=1, + oneof="query", + message=LocationNames, + ) + geo_targets: GeoTargets = proto.Field( + proto.MESSAGE, + number=2, + oneof="query", + message=GeoTargets, + ) + + +class SuggestGeoTargetConstantsResponse(proto.Message): + r"""Response message for + [GeoTargetConstantService.SuggestGeoTargetConstants][google.ads.googleads.v24.services.GeoTargetConstantService.SuggestGeoTargetConstants]. + + Attributes: + geo_target_constant_suggestions (MutableSequence[google.ads.googleads.v24.services.types.GeoTargetConstantSuggestion]): + Geo target constant suggestions. + """ + + geo_target_constant_suggestions: MutableSequence[ + "GeoTargetConstantSuggestion" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="GeoTargetConstantSuggestion", + ) + + +class GeoTargetConstantSuggestion(proto.Message): + r"""A geo target constant suggestion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + locale (str): + The language this GeoTargetConstantSuggestion + is currently translated to. It affects the name + of geo target fields. For example, if locale=en, + then name=Spain. If locale=es, then name=España. + The default locale will be returned if no + translation exists for the locale in the + request. + + This field is a member of `oneof`_ ``_locale``. + reach (int): + Approximate user population that will be + targeted, rounded to the nearest 100. + + This field is a member of `oneof`_ ``_reach``. + search_term (str): + If the request searched by location name, + this is the location name that matched the geo + target. + + This field is a member of `oneof`_ ``_search_term``. + geo_target_constant (google.ads.googleads.v24.resources.types.GeoTargetConstant): + The GeoTargetConstant result. + geo_target_constant_parents (MutableSequence[google.ads.googleads.v24.resources.types.GeoTargetConstant]): + The list of parents of the geo target + constant. + """ + + locale: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + reach: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + search_term: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + geo_target_constant: gagr_geo_target_constant.GeoTargetConstant = ( + proto.Field( + proto.MESSAGE, + number=4, + message=gagr_geo_target_constant.GeoTargetConstant, + ) + ) + geo_target_constant_parents: MutableSequence[ + gagr_geo_target_constant.GeoTargetConstant + ] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message=gagr_geo_target_constant.GeoTargetConstant, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/goal_service.py b/google/ads/googleads/v24/services/types/goal_service.py new file mode 100644 index 000000000..ad15f7ed3 --- /dev/null +++ b/google/ads/googleads/v24/services/types/goal_service.py @@ -0,0 +1,161 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import goal +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateGoalsRequest", + "GoalOperation", + "MutateGoalsResponse", + "MutateGoalResult", + }, +) + + +class MutateGoalsRequest(proto.Message): + r"""Request message for + [GoalService.MutateGoals][google.ads.googleads.v24.services.GoalService.MutateGoals]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose goals + are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.GoalOperation]): + Required. The list of operations to perform + on the goals. + partial_failure (bool): + Optional. If true, successful operations will + be carried out and invalid operations will + return errors. If false, all operations will be + carried out in one transaction if and only if + they are all valid. Default is false. + validate_only (bool): + Optional. If true, the request is validated + but not executed. Only errors are returned, not + results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["GoalOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="GoalOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class GoalOperation(proto.Message): + r"""A single mutate operation on the goal. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.Goal): + Create a new goal. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.Goal): + Update an existing goal. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=3, + message=field_mask_pb2.FieldMask, + ) + create: goal.Goal = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=goal.Goal, + ) + update: goal.Goal = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=goal.Goal, + ) + + +class MutateGoalsResponse(proto.Message): + r"""Response message for a goal mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in + the partial failure mode. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateGoalResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + results: MutableSequence["MutateGoalResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateGoalResult", + ) + + +class MutateGoalResult(proto.Message): + r"""The result for the goal mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/google_ads_field_service.py b/google/ads/googleads/v24/services/types/google_ads_field_service.py new file mode 100644 index 000000000..7a5937c1e --- /dev/null +++ b/google/ads/googleads/v24/services/types/google_ads_field_service.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import google_ads_field + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "GetGoogleAdsFieldRequest", + "SearchGoogleAdsFieldsRequest", + "SearchGoogleAdsFieldsResponse", + }, +) + + +class GetGoogleAdsFieldRequest(proto.Message): + r"""Request message for + [GoogleAdsFieldService.GetGoogleAdsField][google.ads.googleads.v24.services.GoogleAdsFieldService.GetGoogleAdsField]. + + Attributes: + resource_name (str): + Required. The resource name of the field to + get. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class SearchGoogleAdsFieldsRequest(proto.Message): + r"""Request message for + [GoogleAdsFieldService.SearchGoogleAdsFields][google.ads.googleads.v24.services.GoogleAdsFieldService.SearchGoogleAdsFields]. + + Attributes: + query (str): + Required. The query string. + page_token (str): + Token of the page to retrieve. If not specified, the first + page of results will be returned. Use the value obtained + from ``next_page_token`` in the previous response in order + to request the next page of results. + page_size (int): + Number of elements to retrieve in a single + page. When too large a page is requested, the + server may decide to further limit the number of + returned resources. + """ + + query: str = proto.Field( + proto.STRING, + number=1, + ) + page_token: str = proto.Field( + proto.STRING, + number=2, + ) + page_size: int = proto.Field( + proto.INT32, + number=3, + ) + + +class SearchGoogleAdsFieldsResponse(proto.Message): + r"""Response message for + [GoogleAdsFieldService.SearchGoogleAdsFields][google.ads.googleads.v24.services.GoogleAdsFieldService.SearchGoogleAdsFields]. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.resources.types.GoogleAdsField]): + The list of fields that matched the query. + next_page_token (str): + Pagination token used to retrieve the next page of results. + Pass the content of this string as the ``page_token`` + attribute of the next request. ``next_page_token`` is not + returned for the last page. + total_results_count (int): + Total number of results that match the query + ignoring the LIMIT clause. + """ + + @property + def raw_page(self): + return self + + results: MutableSequence[google_ads_field.GoogleAdsField] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=google_ads_field.GoogleAdsField, + ) + ) + next_page_token: str = proto.Field( + proto.STRING, + number=2, + ) + total_results_count: int = proto.Field( + proto.INT64, + number=3, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/google_ads_service.py b/google/ads/googleads/v24/services/types/google_ads_service.py new file mode 100644 index 000000000..4c8c9df15 --- /dev/null +++ b/google/ads/googleads/v24/services/types/google_ads_service.py @@ -0,0 +1,4209 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.actions.types import book_campaigns +from google.ads.googleads.v24.actions.types import quote_campaigns +from google.ads.googleads.v24.common.types import metrics as gagc_metrics +from google.ads.googleads.v24.common.types import segments as gagc_segments +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.enums.types import ( + summary_row_setting as gage_summary_row_setting, +) +from google.ads.googleads.v24.resources.types import ( + accessible_bidding_strategy as gagr_accessible_bidding_strategy, +) +from google.ads.googleads.v24.resources.types import ( + account_budget as gagr_account_budget, +) +from google.ads.googleads.v24.resources.types import ( + account_budget_proposal as gagr_account_budget_proposal, +) +from google.ads.googleads.v24.resources.types import ( + account_link as gagr_account_link, +) +from google.ads.googleads.v24.resources.types import ad as gagr_ad +from google.ads.googleads.v24.resources.types import ad_group as gagr_ad_group +from google.ads.googleads.v24.resources.types import ( + ad_group_ad as gagr_ad_group_ad, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_ad_asset_combination_view as gagr_ad_group_ad_asset_combination_view, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_ad_asset_view as gagr_ad_group_ad_asset_view, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_ad_label as gagr_ad_group_ad_label, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_asset as gagr_ad_group_asset, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_asset_set as gagr_ad_group_asset_set, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_audience_view as gagr_ad_group_audience_view, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_bid_modifier as gagr_ad_group_bid_modifier, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_criterion as gagr_ad_group_criterion, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_criterion_customizer as gagr_ad_group_criterion_customizer, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_criterion_label as gagr_ad_group_criterion_label, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_criterion_simulation as gagr_ad_group_criterion_simulation, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_customizer as gagr_ad_group_customizer, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_label as gagr_ad_group_label, +) +from google.ads.googleads.v24.resources.types import ( + ad_group_simulation as gagr_ad_group_simulation, +) +from google.ads.googleads.v24.resources.types import ( + ad_parameter as gagr_ad_parameter, +) +from google.ads.googleads.v24.resources.types import ( + ad_schedule_view as gagr_ad_schedule_view, +) +from google.ads.googleads.v24.resources.types import ( + age_range_view as gagr_age_range_view, +) +from google.ads.googleads.v24.resources.types import ( + ai_max_search_term_ad_combination_view as gagr_ai_max_search_term_ad_combination_view, +) +from google.ads.googleads.v24.resources.types import ( + android_privacy_shared_key_google_ad_group as gagr_android_privacy_shared_key_google_ad_group, +) +from google.ads.googleads.v24.resources.types import ( + android_privacy_shared_key_google_campaign as gagr_android_privacy_shared_key_google_campaign, +) +from google.ads.googleads.v24.resources.types import ( + android_privacy_shared_key_google_network_type as gagr_android_privacy_shared_key_google_network_type, +) +from google.ads.googleads.v24.resources.types import ( + app_top_combination_view as gagr_app_top_combination_view, +) +from google.ads.googleads.v24.resources.types import ( + applied_incentive as gagr_applied_incentive, +) +from google.ads.googleads.v24.resources.types import asset as gagr_asset +from google.ads.googleads.v24.resources.types import ( + asset_field_type_view as gagr_asset_field_type_view, +) +from google.ads.googleads.v24.resources.types import ( + asset_group as gagr_asset_group, +) +from google.ads.googleads.v24.resources.types import ( + asset_group_asset as gagr_asset_group_asset, +) +from google.ads.googleads.v24.resources.types import ( + asset_group_listing_group_filter as gagr_asset_group_listing_group_filter, +) +from google.ads.googleads.v24.resources.types import ( + asset_group_product_group_view as gagr_asset_group_product_group_view, +) +from google.ads.googleads.v24.resources.types import ( + asset_group_signal as gagr_asset_group_signal, +) +from google.ads.googleads.v24.resources.types import ( + asset_group_top_combination_view as gagr_asset_group_top_combination_view, +) +from google.ads.googleads.v24.resources.types import asset_set as gagr_asset_set +from google.ads.googleads.v24.resources.types import ( + asset_set_asset as gagr_asset_set_asset, +) +from google.ads.googleads.v24.resources.types import ( + asset_set_type_view as gagr_asset_set_type_view, +) +from google.ads.googleads.v24.resources.types import audience as gagr_audience +from google.ads.googleads.v24.resources.types import batch_job as gagr_batch_job +from google.ads.googleads.v24.resources.types import ( + bidding_data_exclusion as gagr_bidding_data_exclusion, +) +from google.ads.googleads.v24.resources.types import ( + bidding_seasonality_adjustment as gagr_bidding_seasonality_adjustment, +) +from google.ads.googleads.v24.resources.types import ( + bidding_strategy as gagr_bidding_strategy, +) +from google.ads.googleads.v24.resources.types import ( + bidding_strategy_simulation as gagr_bidding_strategy_simulation, +) +from google.ads.googleads.v24.resources.types import ( + billing_setup as gagr_billing_setup, +) +from google.ads.googleads.v24.resources.types import call_view as gagr_call_view +from google.ads.googleads.v24.resources.types import campaign as gagr_campaign +from google.ads.googleads.v24.resources.types import ( + campaign_aggregate_asset_view as gagr_campaign_aggregate_asset_view, +) +from google.ads.googleads.v24.resources.types import ( + campaign_asset as gagr_campaign_asset, +) +from google.ads.googleads.v24.resources.types import ( + campaign_asset_set as gagr_campaign_asset_set, +) +from google.ads.googleads.v24.resources.types import ( + campaign_audience_view as gagr_campaign_audience_view, +) +from google.ads.googleads.v24.resources.types import ( + campaign_bid_modifier as gagr_campaign_bid_modifier, +) +from google.ads.googleads.v24.resources.types import ( + campaign_budget as gagr_campaign_budget, +) +from google.ads.googleads.v24.resources.types import ( + campaign_conversion_goal as gagr_campaign_conversion_goal, +) +from google.ads.googleads.v24.resources.types import ( + campaign_criterion as gagr_campaign_criterion, +) +from google.ads.googleads.v24.resources.types import ( + campaign_customizer as gagr_campaign_customizer, +) +from google.ads.googleads.v24.resources.types import ( + campaign_draft as gagr_campaign_draft, +) +from google.ads.googleads.v24.resources.types import ( + campaign_goal_config as gagr_campaign_goal_config, +) +from google.ads.googleads.v24.resources.types import ( + campaign_group as gagr_campaign_group, +) +from google.ads.googleads.v24.resources.types import ( + campaign_label as gagr_campaign_label, +) +from google.ads.googleads.v24.resources.types import ( + campaign_lifecycle_goal as gagr_campaign_lifecycle_goal, +) +from google.ads.googleads.v24.resources.types import ( + campaign_search_term_insight as gagr_campaign_search_term_insight, +) +from google.ads.googleads.v24.resources.types import ( + campaign_search_term_view as gagr_campaign_search_term_view, +) +from google.ads.googleads.v24.resources.types import ( + campaign_shared_set as gagr_campaign_shared_set, +) +from google.ads.googleads.v24.resources.types import ( + campaign_simulation as gagr_campaign_simulation, +) +from google.ads.googleads.v24.resources.types import ( + carrier_constant as gagr_carrier_constant, +) +from google.ads.googleads.v24.resources.types import ( + cart_data_sales_view as gagr_cart_data_sales_view, +) +from google.ads.googleads.v24.resources.types import ( + change_event as gagr_change_event, +) +from google.ads.googleads.v24.resources.types import ( + change_status as gagr_change_status, +) +from google.ads.googleads.v24.resources.types import ( + channel_aggregate_asset_view as gagr_channel_aggregate_asset_view, +) +from google.ads.googleads.v24.resources.types import ( + click_view as gagr_click_view, +) +from google.ads.googleads.v24.resources.types import ( + combined_audience as gagr_combined_audience, +) +from google.ads.googleads.v24.resources.types import ( + content_criterion_view as gagr_content_criterion_view, +) +from google.ads.googleads.v24.resources.types import ( + conversion_action as gagr_conversion_action, +) +from google.ads.googleads.v24.resources.types import ( + conversion_custom_variable as gagr_conversion_custom_variable, +) +from google.ads.googleads.v24.resources.types import ( + conversion_goal_campaign_config as gagr_conversion_goal_campaign_config, +) +from google.ads.googleads.v24.resources.types import ( + conversion_value_rule as gagr_conversion_value_rule, +) +from google.ads.googleads.v24.resources.types import ( + conversion_value_rule_set as gagr_conversion_value_rule_set, +) +from google.ads.googleads.v24.resources.types import ( + currency_constant as gagr_currency_constant, +) +from google.ads.googleads.v24.resources.types import ( + custom_audience as gagr_custom_audience, +) +from google.ads.googleads.v24.resources.types import ( + custom_conversion_goal as gagr_custom_conversion_goal, +) +from google.ads.googleads.v24.resources.types import ( + custom_interest as gagr_custom_interest, +) +from google.ads.googleads.v24.resources.types import customer as gagr_customer +from google.ads.googleads.v24.resources.types import ( + customer_asset as gagr_customer_asset, +) +from google.ads.googleads.v24.resources.types import ( + customer_asset_set as gagr_customer_asset_set, +) +from google.ads.googleads.v24.resources.types import ( + customer_client as gagr_customer_client, +) +from google.ads.googleads.v24.resources.types import ( + customer_client_link as gagr_customer_client_link, +) +from google.ads.googleads.v24.resources.types import ( + customer_conversion_goal as gagr_customer_conversion_goal, +) +from google.ads.googleads.v24.resources.types import ( + customer_customizer as gagr_customer_customizer, +) +from google.ads.googleads.v24.resources.types import ( + customer_label as gagr_customer_label, +) +from google.ads.googleads.v24.resources.types import ( + customer_lifecycle_goal as gagr_customer_lifecycle_goal, +) +from google.ads.googleads.v24.resources.types import ( + customer_manager_link as gagr_customer_manager_link, +) +from google.ads.googleads.v24.resources.types import ( + customer_negative_criterion as gagr_customer_negative_criterion, +) +from google.ads.googleads.v24.resources.types import ( + customer_search_term_insight as gagr_customer_search_term_insight, +) +from google.ads.googleads.v24.resources.types import ( + customer_user_access as gagr_customer_user_access, +) +from google.ads.googleads.v24.resources.types import ( + customer_user_access_invitation as gagr_customer_user_access_invitation, +) +from google.ads.googleads.v24.resources.types import ( + customizer_attribute as gagr_customizer_attribute, +) +from google.ads.googleads.v24.resources.types import data_link as gagr_data_link +from google.ads.googleads.v24.resources.types import ( + detail_content_suitability_placement_view as gagr_detail_content_suitability_placement_view, +) +from google.ads.googleads.v24.resources.types import ( + detail_placement_view as gagr_detail_placement_view, +) +from google.ads.googleads.v24.resources.types import ( + detailed_demographic as gagr_detailed_demographic, +) +from google.ads.googleads.v24.resources.types import ( + display_keyword_view as gagr_display_keyword_view, +) +from google.ads.googleads.v24.resources.types import ( + distance_view as gagr_distance_view, +) +from google.ads.googleads.v24.resources.types import ( + domain_category as gagr_domain_category, +) +from google.ads.googleads.v24.resources.types import ( + dynamic_search_ads_search_term_view as gagr_dynamic_search_ads_search_term_view, +) +from google.ads.googleads.v24.resources.types import ( + expanded_landing_page_view as gagr_expanded_landing_page_view, +) +from google.ads.googleads.v24.resources.types import ( + experiment as gagr_experiment, +) +from google.ads.googleads.v24.resources.types import ( + experiment_arm as gagr_experiment_arm, +) +from google.ads.googleads.v24.resources.types import ( + final_url_expansion_asset_view as gagr_final_url_expansion_asset_view, +) +from google.ads.googleads.v24.resources.types import ( + gender_view as gagr_gender_view, +) +from google.ads.googleads.v24.resources.types import ( + geo_target_constant as gagr_geo_target_constant, +) +from google.ads.googleads.v24.resources.types import ( + geographic_view as gagr_geographic_view, +) +from google.ads.googleads.v24.resources.types import goal as gagr_goal +from google.ads.googleads.v24.resources.types import ( + group_content_suitability_placement_view as gagr_group_content_suitability_placement_view, +) +from google.ads.googleads.v24.resources.types import ( + group_placement_view as gagr_group_placement_view, +) +from google.ads.googleads.v24.resources.types import ( + hotel_group_view as gagr_hotel_group_view, +) +from google.ads.googleads.v24.resources.types import ( + hotel_performance_view as gagr_hotel_performance_view, +) +from google.ads.googleads.v24.resources.types import ( + hotel_reconciliation as gagr_hotel_reconciliation, +) +from google.ads.googleads.v24.resources.types import ( + income_range_view as gagr_income_range_view, +) +from google.ads.googleads.v24.resources.types import ( + keyword_plan as gagr_keyword_plan, +) +from google.ads.googleads.v24.resources.types import ( + keyword_plan_ad_group as gagr_keyword_plan_ad_group, +) +from google.ads.googleads.v24.resources.types import ( + keyword_plan_ad_group_keyword as gagr_keyword_plan_ad_group_keyword, +) +from google.ads.googleads.v24.resources.types import ( + keyword_plan_campaign as gagr_keyword_plan_campaign, +) +from google.ads.googleads.v24.resources.types import ( + keyword_plan_campaign_keyword as gagr_keyword_plan_campaign_keyword, +) +from google.ads.googleads.v24.resources.types import ( + keyword_theme_constant as gagr_keyword_theme_constant, +) +from google.ads.googleads.v24.resources.types import ( + keyword_view as gagr_keyword_view, +) +from google.ads.googleads.v24.resources.types import label as gagr_label +from google.ads.googleads.v24.resources.types import ( + landing_page_view as gagr_landing_page_view, +) +from google.ads.googleads.v24.resources.types import ( + language_constant as gagr_language_constant, +) +from google.ads.googleads.v24.resources.types import ( + lead_form_submission_data as gagr_lead_form_submission_data, +) +from google.ads.googleads.v24.resources.types import ( + life_event as gagr_life_event, +) +from google.ads.googleads.v24.resources.types import ( + local_services_employee as gagr_local_services_employee, +) +from google.ads.googleads.v24.resources.types import ( + local_services_lead as gagr_local_services_lead, +) +from google.ads.googleads.v24.resources.types import ( + local_services_lead_conversation as gagr_local_services_lead_conversation, +) +from google.ads.googleads.v24.resources.types import ( + local_services_verification_artifact as gagr_local_services_verification_artifact, +) +from google.ads.googleads.v24.resources.types import ( + location_interest_view as gagr_location_interest_view, +) +from google.ads.googleads.v24.resources.types import ( + location_view as gagr_location_view, +) +from google.ads.googleads.v24.resources.types import ( + managed_placement_view as gagr_managed_placement_view, +) +from google.ads.googleads.v24.resources.types import ( + matched_location_interest_view as gagr_matched_location_interest_view, +) +from google.ads.googleads.v24.resources.types import ( + media_file as gagr_media_file, +) +from google.ads.googleads.v24.resources.types import ( + mobile_app_category_constant as gagr_mobile_app_category_constant, +) +from google.ads.googleads.v24.resources.types import ( + mobile_device_constant as gagr_mobile_device_constant, +) +from google.ads.googleads.v24.resources.types import ( + offline_conversion_upload_client_summary as gagr_offline_conversion_upload_client_summary, +) +from google.ads.googleads.v24.resources.types import ( + offline_conversion_upload_conversion_action_summary as gagr_offline_conversion_upload_conversion_action_summary, +) +from google.ads.googleads.v24.resources.types import ( + offline_user_data_job as gagr_offline_user_data_job, +) +from google.ads.googleads.v24.resources.types import ( + operating_system_version_constant as gagr_operating_system_version_constant, +) +from google.ads.googleads.v24.resources.types import ( + paid_organic_search_term_view as gagr_paid_organic_search_term_view, +) +from google.ads.googleads.v24.resources.types import ( + parental_status_view as gagr_parental_status_view, +) +from google.ads.googleads.v24.resources.types import ( + per_store_view as gagr_per_store_view, +) +from google.ads.googleads.v24.resources.types import ( + performance_max_placement_view as gagr_performance_max_placement_view, +) +from google.ads.googleads.v24.resources.types import ( + product_category_constant as gagr_product_category_constant, +) +from google.ads.googleads.v24.resources.types import ( + product_group_view as gagr_product_group_view, +) +from google.ads.googleads.v24.resources.types import ( + product_link as gagr_product_link, +) +from google.ads.googleads.v24.resources.types import ( + product_link_invitation as gagr_product_link_invitation, +) +from google.ads.googleads.v24.resources.types import ( + qualifying_question as gagr_qualifying_question, +) +from google.ads.googleads.v24.resources.types import ( + recommendation as gagr_recommendation, +) +from google.ads.googleads.v24.resources.types import ( + recommendation_subscription as gagr_recommendation_subscription, +) +from google.ads.googleads.v24.resources.types import ( + remarketing_action as gagr_remarketing_action, +) +from google.ads.googleads.v24.resources.types import ( + search_term_view as gagr_search_term_view, +) +from google.ads.googleads.v24.resources.types import ( + shared_criterion as gagr_shared_criterion, +) +from google.ads.googleads.v24.resources.types import ( + shared_set as gagr_shared_set, +) +from google.ads.googleads.v24.resources.types import ( + shopping_performance_view as gagr_shopping_performance_view, +) +from google.ads.googleads.v24.resources.types import ( + shopping_product as gagr_shopping_product, +) +from google.ads.googleads.v24.resources.types import ( + smart_campaign_search_term_view as gagr_smart_campaign_search_term_view, +) +from google.ads.googleads.v24.resources.types import ( + smart_campaign_setting as gagr_smart_campaign_setting, +) +from google.ads.googleads.v24.resources.types import ( + targeting_expansion_view as gagr_targeting_expansion_view, +) +from google.ads.googleads.v24.resources.types import ( + third_party_app_analytics_link as gagr_third_party_app_analytics_link, +) +from google.ads.googleads.v24.resources.types import ( + topic_constant as gagr_topic_constant, +) +from google.ads.googleads.v24.resources.types import ( + topic_view as gagr_topic_view, +) +from google.ads.googleads.v24.resources.types import ( + travel_activity_group_view as gagr_travel_activity_group_view, +) +from google.ads.googleads.v24.resources.types import ( + travel_activity_performance_view as gagr_travel_activity_performance_view, +) +from google.ads.googleads.v24.resources.types import ( + user_interest as gagr_user_interest, +) +from google.ads.googleads.v24.resources.types import user_list as gagr_user_list +from google.ads.googleads.v24.resources.types import ( + user_list_customer_type as gagr_user_list_customer_type, +) +from google.ads.googleads.v24.resources.types import ( + user_location_view as gagr_user_location_view, +) +from google.ads.googleads.v24.resources.types import video as gagr_video +from google.ads.googleads.v24.resources.types import ( + video_enhancement as gagr_video_enhancement, +) +from google.ads.googleads.v24.resources.types import ( + webpage_view as gagr_webpage_view, +) +from google.ads.googleads.v24.resources.types import youtube_video_upload +from google.ads.googleads.v24.services.types import ad_group_ad_label_service +from google.ads.googleads.v24.services.types import ad_group_ad_service +from google.ads.googleads.v24.services.types import ad_group_asset_service +from google.ads.googleads.v24.services.types import ( + ad_group_bid_modifier_service, +) +from google.ads.googleads.v24.services.types import ( + ad_group_criterion_customizer_service, +) +from google.ads.googleads.v24.services.types import ( + ad_group_criterion_label_service, +) +from google.ads.googleads.v24.services.types import ad_group_criterion_service +from google.ads.googleads.v24.services.types import ad_group_customizer_service +from google.ads.googleads.v24.services.types import ad_group_label_service +from google.ads.googleads.v24.services.types import ad_group_service +from google.ads.googleads.v24.services.types import ad_parameter_service +from google.ads.googleads.v24.services.types import ad_service +from google.ads.googleads.v24.services.types import asset_group_asset_service +from google.ads.googleads.v24.services.types import ( + asset_group_listing_group_filter_service, +) +from google.ads.googleads.v24.services.types import asset_group_service +from google.ads.googleads.v24.services.types import asset_group_signal_service +from google.ads.googleads.v24.services.types import asset_service +from google.ads.googleads.v24.services.types import asset_set_asset_service +from google.ads.googleads.v24.services.types import asset_set_service +from google.ads.googleads.v24.services.types import audience_service +from google.ads.googleads.v24.services.types import ( + bidding_data_exclusion_service, +) +from google.ads.googleads.v24.services.types import ( + bidding_seasonality_adjustment_service, +) +from google.ads.googleads.v24.services.types import bidding_strategy_service +from google.ads.googleads.v24.services.types import campaign_asset_service +from google.ads.googleads.v24.services.types import campaign_asset_set_service +from google.ads.googleads.v24.services.types import ( + campaign_bid_modifier_service, +) +from google.ads.googleads.v24.services.types import campaign_budget_service +from google.ads.googleads.v24.services.types import ( + campaign_conversion_goal_service, +) +from google.ads.googleads.v24.services.types import campaign_criterion_service +from google.ads.googleads.v24.services.types import campaign_customizer_service +from google.ads.googleads.v24.services.types import campaign_draft_service +from google.ads.googleads.v24.services.types import campaign_group_service +from google.ads.googleads.v24.services.types import campaign_label_service +from google.ads.googleads.v24.services.types import campaign_service +from google.ads.googleads.v24.services.types import campaign_shared_set_service +from google.ads.googleads.v24.services.types import conversion_action_service +from google.ads.googleads.v24.services.types import ( + conversion_custom_variable_service, +) +from google.ads.googleads.v24.services.types import ( + conversion_goal_campaign_config_service, +) +from google.ads.googleads.v24.services.types import ( + conversion_value_rule_service, +) +from google.ads.googleads.v24.services.types import ( + conversion_value_rule_set_service, +) +from google.ads.googleads.v24.services.types import ( + custom_conversion_goal_service, +) +from google.ads.googleads.v24.services.types import customer_asset_service +from google.ads.googleads.v24.services.types import ( + customer_conversion_goal_service, +) +from google.ads.googleads.v24.services.types import customer_customizer_service +from google.ads.googleads.v24.services.types import customer_label_service +from google.ads.googleads.v24.services.types import ( + customer_negative_criterion_service, +) +from google.ads.googleads.v24.services.types import customer_service +from google.ads.googleads.v24.services.types import customizer_attribute_service +from google.ads.googleads.v24.services.types import experiment_arm_service +from google.ads.googleads.v24.services.types import experiment_service +from google.ads.googleads.v24.services.types import ( + keyword_plan_ad_group_keyword_service, +) +from google.ads.googleads.v24.services.types import ( + keyword_plan_ad_group_service, +) +from google.ads.googleads.v24.services.types import ( + keyword_plan_campaign_keyword_service, +) +from google.ads.googleads.v24.services.types import ( + keyword_plan_campaign_service, +) +from google.ads.googleads.v24.services.types import keyword_plan_service +from google.ads.googleads.v24.services.types import label_service +from google.ads.googleads.v24.services.types import ( + recommendation_subscription_service, +) +from google.ads.googleads.v24.services.types import remarketing_action_service +from google.ads.googleads.v24.services.types import shared_criterion_service +from google.ads.googleads.v24.services.types import shared_set_service +from google.ads.googleads.v24.services.types import ( + smart_campaign_setting_service, +) +from google.ads.googleads.v24.services.types import user_list_service +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "SearchGoogleAdsRequest", + "SearchGoogleAdsResponse", + "SearchGoogleAdsStreamRequest", + "SearchGoogleAdsStreamResponse", + "GoogleAdsRow", + "MutateGoogleAdsRequest", + "MutateGoogleAdsResponse", + "MutateOperation", + "MutateOperationResponse", + "SearchSettings", + "MetricAttributes", + }, +) + + +class SearchGoogleAdsRequest(proto.Message): + r"""Request message for + [GoogleAdsService.Search][google.ads.googleads.v24.services.GoogleAdsService.Search]. + + Attributes: + customer_id (str): + Required. The ID of the customer being + queried. + query (str): + Required. The query string. + page_token (str): + Token of the page to retrieve. If not specified, the first + page of results will be returned. Use the value obtained + from ``next_page_token`` in the previous response in order + to request the next page of results. + page_size (int): + This field is deprecated and will be removed in a future + version of the API. Google Ads API returns a + ``PAGE_SIZE_NOT_SUPPORTED`` error if this field is set in + the request body. + validate_only (bool): + If true, the request is validated but not + executed. + search_settings (google.ads.googleads.v24.services.types.SearchSettings): + Settings that allow users to specify request + count, summary row, and results behavior. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + query: str = proto.Field( + proto.STRING, + number=2, + ) + page_token: str = proto.Field( + proto.STRING, + number=3, + ) + page_size: int = proto.Field( + proto.INT32, + number=4, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=5, + ) + search_settings: "SearchSettings" = proto.Field( + proto.MESSAGE, + number=10, + message="SearchSettings", + ) + + +class SearchGoogleAdsResponse(proto.Message): + r"""Response message for + [GoogleAdsService.Search][google.ads.googleads.v24.services.GoogleAdsService.Search]. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.GoogleAdsRow]): + The list of rows that matched the query. + next_page_token (str): + Pagination token used to retrieve the next page of results. + Pass the content of this string as the ``page_token`` + attribute of the next request. ``next_page_token`` is not + returned for the last page. + total_results_count (int): + Total number of results that match the query + ignoring the LIMIT clause. + field_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that represents what fields were + requested by the user. + summary_row (google.ads.googleads.v24.services.types.GoogleAdsRow): + Summary row that contains summary of metrics + in results. Summary of metrics means aggregation + of metrics across all results, here aggregation + could be sum, average, rate, etc. + query_resource_consumption (int): + The amount of resources consumed to serve the + query. + metric_attributes (MutableSequence[google.ads.googleads.v24.services.types.MetricAttributes]): + The metric attributes of the metrics in the + results. + """ + + @property + def raw_page(self): + return self + + results: MutableSequence["GoogleAdsRow"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="GoogleAdsRow", + ) + next_page_token: str = proto.Field( + proto.STRING, + number=2, + ) + total_results_count: int = proto.Field( + proto.INT64, + number=3, + ) + field_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=5, + message=field_mask_pb2.FieldMask, + ) + summary_row: "GoogleAdsRow" = proto.Field( + proto.MESSAGE, + number=6, + message="GoogleAdsRow", + ) + query_resource_consumption: int = proto.Field( + proto.INT64, + number=8, + ) + metric_attributes: MutableSequence["MetricAttributes"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=13, + message="MetricAttributes", + ) + ) + + +class SearchGoogleAdsStreamRequest(proto.Message): + r"""Request message for + [GoogleAdsService.SearchStream][google.ads.googleads.v24.services.GoogleAdsService.SearchStream]. + + Attributes: + customer_id (str): + Required. The ID of the customer being + queried. + query (str): + Required. The query string. + summary_row_setting (google.ads.googleads.v24.enums.types.SummaryRowSettingEnum.SummaryRowSetting): + Determines whether a summary row will be + returned. By default, summary row is not + returned. If requested, the summary row will be + sent in a response by itself after all other + query results are returned. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + query: str = proto.Field( + proto.STRING, + number=2, + ) + summary_row_setting: ( + gage_summary_row_setting.SummaryRowSettingEnum.SummaryRowSetting + ) = proto.Field( + proto.ENUM, + number=3, + enum=gage_summary_row_setting.SummaryRowSettingEnum.SummaryRowSetting, + ) + + +class SearchGoogleAdsStreamResponse(proto.Message): + r"""Response message for + [GoogleAdsService.SearchStream][google.ads.googleads.v24.services.GoogleAdsService.SearchStream]. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.GoogleAdsRow]): + The list of rows that matched the query. + field_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that represents what fields were + requested by the user. + summary_row (google.ads.googleads.v24.services.types.GoogleAdsRow): + Summary row that contains summary of metrics + in results. Summary of metrics means aggregation + of metrics across all results, here aggregation + could be sum, average, rate, etc. + request_id (str): + The unique id of the request that is used for + debugging purposes. + query_resource_consumption (int): + The amount of resources consumed to serve the query. + query_resource_consumption for the Summary row and + non-Summary responses are returned separately in their + respective rows. query_resource_consumption for non-Summary + responses is returned in the final batch of results. + metric_attributes (MutableSequence[google.ads.googleads.v24.services.types.MetricAttributes]): + The metric attributes of the metrics in the + results. + """ + + results: MutableSequence["GoogleAdsRow"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="GoogleAdsRow", + ) + field_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=2, + message=field_mask_pb2.FieldMask, + ) + summary_row: "GoogleAdsRow" = proto.Field( + proto.MESSAGE, + number=3, + message="GoogleAdsRow", + ) + request_id: str = proto.Field( + proto.STRING, + number=4, + ) + query_resource_consumption: int = proto.Field( + proto.INT64, + number=6, + ) + metric_attributes: MutableSequence["MetricAttributes"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=11, + message="MetricAttributes", + ) + ) + + +class GoogleAdsRow(proto.Message): + r"""A returned row from the query. + + Attributes: + account_budget (google.ads.googleads.v24.resources.types.AccountBudget): + The account budget in the query. + account_budget_proposal (google.ads.googleads.v24.resources.types.AccountBudgetProposal): + The account budget proposal referenced in the + query. + account_link (google.ads.googleads.v24.resources.types.AccountLink): + The AccountLink referenced in the query. + ad (google.ads.googleads.v24.resources.types.Ad): + The Ad referenced in the query. + ad_group (google.ads.googleads.v24.resources.types.AdGroup): + The ad group referenced in the query. + ad_group_ad (google.ads.googleads.v24.resources.types.AdGroupAd): + The ad referenced in the query. + ad_group_ad_asset_combination_view (google.ads.googleads.v24.resources.types.AdGroupAdAssetCombinationView): + The ad group ad asset combination view in the + query. + app_top_combination_view (google.ads.googleads.v24.resources.types.AppTopCombinationView): + The app top combination view in the query. + ad_group_ad_asset_view (google.ads.googleads.v24.resources.types.AdGroupAdAssetView): + The ad group ad asset view in the query. + ad_group_ad_label (google.ads.googleads.v24.resources.types.AdGroupAdLabel): + The ad group ad label referenced in the + query. + ad_group_asset (google.ads.googleads.v24.resources.types.AdGroupAsset): + The ad group asset referenced in the query. + ad_group_asset_set (google.ads.googleads.v24.resources.types.AdGroupAssetSet): + The ad group asset set referenced in the + query. + ad_group_audience_view (google.ads.googleads.v24.resources.types.AdGroupAudienceView): + The ad group audience view referenced in the + query. + ad_group_bid_modifier (google.ads.googleads.v24.resources.types.AdGroupBidModifier): + The bid modifier referenced in the query. + ad_group_criterion (google.ads.googleads.v24.resources.types.AdGroupCriterion): + The criterion referenced in the query. + ad_group_criterion_customizer (google.ads.googleads.v24.resources.types.AdGroupCriterionCustomizer): + The ad group criterion customizer referenced + in the query. + ad_group_criterion_label (google.ads.googleads.v24.resources.types.AdGroupCriterionLabel): + The ad group criterion label referenced in + the query. + ad_group_criterion_simulation (google.ads.googleads.v24.resources.types.AdGroupCriterionSimulation): + The ad group criterion simulation referenced + in the query. + ad_group_customizer (google.ads.googleads.v24.resources.types.AdGroupCustomizer): + The ad group customizer referenced in the + query. + ad_group_label (google.ads.googleads.v24.resources.types.AdGroupLabel): + The ad group label referenced in the query. + ad_group_simulation (google.ads.googleads.v24.resources.types.AdGroupSimulation): + The ad group simulation referenced in the + query. + ad_parameter (google.ads.googleads.v24.resources.types.AdParameter): + The ad parameter referenced in the query. + age_range_view (google.ads.googleads.v24.resources.types.AgeRangeView): + The age range view referenced in the query. + ad_schedule_view (google.ads.googleads.v24.resources.types.AdScheduleView): + The ad schedule view referenced in the query. + ai_max_search_term_ad_combination_view (google.ads.googleads.v24.resources.types.AiMaxSearchTermAdCombinationView): + The AI Max search term ad combination view + referenced in the query. + domain_category (google.ads.googleads.v24.resources.types.DomainCategory): + The domain category referenced in the query. + asset (google.ads.googleads.v24.resources.types.Asset): + The asset referenced in the query. + asset_field_type_view (google.ads.googleads.v24.resources.types.AssetFieldTypeView): + The asset field type view referenced in the + query. + channel_aggregate_asset_view (google.ads.googleads.v24.resources.types.ChannelAggregateAssetView): + The channel aggregate asset view referenced + in the query. + campaign_aggregate_asset_view (google.ads.googleads.v24.resources.types.CampaignAggregateAssetView): + The campaign aggregate asset view referenced + in the query. + asset_group_asset (google.ads.googleads.v24.resources.types.AssetGroupAsset): + The asset group asset referenced in the + query. + asset_group_signal (google.ads.googleads.v24.resources.types.AssetGroupSignal): + The asset group signal referenced in the + query. + asset_group_listing_group_filter (google.ads.googleads.v24.resources.types.AssetGroupListingGroupFilter): + The asset group listing group filter + referenced in the query. + asset_group_product_group_view (google.ads.googleads.v24.resources.types.AssetGroupProductGroupView): + The asset group product group view referenced + in the query. + asset_group_top_combination_view (google.ads.googleads.v24.resources.types.AssetGroupTopCombinationView): + The asset group top combination view + referenced in the query. + asset_group (google.ads.googleads.v24.resources.types.AssetGroup): + The asset group referenced in the query. + asset_set_asset (google.ads.googleads.v24.resources.types.AssetSetAsset): + The asset set asset referenced in the query. + asset_set (google.ads.googleads.v24.resources.types.AssetSet): + The asset set referenced in the query. + asset_set_type_view (google.ads.googleads.v24.resources.types.AssetSetTypeView): + The asset set type view referenced in the + query. + batch_job (google.ads.googleads.v24.resources.types.BatchJob): + The batch job referenced in the query. + bidding_data_exclusion (google.ads.googleads.v24.resources.types.BiddingDataExclusion): + The bidding data exclusion referenced in the + query. + bidding_seasonality_adjustment (google.ads.googleads.v24.resources.types.BiddingSeasonalityAdjustment): + The bidding seasonality adjustment referenced + in the query. + bidding_strategy (google.ads.googleads.v24.resources.types.BiddingStrategy): + The bidding strategy referenced in the query. + bidding_strategy_simulation (google.ads.googleads.v24.resources.types.BiddingStrategySimulation): + The bidding strategy simulation referenced in + the query. + billing_setup (google.ads.googleads.v24.resources.types.BillingSetup): + The billing setup referenced in the query. + call_view (google.ads.googleads.v24.resources.types.CallView): + The call view referenced in the query. + campaign_budget (google.ads.googleads.v24.resources.types.CampaignBudget): + The campaign budget referenced in the query. + campaign (google.ads.googleads.v24.resources.types.Campaign): + The campaign referenced in the query. + campaign_asset (google.ads.googleads.v24.resources.types.CampaignAsset): + The campaign asset referenced in the query. + campaign_asset_set (google.ads.googleads.v24.resources.types.CampaignAssetSet): + The campaign asset set referenced in the + query. + campaign_audience_view (google.ads.googleads.v24.resources.types.CampaignAudienceView): + The campaign audience view referenced in the + query. + campaign_bid_modifier (google.ads.googleads.v24.resources.types.CampaignBidModifier): + The campaign bid modifier referenced in the + query. + campaign_conversion_goal (google.ads.googleads.v24.resources.types.CampaignConversionGoal): + The CampaignConversionGoal referenced in the + query. + campaign_criterion (google.ads.googleads.v24.resources.types.CampaignCriterion): + The campaign criterion referenced in the + query. + campaign_customizer (google.ads.googleads.v24.resources.types.CampaignCustomizer): + The campaign customizer referenced in the + query. + campaign_draft (google.ads.googleads.v24.resources.types.CampaignDraft): + The campaign draft referenced in the query. + campaign_group (google.ads.googleads.v24.resources.types.CampaignGroup): + Campaign Group referenced in AWQL query. + campaign_goal_config (google.ads.googleads.v24.resources.types.CampaignGoalConfig): + The campaign goal config referenced in the + query. + campaign_label (google.ads.googleads.v24.resources.types.CampaignLabel): + The campaign label referenced in the query. + campaign_lifecycle_goal (google.ads.googleads.v24.resources.types.CampaignLifecycleGoal): + The campaign lifecycle goal referenced in the + query. + campaign_search_term_insight (google.ads.googleads.v24.resources.types.CampaignSearchTermInsight): + The campaign search term insight referenced + in the query. + campaign_search_term_view (google.ads.googleads.v24.resources.types.CampaignSearchTermView): + The campaign-level search term view + referenced in the query. + campaign_shared_set (google.ads.googleads.v24.resources.types.CampaignSharedSet): + Campaign Shared Set referenced in AWQL query. + campaign_simulation (google.ads.googleads.v24.resources.types.CampaignSimulation): + The campaign simulation referenced in the + query. + carrier_constant (google.ads.googleads.v24.resources.types.CarrierConstant): + The carrier constant referenced in the query. + cart_data_sales_view (google.ads.googleads.v24.resources.types.CartDataSalesView): + The cart data sales view referenced in the + query. + change_event (google.ads.googleads.v24.resources.types.ChangeEvent): + The ChangeEvent referenced in the query. + change_status (google.ads.googleads.v24.resources.types.ChangeStatus): + The ChangeStatus referenced in the query. + combined_audience (google.ads.googleads.v24.resources.types.CombinedAudience): + The CombinedAudience referenced in the query. + audience (google.ads.googleads.v24.resources.types.Audience): + The Audience referenced in the query. + conversion_action (google.ads.googleads.v24.resources.types.ConversionAction): + The conversion action referenced in the + query. + conversion_custom_variable (google.ads.googleads.v24.resources.types.ConversionCustomVariable): + The conversion custom variable referenced in + the query. + conversion_goal_campaign_config (google.ads.googleads.v24.resources.types.ConversionGoalCampaignConfig): + The ConversionGoalCampaignConfig referenced + in the query. + conversion_value_rule (google.ads.googleads.v24.resources.types.ConversionValueRule): + The conversion value rule referenced in the + query. + conversion_value_rule_set (google.ads.googleads.v24.resources.types.ConversionValueRuleSet): + The conversion value rule set referenced in + the query. + click_view (google.ads.googleads.v24.resources.types.ClickView): + The ClickView referenced in the query. + currency_constant (google.ads.googleads.v24.resources.types.CurrencyConstant): + The currency constant referenced in the + query. + custom_audience (google.ads.googleads.v24.resources.types.CustomAudience): + The CustomAudience referenced in the query. + custom_conversion_goal (google.ads.googleads.v24.resources.types.CustomConversionGoal): + The CustomConversionGoal referenced in the + query. + custom_interest (google.ads.googleads.v24.resources.types.CustomInterest): + The CustomInterest referenced in the query. + customer (google.ads.googleads.v24.resources.types.Customer): + The customer referenced in the query. + customer_asset (google.ads.googleads.v24.resources.types.CustomerAsset): + The customer asset referenced in the query. + customer_asset_set (google.ads.googleads.v24.resources.types.CustomerAssetSet): + The customer asset set referenced in the + query. + accessible_bidding_strategy (google.ads.googleads.v24.resources.types.AccessibleBiddingStrategy): + The accessible bidding strategy referenced in + the query. + customer_customizer (google.ads.googleads.v24.resources.types.CustomerCustomizer): + The customer customizer referenced in the + query. + customer_manager_link (google.ads.googleads.v24.resources.types.CustomerManagerLink): + The CustomerManagerLink referenced in the + query. + customer_client_link (google.ads.googleads.v24.resources.types.CustomerClientLink): + The CustomerClientLink referenced in the + query. + customer_client (google.ads.googleads.v24.resources.types.CustomerClient): + The CustomerClient referenced in the query. + customer_conversion_goal (google.ads.googleads.v24.resources.types.CustomerConversionGoal): + The CustomerConversionGoal referenced in the + query. + customer_label (google.ads.googleads.v24.resources.types.CustomerLabel): + The customer label referenced in the query. + customer_lifecycle_goal (google.ads.googleads.v24.resources.types.CustomerLifecycleGoal): + The customer lifecycle goal referenced in the + query. + customer_negative_criterion (google.ads.googleads.v24.resources.types.CustomerNegativeCriterion): + The customer negative criterion referenced in + the query. + customer_search_term_insight (google.ads.googleads.v24.resources.types.CustomerSearchTermInsight): + The customer search term insight referenced + in the query. + customer_user_access (google.ads.googleads.v24.resources.types.CustomerUserAccess): + The CustomerUserAccess referenced in the + query. + customer_user_access_invitation (google.ads.googleads.v24.resources.types.CustomerUserAccessInvitation): + The CustomerUserAccessInvitation referenced + in the query. + customizer_attribute (google.ads.googleads.v24.resources.types.CustomizerAttribute): + The customizer attribute referenced in the + query. + data_link (google.ads.googleads.v24.resources.types.DataLink): + The data link referenced in the query. + detail_content_suitability_placement_view (google.ads.googleads.v24.resources.types.DetailContentSuitabilityPlacementView): + The detail content suitability placement view + referenced in the query. + detail_placement_view (google.ads.googleads.v24.resources.types.DetailPlacementView): + The detail placement view referenced in the + query. + detailed_demographic (google.ads.googleads.v24.resources.types.DetailedDemographic): + The detailed demographic referenced in the + query. + display_keyword_view (google.ads.googleads.v24.resources.types.DisplayKeywordView): + The display keyword view referenced in the + query. + distance_view (google.ads.googleads.v24.resources.types.DistanceView): + The distance view referenced in the query. + dynamic_search_ads_search_term_view (google.ads.googleads.v24.resources.types.DynamicSearchAdsSearchTermView): + The dynamic search ads search term view + referenced in the query. + expanded_landing_page_view (google.ads.googleads.v24.resources.types.ExpandedLandingPageView): + The expanded landing page view referenced in + the query. + final_url_expansion_asset_view (google.ads.googleads.v24.resources.types.FinalUrlExpansionAssetView): + The final url expansion asset view referenced + in the query. + gender_view (google.ads.googleads.v24.resources.types.GenderView): + The gender view referenced in the query. + geo_target_constant (google.ads.googleads.v24.resources.types.GeoTargetConstant): + The geo target constant referenced in the + query. + geographic_view (google.ads.googleads.v24.resources.types.GeographicView): + The geographic view referenced in the query. + goal (google.ads.googleads.v24.resources.types.Goal): + The goal in the query. + group_content_suitability_placement_view (google.ads.googleads.v24.resources.types.GroupContentSuitabilityPlacementView): + The group content suitability placement view + referenced in the query. + group_placement_view (google.ads.googleads.v24.resources.types.GroupPlacementView): + The group placement view referenced in the + query. + hotel_group_view (google.ads.googleads.v24.resources.types.HotelGroupView): + The hotel group view referenced in the query. + hotel_performance_view (google.ads.googleads.v24.resources.types.HotelPerformanceView): + The hotel performance view referenced in the + query. + hotel_reconciliation (google.ads.googleads.v24.resources.types.HotelReconciliation): + The hotel reconciliation referenced in the + query. + income_range_view (google.ads.googleads.v24.resources.types.IncomeRangeView): + The income range view referenced in the + query. + keyword_view (google.ads.googleads.v24.resources.types.KeywordView): + The keyword view referenced in the query. + keyword_plan (google.ads.googleads.v24.resources.types.KeywordPlan): + The keyword plan referenced in the query. + keyword_plan_campaign (google.ads.googleads.v24.resources.types.KeywordPlanCampaign): + The keyword plan campaign referenced in the + query. + keyword_plan_campaign_keyword (google.ads.googleads.v24.resources.types.KeywordPlanCampaignKeyword): + The keyword plan campaign keyword referenced + in the query. + keyword_plan_ad_group (google.ads.googleads.v24.resources.types.KeywordPlanAdGroup): + The keyword plan ad group referenced in the + query. + keyword_plan_ad_group_keyword (google.ads.googleads.v24.resources.types.KeywordPlanAdGroupKeyword): + The keyword plan ad group referenced in the + query. + keyword_theme_constant (google.ads.googleads.v24.resources.types.KeywordThemeConstant): + The keyword theme constant referenced in the + query. + label (google.ads.googleads.v24.resources.types.Label): + The label referenced in the query. + landing_page_view (google.ads.googleads.v24.resources.types.LandingPageView): + The landing page view referenced in the + query. + language_constant (google.ads.googleads.v24.resources.types.LanguageConstant): + The language constant referenced in the + query. + location_view (google.ads.googleads.v24.resources.types.LocationView): + The location view referenced in the query. + location_interest_view (google.ads.googleads.v24.resources.types.LocationInterestView): + The location interest view referenced in the + query. + managed_placement_view (google.ads.googleads.v24.resources.types.ManagedPlacementView): + The managed placement view referenced in the + query. + matched_location_interest_view (google.ads.googleads.v24.resources.types.MatchedLocationInterestView): + The matched location interest view referenced + in the query. + content_criterion_view (google.ads.googleads.v24.resources.types.ContentCriterionView): + The content criterion view referenced in the + query. + media_file (google.ads.googleads.v24.resources.types.MediaFile): + The media file referenced in the query. + local_services_employee (google.ads.googleads.v24.resources.types.LocalServicesEmployee): + The local services employee referenced in the + query. + local_services_verification_artifact (google.ads.googleads.v24.resources.types.LocalServicesVerificationArtifact): + The local services verification artifact + referenced in the query. + mobile_app_category_constant (google.ads.googleads.v24.resources.types.MobileAppCategoryConstant): + The mobile app category constant referenced + in the query. + mobile_device_constant (google.ads.googleads.v24.resources.types.MobileDeviceConstant): + The mobile device constant referenced in the + query. + offline_conversion_upload_client_summary (google.ads.googleads.v24.resources.types.OfflineConversionUploadClientSummary): + Offline conversion upload summary at customer + level. + offline_conversion_upload_conversion_action_summary (google.ads.googleads.v24.resources.types.OfflineConversionUploadConversionActionSummary): + Offline conversion upload summary at + conversion type level. + offline_user_data_job (google.ads.googleads.v24.resources.types.OfflineUserDataJob): + The offline user data job referenced in the + query. + operating_system_version_constant (google.ads.googleads.v24.resources.types.OperatingSystemVersionConstant): + The operating system version constant + referenced in the query. + paid_organic_search_term_view (google.ads.googleads.v24.resources.types.PaidOrganicSearchTermView): + The paid organic search term view referenced + in the query. + qualifying_question (google.ads.googleads.v24.resources.types.QualifyingQuestion): + The qualifying question referenced in the + query. + parental_status_view (google.ads.googleads.v24.resources.types.ParentalStatusView): + The parental status view referenced in the + query. + per_store_view (google.ads.googleads.v24.resources.types.PerStoreView): + The per store view referenced in the query. + performance_max_placement_view (google.ads.googleads.v24.resources.types.PerformanceMaxPlacementView): + The performance max placement view referenced + in the query. + product_category_constant (google.ads.googleads.v24.resources.types.ProductCategoryConstant): + The product category referenced in the query. + product_group_view (google.ads.googleads.v24.resources.types.ProductGroupView): + The product group view referenced in the + query. + product_link (google.ads.googleads.v24.resources.types.ProductLink): + The product link referenced in the query. + product_link_invitation (google.ads.googleads.v24.resources.types.ProductLinkInvitation): + The product link invitation in the query. + recommendation (google.ads.googleads.v24.resources.types.Recommendation): + The recommendation referenced in the query. + recommendation_subscription (google.ads.googleads.v24.resources.types.RecommendationSubscription): + The recommendation subscription referenced in + the query. + search_term_view (google.ads.googleads.v24.resources.types.SearchTermView): + The search term view referenced in the query. + shared_criterion (google.ads.googleads.v24.resources.types.SharedCriterion): + The shared set referenced in the query. + shared_set (google.ads.googleads.v24.resources.types.SharedSet): + The shared set referenced in the query. + smart_campaign_setting (google.ads.googleads.v24.resources.types.SmartCampaignSetting): + The Smart campaign setting referenced in the + query. + shopping_performance_view (google.ads.googleads.v24.resources.types.ShoppingPerformanceView): + The shopping performance view referenced in + the query. + shopping_product (google.ads.googleads.v24.resources.types.ShoppingProduct): + The shopping product referenced in the query. + smart_campaign_search_term_view (google.ads.googleads.v24.resources.types.SmartCampaignSearchTermView): + The Smart campaign search term view + referenced in the query. + targeting_expansion_view (google.ads.googleads.v24.resources.types.TargetingExpansionView): + The Targeting expansion view referenced in + the query. + third_party_app_analytics_link (google.ads.googleads.v24.resources.types.ThirdPartyAppAnalyticsLink): + The AccountLink referenced in the query. + topic_view (google.ads.googleads.v24.resources.types.TopicView): + The topic view referenced in the query. + travel_activity_group_view (google.ads.googleads.v24.resources.types.TravelActivityGroupView): + The travel activity group view referenced in + the query. + travel_activity_performance_view (google.ads.googleads.v24.resources.types.TravelActivityPerformanceView): + The travel activity performance view + referenced in the query. + experiment (google.ads.googleads.v24.resources.types.Experiment): + The experiment referenced in the query. + experiment_arm (google.ads.googleads.v24.resources.types.ExperimentArm): + The experiment arm referenced in the query. + user_interest (google.ads.googleads.v24.resources.types.UserInterest): + The user interest referenced in the query. + life_event (google.ads.googleads.v24.resources.types.LifeEvent): + The life event referenced in the query. + user_list (google.ads.googleads.v24.resources.types.UserList): + The user list referenced in the query. + user_list_customer_type (google.ads.googleads.v24.resources.types.UserListCustomerType): + The user list customer type in the query. + user_location_view (google.ads.googleads.v24.resources.types.UserLocationView): + The user location view referenced in the + query. + remarketing_action (google.ads.googleads.v24.resources.types.RemarketingAction): + The remarketing action referenced in the + query. + topic_constant (google.ads.googleads.v24.resources.types.TopicConstant): + The topic constant referenced in the query. + video (google.ads.googleads.v24.resources.types.Video): + The video referenced in the query. + video_enhancement (google.ads.googleads.v24.resources.types.VideoEnhancement): + The video enhancement referenced in the + query. + webpage_view (google.ads.googleads.v24.resources.types.WebpageView): + The webpage view referenced in the query. + lead_form_submission_data (google.ads.googleads.v24.resources.types.LeadFormSubmissionData): + The lead form user submission referenced in + the query. + local_services_lead (google.ads.googleads.v24.resources.types.LocalServicesLead): + The local services lead referenced in the + query. + local_services_lead_conversation (google.ads.googleads.v24.resources.types.LocalServicesLeadConversation): + The local services lead + conversationreferenced in the query. + android_privacy_shared_key_google_ad_group (google.ads.googleads.v24.resources.types.AndroidPrivacySharedKeyGoogleAdGroup): + The android privacy shared key google ad + group referenced in the query. + android_privacy_shared_key_google_campaign (google.ads.googleads.v24.resources.types.AndroidPrivacySharedKeyGoogleCampaign): + The android privacy shared key google + campaign referenced in the query. + android_privacy_shared_key_google_network_type (google.ads.googleads.v24.resources.types.AndroidPrivacySharedKeyGoogleNetworkType): + The android privacy shared key google network + type referenced in the query. + you_tube_video_upload (google.ads.googleads.v24.resources.types.YouTubeVideoUpload): + The YouTube video upload referenced in the + query. + applied_incentive (google.ads.googleads.v24.resources.types.AppliedIncentive): + The applied incentive referenced in the + query. + metrics (google.ads.googleads.v24.common.types.Metrics): + The metrics. + segments (google.ads.googleads.v24.common.types.Segments): + The segments. + """ + + account_budget: gagr_account_budget.AccountBudget = proto.Field( + proto.MESSAGE, + number=42, + message=gagr_account_budget.AccountBudget, + ) + account_budget_proposal: ( + gagr_account_budget_proposal.AccountBudgetProposal + ) = proto.Field( + proto.MESSAGE, + number=43, + message=gagr_account_budget_proposal.AccountBudgetProposal, + ) + account_link: gagr_account_link.AccountLink = proto.Field( + proto.MESSAGE, + number=143, + message=gagr_account_link.AccountLink, + ) + ad: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=227, + message=gagr_ad.Ad, + ) + ad_group: gagr_ad_group.AdGroup = proto.Field( + proto.MESSAGE, + number=3, + message=gagr_ad_group.AdGroup, + ) + ad_group_ad: gagr_ad_group_ad.AdGroupAd = proto.Field( + proto.MESSAGE, + number=16, + message=gagr_ad_group_ad.AdGroupAd, + ) + ad_group_ad_asset_combination_view: ( + gagr_ad_group_ad_asset_combination_view.AdGroupAdAssetCombinationView + ) = proto.Field( + proto.MESSAGE, + number=193, + message=gagr_ad_group_ad_asset_combination_view.AdGroupAdAssetCombinationView, + ) + app_top_combination_view: ( + gagr_app_top_combination_view.AppTopCombinationView + ) = proto.Field( + proto.MESSAGE, + number=247, + message=gagr_app_top_combination_view.AppTopCombinationView, + ) + ad_group_ad_asset_view: gagr_ad_group_ad_asset_view.AdGroupAdAssetView = ( + proto.Field( + proto.MESSAGE, + number=131, + message=gagr_ad_group_ad_asset_view.AdGroupAdAssetView, + ) + ) + ad_group_ad_label: gagr_ad_group_ad_label.AdGroupAdLabel = proto.Field( + proto.MESSAGE, + number=120, + message=gagr_ad_group_ad_label.AdGroupAdLabel, + ) + ad_group_asset: gagr_ad_group_asset.AdGroupAsset = proto.Field( + proto.MESSAGE, + number=154, + message=gagr_ad_group_asset.AdGroupAsset, + ) + ad_group_asset_set: gagr_ad_group_asset_set.AdGroupAssetSet = proto.Field( + proto.MESSAGE, + number=196, + message=gagr_ad_group_asset_set.AdGroupAssetSet, + ) + ad_group_audience_view: gagr_ad_group_audience_view.AdGroupAudienceView = ( + proto.Field( + proto.MESSAGE, + number=57, + message=gagr_ad_group_audience_view.AdGroupAudienceView, + ) + ) + ad_group_bid_modifier: gagr_ad_group_bid_modifier.AdGroupBidModifier = ( + proto.Field( + proto.MESSAGE, + number=24, + message=gagr_ad_group_bid_modifier.AdGroupBidModifier, + ) + ) + ad_group_criterion: gagr_ad_group_criterion.AdGroupCriterion = proto.Field( + proto.MESSAGE, + number=17, + message=gagr_ad_group_criterion.AdGroupCriterion, + ) + ad_group_criterion_customizer: ( + gagr_ad_group_criterion_customizer.AdGroupCriterionCustomizer + ) = proto.Field( + proto.MESSAGE, + number=187, + message=gagr_ad_group_criterion_customizer.AdGroupCriterionCustomizer, + ) + ad_group_criterion_label: ( + gagr_ad_group_criterion_label.AdGroupCriterionLabel + ) = proto.Field( + proto.MESSAGE, + number=121, + message=gagr_ad_group_criterion_label.AdGroupCriterionLabel, + ) + ad_group_criterion_simulation: ( + gagr_ad_group_criterion_simulation.AdGroupCriterionSimulation + ) = proto.Field( + proto.MESSAGE, + number=110, + message=gagr_ad_group_criterion_simulation.AdGroupCriterionSimulation, + ) + ad_group_customizer: gagr_ad_group_customizer.AdGroupCustomizer = ( + proto.Field( + proto.MESSAGE, + number=185, + message=gagr_ad_group_customizer.AdGroupCustomizer, + ) + ) + ad_group_label: gagr_ad_group_label.AdGroupLabel = proto.Field( + proto.MESSAGE, + number=115, + message=gagr_ad_group_label.AdGroupLabel, + ) + ad_group_simulation: gagr_ad_group_simulation.AdGroupSimulation = ( + proto.Field( + proto.MESSAGE, + number=107, + message=gagr_ad_group_simulation.AdGroupSimulation, + ) + ) + ad_parameter: gagr_ad_parameter.AdParameter = proto.Field( + proto.MESSAGE, + number=130, + message=gagr_ad_parameter.AdParameter, + ) + age_range_view: gagr_age_range_view.AgeRangeView = proto.Field( + proto.MESSAGE, + number=48, + message=gagr_age_range_view.AgeRangeView, + ) + ad_schedule_view: gagr_ad_schedule_view.AdScheduleView = proto.Field( + proto.MESSAGE, + number=89, + message=gagr_ad_schedule_view.AdScheduleView, + ) + ai_max_search_term_ad_combination_view: ( + gagr_ai_max_search_term_ad_combination_view.AiMaxSearchTermAdCombinationView + ) = proto.Field( + proto.MESSAGE, + number=242, + message=gagr_ai_max_search_term_ad_combination_view.AiMaxSearchTermAdCombinationView, + ) + domain_category: gagr_domain_category.DomainCategory = proto.Field( + proto.MESSAGE, + number=91, + message=gagr_domain_category.DomainCategory, + ) + asset: gagr_asset.Asset = proto.Field( + proto.MESSAGE, + number=105, + message=gagr_asset.Asset, + ) + asset_field_type_view: gagr_asset_field_type_view.AssetFieldTypeView = ( + proto.Field( + proto.MESSAGE, + number=168, + message=gagr_asset_field_type_view.AssetFieldTypeView, + ) + ) + channel_aggregate_asset_view: ( + gagr_channel_aggregate_asset_view.ChannelAggregateAssetView + ) = proto.Field( + proto.MESSAGE, + number=222, + message=gagr_channel_aggregate_asset_view.ChannelAggregateAssetView, + ) + campaign_aggregate_asset_view: ( + gagr_campaign_aggregate_asset_view.CampaignAggregateAssetView + ) = proto.Field( + proto.MESSAGE, + number=224, + message=gagr_campaign_aggregate_asset_view.CampaignAggregateAssetView, + ) + asset_group_asset: gagr_asset_group_asset.AssetGroupAsset = proto.Field( + proto.MESSAGE, + number=173, + message=gagr_asset_group_asset.AssetGroupAsset, + ) + asset_group_signal: gagr_asset_group_signal.AssetGroupSignal = proto.Field( + proto.MESSAGE, + number=191, + message=gagr_asset_group_signal.AssetGroupSignal, + ) + asset_group_listing_group_filter: ( + gagr_asset_group_listing_group_filter.AssetGroupListingGroupFilter + ) = proto.Field( + proto.MESSAGE, + number=182, + message=gagr_asset_group_listing_group_filter.AssetGroupListingGroupFilter, + ) + asset_group_product_group_view: ( + gagr_asset_group_product_group_view.AssetGroupProductGroupView + ) = proto.Field( + proto.MESSAGE, + number=189, + message=gagr_asset_group_product_group_view.AssetGroupProductGroupView, + ) + asset_group_top_combination_view: ( + gagr_asset_group_top_combination_view.AssetGroupTopCombinationView + ) = proto.Field( + proto.MESSAGE, + number=199, + message=gagr_asset_group_top_combination_view.AssetGroupTopCombinationView, + ) + asset_group: gagr_asset_group.AssetGroup = proto.Field( + proto.MESSAGE, + number=172, + message=gagr_asset_group.AssetGroup, + ) + asset_set_asset: gagr_asset_set_asset.AssetSetAsset = proto.Field( + proto.MESSAGE, + number=180, + message=gagr_asset_set_asset.AssetSetAsset, + ) + asset_set: gagr_asset_set.AssetSet = proto.Field( + proto.MESSAGE, + number=179, + message=gagr_asset_set.AssetSet, + ) + asset_set_type_view: gagr_asset_set_type_view.AssetSetTypeView = ( + proto.Field( + proto.MESSAGE, + number=197, + message=gagr_asset_set_type_view.AssetSetTypeView, + ) + ) + batch_job: gagr_batch_job.BatchJob = proto.Field( + proto.MESSAGE, + number=139, + message=gagr_batch_job.BatchJob, + ) + bidding_data_exclusion: gagr_bidding_data_exclusion.BiddingDataExclusion = ( + proto.Field( + proto.MESSAGE, + number=159, + message=gagr_bidding_data_exclusion.BiddingDataExclusion, + ) + ) + bidding_seasonality_adjustment: ( + gagr_bidding_seasonality_adjustment.BiddingSeasonalityAdjustment + ) = proto.Field( + proto.MESSAGE, + number=160, + message=gagr_bidding_seasonality_adjustment.BiddingSeasonalityAdjustment, + ) + bidding_strategy: gagr_bidding_strategy.BiddingStrategy = proto.Field( + proto.MESSAGE, + number=18, + message=gagr_bidding_strategy.BiddingStrategy, + ) + bidding_strategy_simulation: ( + gagr_bidding_strategy_simulation.BiddingStrategySimulation + ) = proto.Field( + proto.MESSAGE, + number=158, + message=gagr_bidding_strategy_simulation.BiddingStrategySimulation, + ) + billing_setup: gagr_billing_setup.BillingSetup = proto.Field( + proto.MESSAGE, + number=41, + message=gagr_billing_setup.BillingSetup, + ) + call_view: gagr_call_view.CallView = proto.Field( + proto.MESSAGE, + number=152, + message=gagr_call_view.CallView, + ) + campaign_budget: gagr_campaign_budget.CampaignBudget = proto.Field( + proto.MESSAGE, + number=19, + message=gagr_campaign_budget.CampaignBudget, + ) + campaign: gagr_campaign.Campaign = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_campaign.Campaign, + ) + campaign_asset: gagr_campaign_asset.CampaignAsset = proto.Field( + proto.MESSAGE, + number=142, + message=gagr_campaign_asset.CampaignAsset, + ) + campaign_asset_set: gagr_campaign_asset_set.CampaignAssetSet = proto.Field( + proto.MESSAGE, + number=181, + message=gagr_campaign_asset_set.CampaignAssetSet, + ) + campaign_audience_view: gagr_campaign_audience_view.CampaignAudienceView = ( + proto.Field( + proto.MESSAGE, + number=69, + message=gagr_campaign_audience_view.CampaignAudienceView, + ) + ) + campaign_bid_modifier: gagr_campaign_bid_modifier.CampaignBidModifier = ( + proto.Field( + proto.MESSAGE, + number=26, + message=gagr_campaign_bid_modifier.CampaignBidModifier, + ) + ) + campaign_conversion_goal: ( + gagr_campaign_conversion_goal.CampaignConversionGoal + ) = proto.Field( + proto.MESSAGE, + number=175, + message=gagr_campaign_conversion_goal.CampaignConversionGoal, + ) + campaign_criterion: gagr_campaign_criterion.CampaignCriterion = proto.Field( + proto.MESSAGE, + number=20, + message=gagr_campaign_criterion.CampaignCriterion, + ) + campaign_customizer: gagr_campaign_customizer.CampaignCustomizer = ( + proto.Field( + proto.MESSAGE, + number=186, + message=gagr_campaign_customizer.CampaignCustomizer, + ) + ) + campaign_draft: gagr_campaign_draft.CampaignDraft = proto.Field( + proto.MESSAGE, + number=49, + message=gagr_campaign_draft.CampaignDraft, + ) + campaign_group: gagr_campaign_group.CampaignGroup = proto.Field( + proto.MESSAGE, + number=25, + message=gagr_campaign_group.CampaignGroup, + ) + campaign_goal_config: gagr_campaign_goal_config.CampaignGoalConfig = ( + proto.Field( + proto.MESSAGE, + number=236, + message=gagr_campaign_goal_config.CampaignGoalConfig, + ) + ) + campaign_label: gagr_campaign_label.CampaignLabel = proto.Field( + proto.MESSAGE, + number=108, + message=gagr_campaign_label.CampaignLabel, + ) + campaign_lifecycle_goal: ( + gagr_campaign_lifecycle_goal.CampaignLifecycleGoal + ) = proto.Field( + proto.MESSAGE, + number=213, + message=gagr_campaign_lifecycle_goal.CampaignLifecycleGoal, + ) + campaign_search_term_insight: ( + gagr_campaign_search_term_insight.CampaignSearchTermInsight + ) = proto.Field( + proto.MESSAGE, + number=204, + message=gagr_campaign_search_term_insight.CampaignSearchTermInsight, + ) + campaign_search_term_view: ( + gagr_campaign_search_term_view.CampaignSearchTermView + ) = proto.Field( + proto.MESSAGE, + number=243, + message=gagr_campaign_search_term_view.CampaignSearchTermView, + ) + campaign_shared_set: gagr_campaign_shared_set.CampaignSharedSet = ( + proto.Field( + proto.MESSAGE, + number=30, + message=gagr_campaign_shared_set.CampaignSharedSet, + ) + ) + campaign_simulation: gagr_campaign_simulation.CampaignSimulation = ( + proto.Field( + proto.MESSAGE, + number=157, + message=gagr_campaign_simulation.CampaignSimulation, + ) + ) + carrier_constant: gagr_carrier_constant.CarrierConstant = proto.Field( + proto.MESSAGE, + number=66, + message=gagr_carrier_constant.CarrierConstant, + ) + cart_data_sales_view: gagr_cart_data_sales_view.CartDataSalesView = ( + proto.Field( + proto.MESSAGE, + number=221, + message=gagr_cart_data_sales_view.CartDataSalesView, + ) + ) + change_event: gagr_change_event.ChangeEvent = proto.Field( + proto.MESSAGE, + number=145, + message=gagr_change_event.ChangeEvent, + ) + change_status: gagr_change_status.ChangeStatus = proto.Field( + proto.MESSAGE, + number=37, + message=gagr_change_status.ChangeStatus, + ) + combined_audience: gagr_combined_audience.CombinedAudience = proto.Field( + proto.MESSAGE, + number=148, + message=gagr_combined_audience.CombinedAudience, + ) + audience: gagr_audience.Audience = proto.Field( + proto.MESSAGE, + number=190, + message=gagr_audience.Audience, + ) + conversion_action: gagr_conversion_action.ConversionAction = proto.Field( + proto.MESSAGE, + number=103, + message=gagr_conversion_action.ConversionAction, + ) + conversion_custom_variable: ( + gagr_conversion_custom_variable.ConversionCustomVariable + ) = proto.Field( + proto.MESSAGE, + number=153, + message=gagr_conversion_custom_variable.ConversionCustomVariable, + ) + conversion_goal_campaign_config: ( + gagr_conversion_goal_campaign_config.ConversionGoalCampaignConfig + ) = proto.Field( + proto.MESSAGE, + number=177, + message=gagr_conversion_goal_campaign_config.ConversionGoalCampaignConfig, + ) + conversion_value_rule: gagr_conversion_value_rule.ConversionValueRule = ( + proto.Field( + proto.MESSAGE, + number=164, + message=gagr_conversion_value_rule.ConversionValueRule, + ) + ) + conversion_value_rule_set: ( + gagr_conversion_value_rule_set.ConversionValueRuleSet + ) = proto.Field( + proto.MESSAGE, + number=165, + message=gagr_conversion_value_rule_set.ConversionValueRuleSet, + ) + click_view: gagr_click_view.ClickView = proto.Field( + proto.MESSAGE, + number=122, + message=gagr_click_view.ClickView, + ) + currency_constant: gagr_currency_constant.CurrencyConstant = proto.Field( + proto.MESSAGE, + number=134, + message=gagr_currency_constant.CurrencyConstant, + ) + custom_audience: gagr_custom_audience.CustomAudience = proto.Field( + proto.MESSAGE, + number=147, + message=gagr_custom_audience.CustomAudience, + ) + custom_conversion_goal: gagr_custom_conversion_goal.CustomConversionGoal = ( + proto.Field( + proto.MESSAGE, + number=176, + message=gagr_custom_conversion_goal.CustomConversionGoal, + ) + ) + custom_interest: gagr_custom_interest.CustomInterest = proto.Field( + proto.MESSAGE, + number=104, + message=gagr_custom_interest.CustomInterest, + ) + customer: gagr_customer.Customer = proto.Field( + proto.MESSAGE, + number=1, + message=gagr_customer.Customer, + ) + customer_asset: gagr_customer_asset.CustomerAsset = proto.Field( + proto.MESSAGE, + number=155, + message=gagr_customer_asset.CustomerAsset, + ) + customer_asset_set: gagr_customer_asset_set.CustomerAssetSet = proto.Field( + proto.MESSAGE, + number=195, + message=gagr_customer_asset_set.CustomerAssetSet, + ) + accessible_bidding_strategy: ( + gagr_accessible_bidding_strategy.AccessibleBiddingStrategy + ) = proto.Field( + proto.MESSAGE, + number=169, + message=gagr_accessible_bidding_strategy.AccessibleBiddingStrategy, + ) + customer_customizer: gagr_customer_customizer.CustomerCustomizer = ( + proto.Field( + proto.MESSAGE, + number=184, + message=gagr_customer_customizer.CustomerCustomizer, + ) + ) + customer_manager_link: gagr_customer_manager_link.CustomerManagerLink = ( + proto.Field( + proto.MESSAGE, + number=61, + message=gagr_customer_manager_link.CustomerManagerLink, + ) + ) + customer_client_link: gagr_customer_client_link.CustomerClientLink = ( + proto.Field( + proto.MESSAGE, + number=62, + message=gagr_customer_client_link.CustomerClientLink, + ) + ) + customer_client: gagr_customer_client.CustomerClient = proto.Field( + proto.MESSAGE, + number=70, + message=gagr_customer_client.CustomerClient, + ) + customer_conversion_goal: ( + gagr_customer_conversion_goal.CustomerConversionGoal + ) = proto.Field( + proto.MESSAGE, + number=174, + message=gagr_customer_conversion_goal.CustomerConversionGoal, + ) + customer_label: gagr_customer_label.CustomerLabel = proto.Field( + proto.MESSAGE, + number=124, + message=gagr_customer_label.CustomerLabel, + ) + customer_lifecycle_goal: ( + gagr_customer_lifecycle_goal.CustomerLifecycleGoal + ) = proto.Field( + proto.MESSAGE, + number=212, + message=gagr_customer_lifecycle_goal.CustomerLifecycleGoal, + ) + customer_negative_criterion: ( + gagr_customer_negative_criterion.CustomerNegativeCriterion + ) = proto.Field( + proto.MESSAGE, + number=88, + message=gagr_customer_negative_criterion.CustomerNegativeCriterion, + ) + customer_search_term_insight: ( + gagr_customer_search_term_insight.CustomerSearchTermInsight + ) = proto.Field( + proto.MESSAGE, + number=205, + message=gagr_customer_search_term_insight.CustomerSearchTermInsight, + ) + customer_user_access: gagr_customer_user_access.CustomerUserAccess = ( + proto.Field( + proto.MESSAGE, + number=146, + message=gagr_customer_user_access.CustomerUserAccess, + ) + ) + customer_user_access_invitation: ( + gagr_customer_user_access_invitation.CustomerUserAccessInvitation + ) = proto.Field( + proto.MESSAGE, + number=150, + message=gagr_customer_user_access_invitation.CustomerUserAccessInvitation, + ) + customizer_attribute: gagr_customizer_attribute.CustomizerAttribute = ( + proto.Field( + proto.MESSAGE, + number=178, + message=gagr_customizer_attribute.CustomizerAttribute, + ) + ) + data_link: gagr_data_link.DataLink = proto.Field( + proto.MESSAGE, + number=230, + message=gagr_data_link.DataLink, + ) + detail_content_suitability_placement_view: ( + gagr_detail_content_suitability_placement_view.DetailContentSuitabilityPlacementView + ) = proto.Field( + proto.MESSAGE, + number=238, + message=gagr_detail_content_suitability_placement_view.DetailContentSuitabilityPlacementView, + ) + detail_placement_view: gagr_detail_placement_view.DetailPlacementView = ( + proto.Field( + proto.MESSAGE, + number=118, + message=gagr_detail_placement_view.DetailPlacementView, + ) + ) + detailed_demographic: gagr_detailed_demographic.DetailedDemographic = ( + proto.Field( + proto.MESSAGE, + number=166, + message=gagr_detailed_demographic.DetailedDemographic, + ) + ) + display_keyword_view: gagr_display_keyword_view.DisplayKeywordView = ( + proto.Field( + proto.MESSAGE, + number=47, + message=gagr_display_keyword_view.DisplayKeywordView, + ) + ) + distance_view: gagr_distance_view.DistanceView = proto.Field( + proto.MESSAGE, + number=132, + message=gagr_distance_view.DistanceView, + ) + dynamic_search_ads_search_term_view: ( + gagr_dynamic_search_ads_search_term_view.DynamicSearchAdsSearchTermView + ) = proto.Field( + proto.MESSAGE, + number=106, + message=gagr_dynamic_search_ads_search_term_view.DynamicSearchAdsSearchTermView, + ) + expanded_landing_page_view: ( + gagr_expanded_landing_page_view.ExpandedLandingPageView + ) = proto.Field( + proto.MESSAGE, + number=128, + message=gagr_expanded_landing_page_view.ExpandedLandingPageView, + ) + final_url_expansion_asset_view: ( + gagr_final_url_expansion_asset_view.FinalUrlExpansionAssetView + ) = proto.Field( + proto.MESSAGE, + number=240, + message=gagr_final_url_expansion_asset_view.FinalUrlExpansionAssetView, + ) + gender_view: gagr_gender_view.GenderView = proto.Field( + proto.MESSAGE, + number=40, + message=gagr_gender_view.GenderView, + ) + geo_target_constant: gagr_geo_target_constant.GeoTargetConstant = ( + proto.Field( + proto.MESSAGE, + number=23, + message=gagr_geo_target_constant.GeoTargetConstant, + ) + ) + geographic_view: gagr_geographic_view.GeographicView = proto.Field( + proto.MESSAGE, + number=125, + message=gagr_geographic_view.GeographicView, + ) + goal: gagr_goal.Goal = proto.Field( + proto.MESSAGE, + number=237, + message=gagr_goal.Goal, + ) + group_content_suitability_placement_view: ( + gagr_group_content_suitability_placement_view.GroupContentSuitabilityPlacementView + ) = proto.Field( + proto.MESSAGE, + number=239, + message=gagr_group_content_suitability_placement_view.GroupContentSuitabilityPlacementView, + ) + group_placement_view: gagr_group_placement_view.GroupPlacementView = ( + proto.Field( + proto.MESSAGE, + number=119, + message=gagr_group_placement_view.GroupPlacementView, + ) + ) + hotel_group_view: gagr_hotel_group_view.HotelGroupView = proto.Field( + proto.MESSAGE, + number=51, + message=gagr_hotel_group_view.HotelGroupView, + ) + hotel_performance_view: gagr_hotel_performance_view.HotelPerformanceView = ( + proto.Field( + proto.MESSAGE, + number=71, + message=gagr_hotel_performance_view.HotelPerformanceView, + ) + ) + hotel_reconciliation: gagr_hotel_reconciliation.HotelReconciliation = ( + proto.Field( + proto.MESSAGE, + number=188, + message=gagr_hotel_reconciliation.HotelReconciliation, + ) + ) + income_range_view: gagr_income_range_view.IncomeRangeView = proto.Field( + proto.MESSAGE, + number=138, + message=gagr_income_range_view.IncomeRangeView, + ) + keyword_view: gagr_keyword_view.KeywordView = proto.Field( + proto.MESSAGE, + number=21, + message=gagr_keyword_view.KeywordView, + ) + keyword_plan: gagr_keyword_plan.KeywordPlan = proto.Field( + proto.MESSAGE, + number=32, + message=gagr_keyword_plan.KeywordPlan, + ) + keyword_plan_campaign: gagr_keyword_plan_campaign.KeywordPlanCampaign = ( + proto.Field( + proto.MESSAGE, + number=33, + message=gagr_keyword_plan_campaign.KeywordPlanCampaign, + ) + ) + keyword_plan_campaign_keyword: ( + gagr_keyword_plan_campaign_keyword.KeywordPlanCampaignKeyword + ) = proto.Field( + proto.MESSAGE, + number=140, + message=gagr_keyword_plan_campaign_keyword.KeywordPlanCampaignKeyword, + ) + keyword_plan_ad_group: gagr_keyword_plan_ad_group.KeywordPlanAdGroup = ( + proto.Field( + proto.MESSAGE, + number=35, + message=gagr_keyword_plan_ad_group.KeywordPlanAdGroup, + ) + ) + keyword_plan_ad_group_keyword: ( + gagr_keyword_plan_ad_group_keyword.KeywordPlanAdGroupKeyword + ) = proto.Field( + proto.MESSAGE, + number=141, + message=gagr_keyword_plan_ad_group_keyword.KeywordPlanAdGroupKeyword, + ) + keyword_theme_constant: gagr_keyword_theme_constant.KeywordThemeConstant = ( + proto.Field( + proto.MESSAGE, + number=163, + message=gagr_keyword_theme_constant.KeywordThemeConstant, + ) + ) + label: gagr_label.Label = proto.Field( + proto.MESSAGE, + number=52, + message=gagr_label.Label, + ) + landing_page_view: gagr_landing_page_view.LandingPageView = proto.Field( + proto.MESSAGE, + number=126, + message=gagr_landing_page_view.LandingPageView, + ) + language_constant: gagr_language_constant.LanguageConstant = proto.Field( + proto.MESSAGE, + number=55, + message=gagr_language_constant.LanguageConstant, + ) + location_view: gagr_location_view.LocationView = proto.Field( + proto.MESSAGE, + number=123, + message=gagr_location_view.LocationView, + ) + location_interest_view: gagr_location_interest_view.LocationInterestView = ( + proto.Field( + proto.MESSAGE, + number=241, + message=gagr_location_interest_view.LocationInterestView, + ) + ) + managed_placement_view: gagr_managed_placement_view.ManagedPlacementView = ( + proto.Field( + proto.MESSAGE, + number=53, + message=gagr_managed_placement_view.ManagedPlacementView, + ) + ) + matched_location_interest_view: ( + gagr_matched_location_interest_view.MatchedLocationInterestView + ) = proto.Field( + proto.MESSAGE, + number=248, + message=gagr_matched_location_interest_view.MatchedLocationInterestView, + ) + content_criterion_view: gagr_content_criterion_view.ContentCriterionView = ( + proto.Field( + proto.MESSAGE, + number=232, + message=gagr_content_criterion_view.ContentCriterionView, + ) + ) + media_file: gagr_media_file.MediaFile = proto.Field( + proto.MESSAGE, + number=90, + message=gagr_media_file.MediaFile, + ) + local_services_employee: ( + gagr_local_services_employee.LocalServicesEmployee + ) = proto.Field( + proto.MESSAGE, + number=223, + message=gagr_local_services_employee.LocalServicesEmployee, + ) + local_services_verification_artifact: ( + gagr_local_services_verification_artifact.LocalServicesVerificationArtifact + ) = proto.Field( + proto.MESSAGE, + number=211, + message=gagr_local_services_verification_artifact.LocalServicesVerificationArtifact, + ) + mobile_app_category_constant: ( + gagr_mobile_app_category_constant.MobileAppCategoryConstant + ) = proto.Field( + proto.MESSAGE, + number=87, + message=gagr_mobile_app_category_constant.MobileAppCategoryConstant, + ) + mobile_device_constant: gagr_mobile_device_constant.MobileDeviceConstant = ( + proto.Field( + proto.MESSAGE, + number=98, + message=gagr_mobile_device_constant.MobileDeviceConstant, + ) + ) + offline_conversion_upload_client_summary: ( + gagr_offline_conversion_upload_client_summary.OfflineConversionUploadClientSummary + ) = proto.Field( + proto.MESSAGE, + number=216, + message=gagr_offline_conversion_upload_client_summary.OfflineConversionUploadClientSummary, + ) + offline_conversion_upload_conversion_action_summary: ( + gagr_offline_conversion_upload_conversion_action_summary.OfflineConversionUploadConversionActionSummary + ) = proto.Field( + proto.MESSAGE, + number=228, + message=gagr_offline_conversion_upload_conversion_action_summary.OfflineConversionUploadConversionActionSummary, + ) + offline_user_data_job: gagr_offline_user_data_job.OfflineUserDataJob = ( + proto.Field( + proto.MESSAGE, + number=137, + message=gagr_offline_user_data_job.OfflineUserDataJob, + ) + ) + operating_system_version_constant: ( + gagr_operating_system_version_constant.OperatingSystemVersionConstant + ) = proto.Field( + proto.MESSAGE, + number=86, + message=gagr_operating_system_version_constant.OperatingSystemVersionConstant, + ) + paid_organic_search_term_view: ( + gagr_paid_organic_search_term_view.PaidOrganicSearchTermView + ) = proto.Field( + proto.MESSAGE, + number=129, + message=gagr_paid_organic_search_term_view.PaidOrganicSearchTermView, + ) + qualifying_question: gagr_qualifying_question.QualifyingQuestion = ( + proto.Field( + proto.MESSAGE, + number=202, + message=gagr_qualifying_question.QualifyingQuestion, + ) + ) + parental_status_view: gagr_parental_status_view.ParentalStatusView = ( + proto.Field( + proto.MESSAGE, + number=45, + message=gagr_parental_status_view.ParentalStatusView, + ) + ) + per_store_view: gagr_per_store_view.PerStoreView = proto.Field( + proto.MESSAGE, + number=198, + message=gagr_per_store_view.PerStoreView, + ) + performance_max_placement_view: ( + gagr_performance_max_placement_view.PerformanceMaxPlacementView + ) = proto.Field( + proto.MESSAGE, + number=233, + message=gagr_performance_max_placement_view.PerformanceMaxPlacementView, + ) + product_category_constant: ( + gagr_product_category_constant.ProductCategoryConstant + ) = proto.Field( + proto.MESSAGE, + number=208, + message=gagr_product_category_constant.ProductCategoryConstant, + ) + product_group_view: gagr_product_group_view.ProductGroupView = proto.Field( + proto.MESSAGE, + number=54, + message=gagr_product_group_view.ProductGroupView, + ) + product_link: gagr_product_link.ProductLink = proto.Field( + proto.MESSAGE, + number=194, + message=gagr_product_link.ProductLink, + ) + product_link_invitation: ( + gagr_product_link_invitation.ProductLinkInvitation + ) = proto.Field( + proto.MESSAGE, + number=209, + message=gagr_product_link_invitation.ProductLinkInvitation, + ) + recommendation: gagr_recommendation.Recommendation = proto.Field( + proto.MESSAGE, + number=22, + message=gagr_recommendation.Recommendation, + ) + recommendation_subscription: ( + gagr_recommendation_subscription.RecommendationSubscription + ) = proto.Field( + proto.MESSAGE, + number=220, + message=gagr_recommendation_subscription.RecommendationSubscription, + ) + search_term_view: gagr_search_term_view.SearchTermView = proto.Field( + proto.MESSAGE, + number=68, + message=gagr_search_term_view.SearchTermView, + ) + shared_criterion: gagr_shared_criterion.SharedCriterion = proto.Field( + proto.MESSAGE, + number=29, + message=gagr_shared_criterion.SharedCriterion, + ) + shared_set: gagr_shared_set.SharedSet = proto.Field( + proto.MESSAGE, + number=27, + message=gagr_shared_set.SharedSet, + ) + smart_campaign_setting: gagr_smart_campaign_setting.SmartCampaignSetting = ( + proto.Field( + proto.MESSAGE, + number=167, + message=gagr_smart_campaign_setting.SmartCampaignSetting, + ) + ) + shopping_performance_view: ( + gagr_shopping_performance_view.ShoppingPerformanceView + ) = proto.Field( + proto.MESSAGE, + number=117, + message=gagr_shopping_performance_view.ShoppingPerformanceView, + ) + shopping_product: gagr_shopping_product.ShoppingProduct = proto.Field( + proto.MESSAGE, + number=226, + message=gagr_shopping_product.ShoppingProduct, + ) + smart_campaign_search_term_view: ( + gagr_smart_campaign_search_term_view.SmartCampaignSearchTermView + ) = proto.Field( + proto.MESSAGE, + number=170, + message=gagr_smart_campaign_search_term_view.SmartCampaignSearchTermView, + ) + targeting_expansion_view: ( + gagr_targeting_expansion_view.TargetingExpansionView + ) = proto.Field( + proto.MESSAGE, + number=244, + message=gagr_targeting_expansion_view.TargetingExpansionView, + ) + third_party_app_analytics_link: ( + gagr_third_party_app_analytics_link.ThirdPartyAppAnalyticsLink + ) = proto.Field( + proto.MESSAGE, + number=144, + message=gagr_third_party_app_analytics_link.ThirdPartyAppAnalyticsLink, + ) + topic_view: gagr_topic_view.TopicView = proto.Field( + proto.MESSAGE, + number=44, + message=gagr_topic_view.TopicView, + ) + travel_activity_group_view: ( + gagr_travel_activity_group_view.TravelActivityGroupView + ) = proto.Field( + proto.MESSAGE, + number=201, + message=gagr_travel_activity_group_view.TravelActivityGroupView, + ) + travel_activity_performance_view: ( + gagr_travel_activity_performance_view.TravelActivityPerformanceView + ) = proto.Field( + proto.MESSAGE, + number=200, + message=gagr_travel_activity_performance_view.TravelActivityPerformanceView, + ) + experiment: gagr_experiment.Experiment = proto.Field( + proto.MESSAGE, + number=133, + message=gagr_experiment.Experiment, + ) + experiment_arm: gagr_experiment_arm.ExperimentArm = proto.Field( + proto.MESSAGE, + number=183, + message=gagr_experiment_arm.ExperimentArm, + ) + user_interest: gagr_user_interest.UserInterest = proto.Field( + proto.MESSAGE, + number=59, + message=gagr_user_interest.UserInterest, + ) + life_event: gagr_life_event.LifeEvent = proto.Field( + proto.MESSAGE, + number=161, + message=gagr_life_event.LifeEvent, + ) + user_list: gagr_user_list.UserList = proto.Field( + proto.MESSAGE, + number=38, + message=gagr_user_list.UserList, + ) + user_list_customer_type: ( + gagr_user_list_customer_type.UserListCustomerType + ) = proto.Field( + proto.MESSAGE, + number=225, + message=gagr_user_list_customer_type.UserListCustomerType, + ) + user_location_view: gagr_user_location_view.UserLocationView = proto.Field( + proto.MESSAGE, + number=135, + message=gagr_user_location_view.UserLocationView, + ) + remarketing_action: gagr_remarketing_action.RemarketingAction = proto.Field( + proto.MESSAGE, + number=60, + message=gagr_remarketing_action.RemarketingAction, + ) + topic_constant: gagr_topic_constant.TopicConstant = proto.Field( + proto.MESSAGE, + number=31, + message=gagr_topic_constant.TopicConstant, + ) + video: gagr_video.Video = proto.Field( + proto.MESSAGE, + number=39, + message=gagr_video.Video, + ) + video_enhancement: gagr_video_enhancement.VideoEnhancement = proto.Field( + proto.MESSAGE, + number=250, + message=gagr_video_enhancement.VideoEnhancement, + ) + webpage_view: gagr_webpage_view.WebpageView = proto.Field( + proto.MESSAGE, + number=162, + message=gagr_webpage_view.WebpageView, + ) + lead_form_submission_data: ( + gagr_lead_form_submission_data.LeadFormSubmissionData + ) = proto.Field( + proto.MESSAGE, + number=192, + message=gagr_lead_form_submission_data.LeadFormSubmissionData, + ) + local_services_lead: gagr_local_services_lead.LocalServicesLead = ( + proto.Field( + proto.MESSAGE, + number=210, + message=gagr_local_services_lead.LocalServicesLead, + ) + ) + local_services_lead_conversation: ( + gagr_local_services_lead_conversation.LocalServicesLeadConversation + ) = proto.Field( + proto.MESSAGE, + number=214, + message=gagr_local_services_lead_conversation.LocalServicesLeadConversation, + ) + android_privacy_shared_key_google_ad_group: ( + gagr_android_privacy_shared_key_google_ad_group.AndroidPrivacySharedKeyGoogleAdGroup + ) = proto.Field( + proto.MESSAGE, + number=217, + message=gagr_android_privacy_shared_key_google_ad_group.AndroidPrivacySharedKeyGoogleAdGroup, + ) + android_privacy_shared_key_google_campaign: ( + gagr_android_privacy_shared_key_google_campaign.AndroidPrivacySharedKeyGoogleCampaign + ) = proto.Field( + proto.MESSAGE, + number=218, + message=gagr_android_privacy_shared_key_google_campaign.AndroidPrivacySharedKeyGoogleCampaign, + ) + android_privacy_shared_key_google_network_type: ( + gagr_android_privacy_shared_key_google_network_type.AndroidPrivacySharedKeyGoogleNetworkType + ) = proto.Field( + proto.MESSAGE, + number=219, + message=gagr_android_privacy_shared_key_google_network_type.AndroidPrivacySharedKeyGoogleNetworkType, + ) + you_tube_video_upload: youtube_video_upload.YouTubeVideoUpload = ( + proto.Field( + proto.MESSAGE, + number=245, + message=youtube_video_upload.YouTubeVideoUpload, + ) + ) + applied_incentive: gagr_applied_incentive.AppliedIncentive = proto.Field( + proto.MESSAGE, + number=246, + message=gagr_applied_incentive.AppliedIncentive, + ) + metrics: gagc_metrics.Metrics = proto.Field( + proto.MESSAGE, + number=4, + message=gagc_metrics.Metrics, + ) + segments: gagc_segments.Segments = proto.Field( + proto.MESSAGE, + number=102, + message=gagc_segments.Segments, + ) + + +class MutateGoogleAdsRequest(proto.Message): + r"""Request message for + [GoogleAdsService.Mutate][google.ads.googleads.v24.services.GoogleAdsService.Mutate]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + resources are being modified. + mutate_operations (MutableSequence[google.ads.googleads.v24.services.types.MutateOperation]): + Required. The list of operations to perform + on individual resources. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Mutates only return errors, not + results. Actions return results and errors. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + The mutable resource will only be returned if + the resource has the appropriate response field. + For example, MutateCampaignResult.campaign. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + mutate_operations: MutableSequence["MutateOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class MutateGoogleAdsResponse(proto.Message): + r"""Response message for + [GoogleAdsService.Mutate][google.ads.googleads.v24.services.GoogleAdsService.Mutate]. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + mutate_operation_responses (MutableSequence[google.ads.googleads.v24.services.types.MutateOperationResponse]): + All responses for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + mutate_operation_responses: MutableSequence["MutateOperationResponse"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateOperationResponse", + ) + ) + + +class MutateOperation(proto.Message): + r"""A single operation (create, update, remove) on a resource, or + execute an action. + + 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: + ad_group_ad_label_operation (google.ads.googleads.v24.services.types.AdGroupAdLabelOperation): + An ad group ad label mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_ad_operation (google.ads.googleads.v24.services.types.AdGroupAdOperation): + An ad group ad mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_asset_operation (google.ads.googleads.v24.services.types.AdGroupAssetOperation): + An ad group asset mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_bid_modifier_operation (google.ads.googleads.v24.services.types.AdGroupBidModifierOperation): + An ad group bid modifier mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_criterion_customizer_operation (google.ads.googleads.v24.services.types.AdGroupCriterionCustomizerOperation): + An ad group criterion customizer mutate + operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_criterion_label_operation (google.ads.googleads.v24.services.types.AdGroupCriterionLabelOperation): + An ad group criterion label mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_criterion_operation (google.ads.googleads.v24.services.types.AdGroupCriterionOperation): + An ad group criterion mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_customizer_operation (google.ads.googleads.v24.services.types.AdGroupCustomizerOperation): + An ad group customizer mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_label_operation (google.ads.googleads.v24.services.types.AdGroupLabelOperation): + An ad group label mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_operation (google.ads.googleads.v24.services.types.AdGroupOperation): + An ad group mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_operation (google.ads.googleads.v24.services.types.AdOperation): + An ad mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_parameter_operation (google.ads.googleads.v24.services.types.AdParameterOperation): + An ad parameter mutate operation. + + This field is a member of `oneof`_ ``operation``. + asset_operation (google.ads.googleads.v24.services.types.AssetOperation): + An asset mutate operation. + + This field is a member of `oneof`_ ``operation``. + asset_group_asset_operation (google.ads.googleads.v24.services.types.AssetGroupAssetOperation): + An asset group asset mutate operation. + + This field is a member of `oneof`_ ``operation``. + asset_group_listing_group_filter_operation (google.ads.googleads.v24.services.types.AssetGroupListingGroupFilterOperation): + An asset group listing group filter mutate + operation. + + This field is a member of `oneof`_ ``operation``. + asset_group_signal_operation (google.ads.googleads.v24.services.types.AssetGroupSignalOperation): + An asset group signal mutate operation. + + This field is a member of `oneof`_ ``operation``. + asset_group_operation (google.ads.googleads.v24.services.types.AssetGroupOperation): + An asset group mutate operation. + + This field is a member of `oneof`_ ``operation``. + asset_set_asset_operation (google.ads.googleads.v24.services.types.AssetSetAssetOperation): + An asset set asset mutate operation. + + This field is a member of `oneof`_ ``operation``. + asset_set_operation (google.ads.googleads.v24.services.types.AssetSetOperation): + An asset set mutate operation. + + This field is a member of `oneof`_ ``operation``. + audience_operation (google.ads.googleads.v24.services.types.AudienceOperation): + An audience mutate operation. + + This field is a member of `oneof`_ ``operation``. + bidding_data_exclusion_operation (google.ads.googleads.v24.services.types.BiddingDataExclusionOperation): + A bidding data exclusion mutate operation. + + This field is a member of `oneof`_ ``operation``. + bidding_seasonality_adjustment_operation (google.ads.googleads.v24.services.types.BiddingSeasonalityAdjustmentOperation): + A bidding seasonality adjustment mutate + operation. + + This field is a member of `oneof`_ ``operation``. + bidding_strategy_operation (google.ads.googleads.v24.services.types.BiddingStrategyOperation): + A bidding strategy mutate operation. + + This field is a member of `oneof`_ ``operation``. + book_campaigns_operation (google.ads.googleads.v24.actions.types.BookCampaignsOperation): + Request message for the BookCampaigns action. + + This field is a member of `oneof`_ ``operation``. + campaign_asset_operation (google.ads.googleads.v24.services.types.CampaignAssetOperation): + A campaign asset mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_asset_set_operation (google.ads.googleads.v24.services.types.CampaignAssetSetOperation): + A campaign asset mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_bid_modifier_operation (google.ads.googleads.v24.services.types.CampaignBidModifierOperation): + A campaign bid modifier mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_budget_operation (google.ads.googleads.v24.services.types.CampaignBudgetOperation): + A campaign budget mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_conversion_goal_operation (google.ads.googleads.v24.services.types.CampaignConversionGoalOperation): + A campaign conversion goal mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_criterion_operation (google.ads.googleads.v24.services.types.CampaignCriterionOperation): + A campaign criterion mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_customizer_operation (google.ads.googleads.v24.services.types.CampaignCustomizerOperation): + A campaign customizer mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_draft_operation (google.ads.googleads.v24.services.types.CampaignDraftOperation): + A campaign draft mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_group_operation (google.ads.googleads.v24.services.types.CampaignGroupOperation): + A campaign group mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_label_operation (google.ads.googleads.v24.services.types.CampaignLabelOperation): + A campaign label mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_operation (google.ads.googleads.v24.services.types.CampaignOperation): + A campaign mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_shared_set_operation (google.ads.googleads.v24.services.types.CampaignSharedSetOperation): + A campaign shared set mutate operation. + + This field is a member of `oneof`_ ``operation``. + conversion_action_operation (google.ads.googleads.v24.services.types.ConversionActionOperation): + A conversion action mutate operation. + + This field is a member of `oneof`_ ``operation``. + conversion_custom_variable_operation (google.ads.googleads.v24.services.types.ConversionCustomVariableOperation): + A conversion custom variable mutate + operation. + + This field is a member of `oneof`_ ``operation``. + conversion_goal_campaign_config_operation (google.ads.googleads.v24.services.types.ConversionGoalCampaignConfigOperation): + A conversion goal campaign config mutate + operation. + + This field is a member of `oneof`_ ``operation``. + conversion_value_rule_operation (google.ads.googleads.v24.services.types.ConversionValueRuleOperation): + A conversion value rule mutate operation. + + This field is a member of `oneof`_ ``operation``. + conversion_value_rule_set_operation (google.ads.googleads.v24.services.types.ConversionValueRuleSetOperation): + A conversion value rule set mutate operation. + + This field is a member of `oneof`_ ``operation``. + custom_conversion_goal_operation (google.ads.googleads.v24.services.types.CustomConversionGoalOperation): + A custom conversion goal mutate operation. + + This field is a member of `oneof`_ ``operation``. + customer_asset_operation (google.ads.googleads.v24.services.types.CustomerAssetOperation): + A customer asset mutate operation. + + This field is a member of `oneof`_ ``operation``. + customer_conversion_goal_operation (google.ads.googleads.v24.services.types.CustomerConversionGoalOperation): + A customer conversion goal mutate operation. + + This field is a member of `oneof`_ ``operation``. + customer_customizer_operation (google.ads.googleads.v24.services.types.CustomerCustomizerOperation): + A customer customizer mutate operation. + + This field is a member of `oneof`_ ``operation``. + customer_label_operation (google.ads.googleads.v24.services.types.CustomerLabelOperation): + A customer label mutate operation. + + This field is a member of `oneof`_ ``operation``. + customer_negative_criterion_operation (google.ads.googleads.v24.services.types.CustomerNegativeCriterionOperation): + A customer negative criterion mutate + operation. + + This field is a member of `oneof`_ ``operation``. + customer_operation (google.ads.googleads.v24.services.types.CustomerOperation): + A customer mutate operation. + + This field is a member of `oneof`_ ``operation``. + customizer_attribute_operation (google.ads.googleads.v24.services.types.CustomizerAttributeOperation): + A customizer attribute mutate operation. + + This field is a member of `oneof`_ ``operation``. + experiment_operation (google.ads.googleads.v24.services.types.ExperimentOperation): + An experiment mutate operation. + + This field is a member of `oneof`_ ``operation``. + experiment_arm_operation (google.ads.googleads.v24.services.types.ExperimentArmOperation): + An experiment arm mutate operation. + + This field is a member of `oneof`_ ``operation``. + keyword_plan_ad_group_operation (google.ads.googleads.v24.services.types.KeywordPlanAdGroupOperation): + A keyword plan ad group operation. + + This field is a member of `oneof`_ ``operation``. + keyword_plan_ad_group_keyword_operation (google.ads.googleads.v24.services.types.KeywordPlanAdGroupKeywordOperation): + A keyword plan ad group keyword operation. + + This field is a member of `oneof`_ ``operation``. + keyword_plan_campaign_keyword_operation (google.ads.googleads.v24.services.types.KeywordPlanCampaignKeywordOperation): + A keyword plan campaign keyword operation. + + This field is a member of `oneof`_ ``operation``. + keyword_plan_campaign_operation (google.ads.googleads.v24.services.types.KeywordPlanCampaignOperation): + A keyword plan campaign operation. + + This field is a member of `oneof`_ ``operation``. + keyword_plan_operation (google.ads.googleads.v24.services.types.KeywordPlanOperation): + A keyword plan operation. + + This field is a member of `oneof`_ ``operation``. + label_operation (google.ads.googleads.v24.services.types.LabelOperation): + A label mutate operation. + + This field is a member of `oneof`_ ``operation``. + quote_campaigns_operation (google.ads.googleads.v24.actions.types.QuoteCampaignsOperation): + Request message for the QuoteCampaigns action. Requests + using this operation must set validate_only to true. + + This field is a member of `oneof`_ ``operation``. + recommendation_subscription_operation (google.ads.googleads.v24.services.types.RecommendationSubscriptionOperation): + A recommendation subscription mutate + operation. + + This field is a member of `oneof`_ ``operation``. + remarketing_action_operation (google.ads.googleads.v24.services.types.RemarketingActionOperation): + A remarketing action mutate operation. + + This field is a member of `oneof`_ ``operation``. + shared_criterion_operation (google.ads.googleads.v24.services.types.SharedCriterionOperation): + A shared criterion mutate operation. + + This field is a member of `oneof`_ ``operation``. + shared_set_operation (google.ads.googleads.v24.services.types.SharedSetOperation): + A shared set mutate operation. + + This field is a member of `oneof`_ ``operation``. + smart_campaign_setting_operation (google.ads.googleads.v24.services.types.SmartCampaignSettingOperation): + A Smart campaign setting mutate operation. + + This field is a member of `oneof`_ ``operation``. + user_list_operation (google.ads.googleads.v24.services.types.UserListOperation): + A user list mutate operation. + + This field is a member of `oneof`_ ``operation``. + """ + + ad_group_ad_label_operation: ( + ad_group_ad_label_service.AdGroupAdLabelOperation + ) = proto.Field( + proto.MESSAGE, + number=17, + oneof="operation", + message=ad_group_ad_label_service.AdGroupAdLabelOperation, + ) + ad_group_ad_operation: ad_group_ad_service.AdGroupAdOperation = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=ad_group_ad_service.AdGroupAdOperation, + ) + ad_group_asset_operation: ad_group_asset_service.AdGroupAssetOperation = ( + proto.Field( + proto.MESSAGE, + number=56, + oneof="operation", + message=ad_group_asset_service.AdGroupAssetOperation, + ) + ) + ad_group_bid_modifier_operation: ( + ad_group_bid_modifier_service.AdGroupBidModifierOperation + ) = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=ad_group_bid_modifier_service.AdGroupBidModifierOperation, + ) + ad_group_criterion_customizer_operation: ( + ad_group_criterion_customizer_service.AdGroupCriterionCustomizerOperation + ) = proto.Field( + proto.MESSAGE, + number=77, + oneof="operation", + message=ad_group_criterion_customizer_service.AdGroupCriterionCustomizerOperation, + ) + ad_group_criterion_label_operation: ( + ad_group_criterion_label_service.AdGroupCriterionLabelOperation + ) = proto.Field( + proto.MESSAGE, + number=18, + oneof="operation", + message=ad_group_criterion_label_service.AdGroupCriterionLabelOperation, + ) + ad_group_criterion_operation: ( + ad_group_criterion_service.AdGroupCriterionOperation + ) = proto.Field( + proto.MESSAGE, + number=3, + oneof="operation", + message=ad_group_criterion_service.AdGroupCriterionOperation, + ) + ad_group_customizer_operation: ( + ad_group_customizer_service.AdGroupCustomizerOperation + ) = proto.Field( + proto.MESSAGE, + number=75, + oneof="operation", + message=ad_group_customizer_service.AdGroupCustomizerOperation, + ) + ad_group_label_operation: ad_group_label_service.AdGroupLabelOperation = ( + proto.Field( + proto.MESSAGE, + number=21, + oneof="operation", + message=ad_group_label_service.AdGroupLabelOperation, + ) + ) + ad_group_operation: ad_group_service.AdGroupOperation = proto.Field( + proto.MESSAGE, + number=5, + oneof="operation", + message=ad_group_service.AdGroupOperation, + ) + ad_operation: ad_service.AdOperation = proto.Field( + proto.MESSAGE, + number=49, + oneof="operation", + message=ad_service.AdOperation, + ) + ad_parameter_operation: ad_parameter_service.AdParameterOperation = ( + proto.Field( + proto.MESSAGE, + number=22, + oneof="operation", + message=ad_parameter_service.AdParameterOperation, + ) + ) + asset_operation: asset_service.AssetOperation = proto.Field( + proto.MESSAGE, + number=23, + oneof="operation", + message=asset_service.AssetOperation, + ) + asset_group_asset_operation: ( + asset_group_asset_service.AssetGroupAssetOperation + ) = proto.Field( + proto.MESSAGE, + number=65, + oneof="operation", + message=asset_group_asset_service.AssetGroupAssetOperation, + ) + asset_group_listing_group_filter_operation: ( + asset_group_listing_group_filter_service.AssetGroupListingGroupFilterOperation + ) = proto.Field( + proto.MESSAGE, + number=78, + oneof="operation", + message=asset_group_listing_group_filter_service.AssetGroupListingGroupFilterOperation, + ) + asset_group_signal_operation: ( + asset_group_signal_service.AssetGroupSignalOperation + ) = proto.Field( + proto.MESSAGE, + number=80, + oneof="operation", + message=asset_group_signal_service.AssetGroupSignalOperation, + ) + asset_group_operation: asset_group_service.AssetGroupOperation = ( + proto.Field( + proto.MESSAGE, + number=62, + oneof="operation", + message=asset_group_service.AssetGroupOperation, + ) + ) + asset_set_asset_operation: ( + asset_set_asset_service.AssetSetAssetOperation + ) = proto.Field( + proto.MESSAGE, + number=71, + oneof="operation", + message=asset_set_asset_service.AssetSetAssetOperation, + ) + asset_set_operation: asset_set_service.AssetSetOperation = proto.Field( + proto.MESSAGE, + number=72, + oneof="operation", + message=asset_set_service.AssetSetOperation, + ) + audience_operation: audience_service.AudienceOperation = proto.Field( + proto.MESSAGE, + number=81, + oneof="operation", + message=audience_service.AudienceOperation, + ) + bidding_data_exclusion_operation: ( + bidding_data_exclusion_service.BiddingDataExclusionOperation + ) = proto.Field( + proto.MESSAGE, + number=58, + oneof="operation", + message=bidding_data_exclusion_service.BiddingDataExclusionOperation, + ) + bidding_seasonality_adjustment_operation: ( + bidding_seasonality_adjustment_service.BiddingSeasonalityAdjustmentOperation + ) = proto.Field( + proto.MESSAGE, + number=59, + oneof="operation", + message=bidding_seasonality_adjustment_service.BiddingSeasonalityAdjustmentOperation, + ) + bidding_strategy_operation: ( + bidding_strategy_service.BiddingStrategyOperation + ) = proto.Field( + proto.MESSAGE, + number=6, + oneof="operation", + message=bidding_strategy_service.BiddingStrategyOperation, + ) + book_campaigns_operation: book_campaigns.BookCampaignsOperation = ( + proto.Field( + proto.MESSAGE, + number=89, + oneof="operation", + message=book_campaigns.BookCampaignsOperation, + ) + ) + campaign_asset_operation: campaign_asset_service.CampaignAssetOperation = ( + proto.Field( + proto.MESSAGE, + number=52, + oneof="operation", + message=campaign_asset_service.CampaignAssetOperation, + ) + ) + campaign_asset_set_operation: ( + campaign_asset_set_service.CampaignAssetSetOperation + ) = proto.Field( + proto.MESSAGE, + number=73, + oneof="operation", + message=campaign_asset_set_service.CampaignAssetSetOperation, + ) + campaign_bid_modifier_operation: ( + campaign_bid_modifier_service.CampaignBidModifierOperation + ) = proto.Field( + proto.MESSAGE, + number=7, + oneof="operation", + message=campaign_bid_modifier_service.CampaignBidModifierOperation, + ) + campaign_budget_operation: ( + campaign_budget_service.CampaignBudgetOperation + ) = proto.Field( + proto.MESSAGE, + number=8, + oneof="operation", + message=campaign_budget_service.CampaignBudgetOperation, + ) + campaign_conversion_goal_operation: ( + campaign_conversion_goal_service.CampaignConversionGoalOperation + ) = proto.Field( + proto.MESSAGE, + number=67, + oneof="operation", + message=campaign_conversion_goal_service.CampaignConversionGoalOperation, + ) + campaign_criterion_operation: ( + campaign_criterion_service.CampaignCriterionOperation + ) = proto.Field( + proto.MESSAGE, + number=13, + oneof="operation", + message=campaign_criterion_service.CampaignCriterionOperation, + ) + campaign_customizer_operation: ( + campaign_customizer_service.CampaignCustomizerOperation + ) = proto.Field( + proto.MESSAGE, + number=76, + oneof="operation", + message=campaign_customizer_service.CampaignCustomizerOperation, + ) + campaign_draft_operation: campaign_draft_service.CampaignDraftOperation = ( + proto.Field( + proto.MESSAGE, + number=24, + oneof="operation", + message=campaign_draft_service.CampaignDraftOperation, + ) + ) + campaign_group_operation: campaign_group_service.CampaignGroupOperation = ( + proto.Field( + proto.MESSAGE, + number=9, + oneof="operation", + message=campaign_group_service.CampaignGroupOperation, + ) + ) + campaign_label_operation: campaign_label_service.CampaignLabelOperation = ( + proto.Field( + proto.MESSAGE, + number=28, + oneof="operation", + message=campaign_label_service.CampaignLabelOperation, + ) + ) + campaign_operation: campaign_service.CampaignOperation = proto.Field( + proto.MESSAGE, + number=10, + oneof="operation", + message=campaign_service.CampaignOperation, + ) + campaign_shared_set_operation: ( + campaign_shared_set_service.CampaignSharedSetOperation + ) = proto.Field( + proto.MESSAGE, + number=11, + oneof="operation", + message=campaign_shared_set_service.CampaignSharedSetOperation, + ) + conversion_action_operation: ( + conversion_action_service.ConversionActionOperation + ) = proto.Field( + proto.MESSAGE, + number=12, + oneof="operation", + message=conversion_action_service.ConversionActionOperation, + ) + conversion_custom_variable_operation: ( + conversion_custom_variable_service.ConversionCustomVariableOperation + ) = proto.Field( + proto.MESSAGE, + number=55, + oneof="operation", + message=conversion_custom_variable_service.ConversionCustomVariableOperation, + ) + conversion_goal_campaign_config_operation: ( + conversion_goal_campaign_config_service.ConversionGoalCampaignConfigOperation + ) = proto.Field( + proto.MESSAGE, + number=69, + oneof="operation", + message=conversion_goal_campaign_config_service.ConversionGoalCampaignConfigOperation, + ) + conversion_value_rule_operation: ( + conversion_value_rule_service.ConversionValueRuleOperation + ) = proto.Field( + proto.MESSAGE, + number=63, + oneof="operation", + message=conversion_value_rule_service.ConversionValueRuleOperation, + ) + conversion_value_rule_set_operation: ( + conversion_value_rule_set_service.ConversionValueRuleSetOperation + ) = proto.Field( + proto.MESSAGE, + number=64, + oneof="operation", + message=conversion_value_rule_set_service.ConversionValueRuleSetOperation, + ) + custom_conversion_goal_operation: ( + custom_conversion_goal_service.CustomConversionGoalOperation + ) = proto.Field( + proto.MESSAGE, + number=68, + oneof="operation", + message=custom_conversion_goal_service.CustomConversionGoalOperation, + ) + customer_asset_operation: customer_asset_service.CustomerAssetOperation = ( + proto.Field( + proto.MESSAGE, + number=57, + oneof="operation", + message=customer_asset_service.CustomerAssetOperation, + ) + ) + customer_conversion_goal_operation: ( + customer_conversion_goal_service.CustomerConversionGoalOperation + ) = proto.Field( + proto.MESSAGE, + number=66, + oneof="operation", + message=customer_conversion_goal_service.CustomerConversionGoalOperation, + ) + customer_customizer_operation: ( + customer_customizer_service.CustomerCustomizerOperation + ) = proto.Field( + proto.MESSAGE, + number=79, + oneof="operation", + message=customer_customizer_service.CustomerCustomizerOperation, + ) + customer_label_operation: customer_label_service.CustomerLabelOperation = ( + proto.Field( + proto.MESSAGE, + number=32, + oneof="operation", + message=customer_label_service.CustomerLabelOperation, + ) + ) + customer_negative_criterion_operation: ( + customer_negative_criterion_service.CustomerNegativeCriterionOperation + ) = proto.Field( + proto.MESSAGE, + number=34, + oneof="operation", + message=customer_negative_criterion_service.CustomerNegativeCriterionOperation, + ) + customer_operation: customer_service.CustomerOperation = proto.Field( + proto.MESSAGE, + number=35, + oneof="operation", + message=customer_service.CustomerOperation, + ) + customizer_attribute_operation: ( + customizer_attribute_service.CustomizerAttributeOperation + ) = proto.Field( + proto.MESSAGE, + number=70, + oneof="operation", + message=customizer_attribute_service.CustomizerAttributeOperation, + ) + experiment_operation: experiment_service.ExperimentOperation = proto.Field( + proto.MESSAGE, + number=82, + oneof="operation", + message=experiment_service.ExperimentOperation, + ) + experiment_arm_operation: experiment_arm_service.ExperimentArmOperation = ( + proto.Field( + proto.MESSAGE, + number=83, + oneof="operation", + message=experiment_arm_service.ExperimentArmOperation, + ) + ) + keyword_plan_ad_group_operation: ( + keyword_plan_ad_group_service.KeywordPlanAdGroupOperation + ) = proto.Field( + proto.MESSAGE, + number=44, + oneof="operation", + message=keyword_plan_ad_group_service.KeywordPlanAdGroupOperation, + ) + keyword_plan_ad_group_keyword_operation: ( + keyword_plan_ad_group_keyword_service.KeywordPlanAdGroupKeywordOperation + ) = proto.Field( + proto.MESSAGE, + number=50, + oneof="operation", + message=keyword_plan_ad_group_keyword_service.KeywordPlanAdGroupKeywordOperation, + ) + keyword_plan_campaign_keyword_operation: ( + keyword_plan_campaign_keyword_service.KeywordPlanCampaignKeywordOperation + ) = proto.Field( + proto.MESSAGE, + number=51, + oneof="operation", + message=keyword_plan_campaign_keyword_service.KeywordPlanCampaignKeywordOperation, + ) + keyword_plan_campaign_operation: ( + keyword_plan_campaign_service.KeywordPlanCampaignOperation + ) = proto.Field( + proto.MESSAGE, + number=45, + oneof="operation", + message=keyword_plan_campaign_service.KeywordPlanCampaignOperation, + ) + keyword_plan_operation: keyword_plan_service.KeywordPlanOperation = ( + proto.Field( + proto.MESSAGE, + number=48, + oneof="operation", + message=keyword_plan_service.KeywordPlanOperation, + ) + ) + label_operation: label_service.LabelOperation = proto.Field( + proto.MESSAGE, + number=41, + oneof="operation", + message=label_service.LabelOperation, + ) + quote_campaigns_operation: quote_campaigns.QuoteCampaignsOperation = ( + proto.Field( + proto.MESSAGE, + number=88, + oneof="operation", + message=quote_campaigns.QuoteCampaignsOperation, + ) + ) + recommendation_subscription_operation: ( + recommendation_subscription_service.RecommendationSubscriptionOperation + ) = proto.Field( + proto.MESSAGE, + number=86, + oneof="operation", + message=recommendation_subscription_service.RecommendationSubscriptionOperation, + ) + remarketing_action_operation: ( + remarketing_action_service.RemarketingActionOperation + ) = proto.Field( + proto.MESSAGE, + number=43, + oneof="operation", + message=remarketing_action_service.RemarketingActionOperation, + ) + shared_criterion_operation: ( + shared_criterion_service.SharedCriterionOperation + ) = proto.Field( + proto.MESSAGE, + number=14, + oneof="operation", + message=shared_criterion_service.SharedCriterionOperation, + ) + shared_set_operation: shared_set_service.SharedSetOperation = proto.Field( + proto.MESSAGE, + number=15, + oneof="operation", + message=shared_set_service.SharedSetOperation, + ) + smart_campaign_setting_operation: ( + smart_campaign_setting_service.SmartCampaignSettingOperation + ) = proto.Field( + proto.MESSAGE, + number=61, + oneof="operation", + message=smart_campaign_setting_service.SmartCampaignSettingOperation, + ) + user_list_operation: user_list_service.UserListOperation = proto.Field( + proto.MESSAGE, + number=16, + oneof="operation", + message=user_list_service.UserListOperation, + ) + + +class MutateOperationResponse(proto.Message): + r"""Response message for the resource mutate or action. + + 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: + ad_group_ad_label_result (google.ads.googleads.v24.services.types.MutateAdGroupAdLabelResult): + The result for the ad group ad label mutate. + + This field is a member of `oneof`_ ``response``. + ad_group_ad_result (google.ads.googleads.v24.services.types.MutateAdGroupAdResult): + The result for the ad group ad mutate. + + This field is a member of `oneof`_ ``response``. + ad_group_asset_result (google.ads.googleads.v24.services.types.MutateAdGroupAssetResult): + The result for the ad group asset mutate. + + This field is a member of `oneof`_ ``response``. + ad_group_bid_modifier_result (google.ads.googleads.v24.services.types.MutateAdGroupBidModifierResult): + The result for the ad group bid modifier + mutate. + + This field is a member of `oneof`_ ``response``. + ad_group_criterion_customizer_result (google.ads.googleads.v24.services.types.MutateAdGroupCriterionCustomizerResult): + The result for the ad group criterion + customizer mutate. + + This field is a member of `oneof`_ ``response``. + ad_group_criterion_label_result (google.ads.googleads.v24.services.types.MutateAdGroupCriterionLabelResult): + The result for the ad group criterion label + mutate. + + This field is a member of `oneof`_ ``response``. + ad_group_criterion_result (google.ads.googleads.v24.services.types.MutateAdGroupCriterionResult): + The result for the ad group criterion mutate. + + This field is a member of `oneof`_ ``response``. + ad_group_customizer_result (google.ads.googleads.v24.services.types.MutateAdGroupCustomizerResult): + The result for the ad group customizer + mutate. + + This field is a member of `oneof`_ ``response``. + ad_group_label_result (google.ads.googleads.v24.services.types.MutateAdGroupLabelResult): + The result for the ad group label mutate. + + This field is a member of `oneof`_ ``response``. + ad_group_result (google.ads.googleads.v24.services.types.MutateAdGroupResult): + The result for the ad group mutate. + + This field is a member of `oneof`_ ``response``. + ad_parameter_result (google.ads.googleads.v24.services.types.MutateAdParameterResult): + The result for the ad parameter mutate. + + This field is a member of `oneof`_ ``response``. + ad_result (google.ads.googleads.v24.services.types.MutateAdResult): + The result for the ad mutate. + + This field is a member of `oneof`_ ``response``. + asset_result (google.ads.googleads.v24.services.types.MutateAssetResult): + The result for the asset mutate. + + This field is a member of `oneof`_ ``response``. + asset_group_asset_result (google.ads.googleads.v24.services.types.MutateAssetGroupAssetResult): + The result for the asset group asset mutate. + + This field is a member of `oneof`_ ``response``. + asset_group_listing_group_filter_result (google.ads.googleads.v24.services.types.MutateAssetGroupListingGroupFilterResult): + The result for the asset group listing group + filter mutate. + + This field is a member of `oneof`_ ``response``. + asset_group_signal_result (google.ads.googleads.v24.services.types.MutateAssetGroupSignalResult): + The result for the asset group signal mutate. + + This field is a member of `oneof`_ ``response``. + asset_group_result (google.ads.googleads.v24.services.types.MutateAssetGroupResult): + The result for the asset group mutate. + + This field is a member of `oneof`_ ``response``. + asset_set_asset_result (google.ads.googleads.v24.services.types.MutateAssetSetAssetResult): + The result for the asset set asset mutate. + + This field is a member of `oneof`_ ``response``. + asset_set_result (google.ads.googleads.v24.services.types.MutateAssetSetResult): + The result for the asset set mutate. + + This field is a member of `oneof`_ ``response``. + audience_result (google.ads.googleads.v24.services.types.MutateAudienceResult): + The result for the audience mutate. + + This field is a member of `oneof`_ ``response``. + bidding_data_exclusion_result (google.ads.googleads.v24.services.types.MutateBiddingDataExclusionsResult): + The result for the bidding data exclusion + mutate. + + This field is a member of `oneof`_ ``response``. + bidding_seasonality_adjustment_result (google.ads.googleads.v24.services.types.MutateBiddingSeasonalityAdjustmentsResult): + The result for the bidding seasonality + adjustment mutate. + + This field is a member of `oneof`_ ``response``. + bidding_strategy_result (google.ads.googleads.v24.services.types.MutateBiddingStrategyResult): + The result for the bidding strategy mutate. + + This field is a member of `oneof`_ ``response``. + book_campaigns_result (google.ads.googleads.v24.actions.types.BookCampaignsResult): + The result for the BookCampaigns action. + + This field is a member of `oneof`_ ``response``. + campaign_asset_result (google.ads.googleads.v24.services.types.MutateCampaignAssetResult): + The result for the campaign asset mutate. + + This field is a member of `oneof`_ ``response``. + campaign_asset_set_result (google.ads.googleads.v24.services.types.MutateCampaignAssetSetResult): + The result for the campaign asset set mutate. + + This field is a member of `oneof`_ ``response``. + campaign_bid_modifier_result (google.ads.googleads.v24.services.types.MutateCampaignBidModifierResult): + The result for the campaign bid modifier + mutate. + + This field is a member of `oneof`_ ``response``. + campaign_budget_result (google.ads.googleads.v24.services.types.MutateCampaignBudgetResult): + The result for the campaign budget mutate. + + This field is a member of `oneof`_ ``response``. + campaign_conversion_goal_result (google.ads.googleads.v24.services.types.MutateCampaignConversionGoalResult): + The result for the campaign conversion goal + mutate. + + This field is a member of `oneof`_ ``response``. + campaign_criterion_result (google.ads.googleads.v24.services.types.MutateCampaignCriterionResult): + The result for the campaign criterion mutate. + + This field is a member of `oneof`_ ``response``. + campaign_customizer_result (google.ads.googleads.v24.services.types.MutateCampaignCustomizerResult): + The result for the campaign customizer + mutate. + + This field is a member of `oneof`_ ``response``. + campaign_draft_result (google.ads.googleads.v24.services.types.MutateCampaignDraftResult): + The result for the campaign draft mutate. + + This field is a member of `oneof`_ ``response``. + campaign_group_result (google.ads.googleads.v24.services.types.MutateCampaignGroupResult): + The result for the campaign group mutate. + + This field is a member of `oneof`_ ``response``. + campaign_label_result (google.ads.googleads.v24.services.types.MutateCampaignLabelResult): + The result for the campaign label mutate. + + This field is a member of `oneof`_ ``response``. + campaign_result (google.ads.googleads.v24.services.types.MutateCampaignResult): + The result for the campaign mutate. + + This field is a member of `oneof`_ ``response``. + campaign_shared_set_result (google.ads.googleads.v24.services.types.MutateCampaignSharedSetResult): + The result for the campaign shared set + mutate. + + This field is a member of `oneof`_ ``response``. + conversion_action_result (google.ads.googleads.v24.services.types.MutateConversionActionResult): + The result for the conversion action mutate. + + This field is a member of `oneof`_ ``response``. + conversion_custom_variable_result (google.ads.googleads.v24.services.types.MutateConversionCustomVariableResult): + The result for the conversion custom variable + mutate. + + This field is a member of `oneof`_ ``response``. + conversion_goal_campaign_config_result (google.ads.googleads.v24.services.types.MutateConversionGoalCampaignConfigResult): + The result for the conversion goal campaign + config mutate. + + This field is a member of `oneof`_ ``response``. + conversion_value_rule_result (google.ads.googleads.v24.services.types.MutateConversionValueRuleResult): + The result for the conversion value rule + mutate. + + This field is a member of `oneof`_ ``response``. + conversion_value_rule_set_result (google.ads.googleads.v24.services.types.MutateConversionValueRuleSetResult): + The result for the conversion value rule set + mutate. + + This field is a member of `oneof`_ ``response``. + custom_conversion_goal_result (google.ads.googleads.v24.services.types.MutateCustomConversionGoalResult): + The result for the custom conversion goal + mutate. + + This field is a member of `oneof`_ ``response``. + customer_asset_result (google.ads.googleads.v24.services.types.MutateCustomerAssetResult): + The result for the customer asset mutate. + + This field is a member of `oneof`_ ``response``. + customer_conversion_goal_result (google.ads.googleads.v24.services.types.MutateCustomerConversionGoalResult): + The result for the customer conversion goal + mutate. + + This field is a member of `oneof`_ ``response``. + customer_customizer_result (google.ads.googleads.v24.services.types.MutateCustomerCustomizerResult): + The result for the customer customizer + mutate. + + This field is a member of `oneof`_ ``response``. + customer_label_result (google.ads.googleads.v24.services.types.MutateCustomerLabelResult): + The result for the customer label mutate. + + This field is a member of `oneof`_ ``response``. + customer_negative_criterion_result (google.ads.googleads.v24.services.types.MutateCustomerNegativeCriteriaResult): + The result for the customer negative + criterion mutate. + + This field is a member of `oneof`_ ``response``. + customer_result (google.ads.googleads.v24.services.types.MutateCustomerResult): + The result for the customer mutate. + + This field is a member of `oneof`_ ``response``. + customizer_attribute_result (google.ads.googleads.v24.services.types.MutateCustomizerAttributeResult): + The result for the customizer attribute + mutate. + + This field is a member of `oneof`_ ``response``. + experiment_result (google.ads.googleads.v24.services.types.MutateExperimentResult): + The result for the experiment mutate. + + This field is a member of `oneof`_ ``response``. + experiment_arm_result (google.ads.googleads.v24.services.types.MutateExperimentArmResult): + The result for the experiment arm mutate. + + This field is a member of `oneof`_ ``response``. + keyword_plan_ad_group_result (google.ads.googleads.v24.services.types.MutateKeywordPlanAdGroupResult): + The result for the keyword plan ad group + mutate. + + This field is a member of `oneof`_ ``response``. + keyword_plan_campaign_result (google.ads.googleads.v24.services.types.MutateKeywordPlanCampaignResult): + The result for the keyword plan campaign + mutate. + + This field is a member of `oneof`_ ``response``. + keyword_plan_ad_group_keyword_result (google.ads.googleads.v24.services.types.MutateKeywordPlanAdGroupKeywordResult): + The result for the keyword plan ad group + keyword mutate. + + This field is a member of `oneof`_ ``response``. + keyword_plan_campaign_keyword_result (google.ads.googleads.v24.services.types.MutateKeywordPlanCampaignKeywordResult): + The result for the keyword plan campaign + keyword mutate. + + This field is a member of `oneof`_ ``response``. + keyword_plan_result (google.ads.googleads.v24.services.types.MutateKeywordPlansResult): + The result for the keyword plan mutate. + + This field is a member of `oneof`_ ``response``. + label_result (google.ads.googleads.v24.services.types.MutateLabelResult): + The result for the label mutate. + + This field is a member of `oneof`_ ``response``. + quote_campaigns_result (google.ads.googleads.v24.actions.types.QuoteCampaignsResult): + The result for the QuoteCampaigns action. + + This field is a member of `oneof`_ ``response``. + recommendation_subscription_result (google.ads.googleads.v24.services.types.MutateRecommendationSubscriptionResult): + The result for the recommendation + subscription mutate. + + This field is a member of `oneof`_ ``response``. + remarketing_action_result (google.ads.googleads.v24.services.types.MutateRemarketingActionResult): + The result for the remarketing action mutate. + + This field is a member of `oneof`_ ``response``. + shared_criterion_result (google.ads.googleads.v24.services.types.MutateSharedCriterionResult): + The result for the shared criterion mutate. + + This field is a member of `oneof`_ ``response``. + shared_set_result (google.ads.googleads.v24.services.types.MutateSharedSetResult): + The result for the shared set mutate. + + This field is a member of `oneof`_ ``response``. + smart_campaign_setting_result (google.ads.googleads.v24.services.types.MutateSmartCampaignSettingResult): + The result for the Smart campaign setting + mutate. + + This field is a member of `oneof`_ ``response``. + user_list_result (google.ads.googleads.v24.services.types.MutateUserListResult): + The result for the user list mutate. + + This field is a member of `oneof`_ ``response``. + """ + + ad_group_ad_label_result: ( + ad_group_ad_label_service.MutateAdGroupAdLabelResult + ) = proto.Field( + proto.MESSAGE, + number=17, + oneof="response", + message=ad_group_ad_label_service.MutateAdGroupAdLabelResult, + ) + ad_group_ad_result: ad_group_ad_service.MutateAdGroupAdResult = proto.Field( + proto.MESSAGE, + number=1, + oneof="response", + message=ad_group_ad_service.MutateAdGroupAdResult, + ) + ad_group_asset_result: ad_group_asset_service.MutateAdGroupAssetResult = ( + proto.Field( + proto.MESSAGE, + number=56, + oneof="response", + message=ad_group_asset_service.MutateAdGroupAssetResult, + ) + ) + ad_group_bid_modifier_result: ( + ad_group_bid_modifier_service.MutateAdGroupBidModifierResult + ) = proto.Field( + proto.MESSAGE, + number=2, + oneof="response", + message=ad_group_bid_modifier_service.MutateAdGroupBidModifierResult, + ) + ad_group_criterion_customizer_result: ( + ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizerResult + ) = proto.Field( + proto.MESSAGE, + number=77, + oneof="response", + message=ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizerResult, + ) + ad_group_criterion_label_result: ( + ad_group_criterion_label_service.MutateAdGroupCriterionLabelResult + ) = proto.Field( + proto.MESSAGE, + number=18, + oneof="response", + message=ad_group_criterion_label_service.MutateAdGroupCriterionLabelResult, + ) + ad_group_criterion_result: ( + ad_group_criterion_service.MutateAdGroupCriterionResult + ) = proto.Field( + proto.MESSAGE, + number=3, + oneof="response", + message=ad_group_criterion_service.MutateAdGroupCriterionResult, + ) + ad_group_customizer_result: ( + ad_group_customizer_service.MutateAdGroupCustomizerResult + ) = proto.Field( + proto.MESSAGE, + number=75, + oneof="response", + message=ad_group_customizer_service.MutateAdGroupCustomizerResult, + ) + ad_group_label_result: ad_group_label_service.MutateAdGroupLabelResult = ( + proto.Field( + proto.MESSAGE, + number=21, + oneof="response", + message=ad_group_label_service.MutateAdGroupLabelResult, + ) + ) + ad_group_result: ad_group_service.MutateAdGroupResult = proto.Field( + proto.MESSAGE, + number=5, + oneof="response", + message=ad_group_service.MutateAdGroupResult, + ) + ad_parameter_result: ad_parameter_service.MutateAdParameterResult = ( + proto.Field( + proto.MESSAGE, + number=22, + oneof="response", + message=ad_parameter_service.MutateAdParameterResult, + ) + ) + ad_result: ad_service.MutateAdResult = proto.Field( + proto.MESSAGE, + number=49, + oneof="response", + message=ad_service.MutateAdResult, + ) + asset_result: asset_service.MutateAssetResult = proto.Field( + proto.MESSAGE, + number=23, + oneof="response", + message=asset_service.MutateAssetResult, + ) + asset_group_asset_result: ( + asset_group_asset_service.MutateAssetGroupAssetResult + ) = proto.Field( + proto.MESSAGE, + number=65, + oneof="response", + message=asset_group_asset_service.MutateAssetGroupAssetResult, + ) + asset_group_listing_group_filter_result: ( + asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFilterResult + ) = proto.Field( + proto.MESSAGE, + number=78, + oneof="response", + message=asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFilterResult, + ) + asset_group_signal_result: ( + asset_group_signal_service.MutateAssetGroupSignalResult + ) = proto.Field( + proto.MESSAGE, + number=79, + oneof="response", + message=asset_group_signal_service.MutateAssetGroupSignalResult, + ) + asset_group_result: asset_group_service.MutateAssetGroupResult = ( + proto.Field( + proto.MESSAGE, + number=62, + oneof="response", + message=asset_group_service.MutateAssetGroupResult, + ) + ) + asset_set_asset_result: ( + asset_set_asset_service.MutateAssetSetAssetResult + ) = proto.Field( + proto.MESSAGE, + number=71, + oneof="response", + message=asset_set_asset_service.MutateAssetSetAssetResult, + ) + asset_set_result: asset_set_service.MutateAssetSetResult = proto.Field( + proto.MESSAGE, + number=72, + oneof="response", + message=asset_set_service.MutateAssetSetResult, + ) + audience_result: audience_service.MutateAudienceResult = proto.Field( + proto.MESSAGE, + number=80, + oneof="response", + message=audience_service.MutateAudienceResult, + ) + bidding_data_exclusion_result: ( + bidding_data_exclusion_service.MutateBiddingDataExclusionsResult + ) = proto.Field( + proto.MESSAGE, + number=58, + oneof="response", + message=bidding_data_exclusion_service.MutateBiddingDataExclusionsResult, + ) + bidding_seasonality_adjustment_result: ( + bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsResult + ) = proto.Field( + proto.MESSAGE, + number=59, + oneof="response", + message=bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsResult, + ) + bidding_strategy_result: ( + bidding_strategy_service.MutateBiddingStrategyResult + ) = proto.Field( + proto.MESSAGE, + number=6, + oneof="response", + message=bidding_strategy_service.MutateBiddingStrategyResult, + ) + book_campaigns_result: book_campaigns.BookCampaignsResult = proto.Field( + proto.MESSAGE, + number=89, + oneof="response", + message=book_campaigns.BookCampaignsResult, + ) + campaign_asset_result: campaign_asset_service.MutateCampaignAssetResult = ( + proto.Field( + proto.MESSAGE, + number=52, + oneof="response", + message=campaign_asset_service.MutateCampaignAssetResult, + ) + ) + campaign_asset_set_result: ( + campaign_asset_set_service.MutateCampaignAssetSetResult + ) = proto.Field( + proto.MESSAGE, + number=73, + oneof="response", + message=campaign_asset_set_service.MutateCampaignAssetSetResult, + ) + campaign_bid_modifier_result: ( + campaign_bid_modifier_service.MutateCampaignBidModifierResult + ) = proto.Field( + proto.MESSAGE, + number=7, + oneof="response", + message=campaign_bid_modifier_service.MutateCampaignBidModifierResult, + ) + campaign_budget_result: ( + campaign_budget_service.MutateCampaignBudgetResult + ) = proto.Field( + proto.MESSAGE, + number=8, + oneof="response", + message=campaign_budget_service.MutateCampaignBudgetResult, + ) + campaign_conversion_goal_result: ( + campaign_conversion_goal_service.MutateCampaignConversionGoalResult + ) = proto.Field( + proto.MESSAGE, + number=67, + oneof="response", + message=campaign_conversion_goal_service.MutateCampaignConversionGoalResult, + ) + campaign_criterion_result: ( + campaign_criterion_service.MutateCampaignCriterionResult + ) = proto.Field( + proto.MESSAGE, + number=13, + oneof="response", + message=campaign_criterion_service.MutateCampaignCriterionResult, + ) + campaign_customizer_result: ( + campaign_customizer_service.MutateCampaignCustomizerResult + ) = proto.Field( + proto.MESSAGE, + number=76, + oneof="response", + message=campaign_customizer_service.MutateCampaignCustomizerResult, + ) + campaign_draft_result: campaign_draft_service.MutateCampaignDraftResult = ( + proto.Field( + proto.MESSAGE, + number=24, + oneof="response", + message=campaign_draft_service.MutateCampaignDraftResult, + ) + ) + campaign_group_result: campaign_group_service.MutateCampaignGroupResult = ( + proto.Field( + proto.MESSAGE, + number=9, + oneof="response", + message=campaign_group_service.MutateCampaignGroupResult, + ) + ) + campaign_label_result: campaign_label_service.MutateCampaignLabelResult = ( + proto.Field( + proto.MESSAGE, + number=28, + oneof="response", + message=campaign_label_service.MutateCampaignLabelResult, + ) + ) + campaign_result: campaign_service.MutateCampaignResult = proto.Field( + proto.MESSAGE, + number=10, + oneof="response", + message=campaign_service.MutateCampaignResult, + ) + campaign_shared_set_result: ( + campaign_shared_set_service.MutateCampaignSharedSetResult + ) = proto.Field( + proto.MESSAGE, + number=11, + oneof="response", + message=campaign_shared_set_service.MutateCampaignSharedSetResult, + ) + conversion_action_result: ( + conversion_action_service.MutateConversionActionResult + ) = proto.Field( + proto.MESSAGE, + number=12, + oneof="response", + message=conversion_action_service.MutateConversionActionResult, + ) + conversion_custom_variable_result: ( + conversion_custom_variable_service.MutateConversionCustomVariableResult + ) = proto.Field( + proto.MESSAGE, + number=55, + oneof="response", + message=conversion_custom_variable_service.MutateConversionCustomVariableResult, + ) + conversion_goal_campaign_config_result: ( + conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigResult + ) = proto.Field( + proto.MESSAGE, + number=69, + oneof="response", + message=conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigResult, + ) + conversion_value_rule_result: ( + conversion_value_rule_service.MutateConversionValueRuleResult + ) = proto.Field( + proto.MESSAGE, + number=63, + oneof="response", + message=conversion_value_rule_service.MutateConversionValueRuleResult, + ) + conversion_value_rule_set_result: ( + conversion_value_rule_set_service.MutateConversionValueRuleSetResult + ) = proto.Field( + proto.MESSAGE, + number=64, + oneof="response", + message=conversion_value_rule_set_service.MutateConversionValueRuleSetResult, + ) + custom_conversion_goal_result: ( + custom_conversion_goal_service.MutateCustomConversionGoalResult + ) = proto.Field( + proto.MESSAGE, + number=68, + oneof="response", + message=custom_conversion_goal_service.MutateCustomConversionGoalResult, + ) + customer_asset_result: customer_asset_service.MutateCustomerAssetResult = ( + proto.Field( + proto.MESSAGE, + number=57, + oneof="response", + message=customer_asset_service.MutateCustomerAssetResult, + ) + ) + customer_conversion_goal_result: ( + customer_conversion_goal_service.MutateCustomerConversionGoalResult + ) = proto.Field( + proto.MESSAGE, + number=66, + oneof="response", + message=customer_conversion_goal_service.MutateCustomerConversionGoalResult, + ) + customer_customizer_result: ( + customer_customizer_service.MutateCustomerCustomizerResult + ) = proto.Field( + proto.MESSAGE, + number=74, + oneof="response", + message=customer_customizer_service.MutateCustomerCustomizerResult, + ) + customer_label_result: customer_label_service.MutateCustomerLabelResult = ( + proto.Field( + proto.MESSAGE, + number=32, + oneof="response", + message=customer_label_service.MutateCustomerLabelResult, + ) + ) + customer_negative_criterion_result: ( + customer_negative_criterion_service.MutateCustomerNegativeCriteriaResult + ) = proto.Field( + proto.MESSAGE, + number=34, + oneof="response", + message=customer_negative_criterion_service.MutateCustomerNegativeCriteriaResult, + ) + customer_result: customer_service.MutateCustomerResult = proto.Field( + proto.MESSAGE, + number=35, + oneof="response", + message=customer_service.MutateCustomerResult, + ) + customizer_attribute_result: ( + customizer_attribute_service.MutateCustomizerAttributeResult + ) = proto.Field( + proto.MESSAGE, + number=70, + oneof="response", + message=customizer_attribute_service.MutateCustomizerAttributeResult, + ) + experiment_result: experiment_service.MutateExperimentResult = proto.Field( + proto.MESSAGE, + number=81, + oneof="response", + message=experiment_service.MutateExperimentResult, + ) + experiment_arm_result: experiment_arm_service.MutateExperimentArmResult = ( + proto.Field( + proto.MESSAGE, + number=82, + oneof="response", + message=experiment_arm_service.MutateExperimentArmResult, + ) + ) + keyword_plan_ad_group_result: ( + keyword_plan_ad_group_service.MutateKeywordPlanAdGroupResult + ) = proto.Field( + proto.MESSAGE, + number=44, + oneof="response", + message=keyword_plan_ad_group_service.MutateKeywordPlanAdGroupResult, + ) + keyword_plan_campaign_result: ( + keyword_plan_campaign_service.MutateKeywordPlanCampaignResult + ) = proto.Field( + proto.MESSAGE, + number=45, + oneof="response", + message=keyword_plan_campaign_service.MutateKeywordPlanCampaignResult, + ) + keyword_plan_ad_group_keyword_result: ( + keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordResult + ) = proto.Field( + proto.MESSAGE, + number=50, + oneof="response", + message=keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordResult, + ) + keyword_plan_campaign_keyword_result: ( + keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordResult + ) = proto.Field( + proto.MESSAGE, + number=51, + oneof="response", + message=keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordResult, + ) + keyword_plan_result: keyword_plan_service.MutateKeywordPlansResult = ( + proto.Field( + proto.MESSAGE, + number=48, + oneof="response", + message=keyword_plan_service.MutateKeywordPlansResult, + ) + ) + label_result: label_service.MutateLabelResult = proto.Field( + proto.MESSAGE, + number=41, + oneof="response", + message=label_service.MutateLabelResult, + ) + quote_campaigns_result: quote_campaigns.QuoteCampaignsResult = proto.Field( + proto.MESSAGE, + number=88, + oneof="response", + message=quote_campaigns.QuoteCampaignsResult, + ) + recommendation_subscription_result: ( + recommendation_subscription_service.MutateRecommendationSubscriptionResult + ) = proto.Field( + proto.MESSAGE, + number=85, + oneof="response", + message=recommendation_subscription_service.MutateRecommendationSubscriptionResult, + ) + remarketing_action_result: ( + remarketing_action_service.MutateRemarketingActionResult + ) = proto.Field( + proto.MESSAGE, + number=43, + oneof="response", + message=remarketing_action_service.MutateRemarketingActionResult, + ) + shared_criterion_result: ( + shared_criterion_service.MutateSharedCriterionResult + ) = proto.Field( + proto.MESSAGE, + number=14, + oneof="response", + message=shared_criterion_service.MutateSharedCriterionResult, + ) + shared_set_result: shared_set_service.MutateSharedSetResult = proto.Field( + proto.MESSAGE, + number=15, + oneof="response", + message=shared_set_service.MutateSharedSetResult, + ) + smart_campaign_setting_result: ( + smart_campaign_setting_service.MutateSmartCampaignSettingResult + ) = proto.Field( + proto.MESSAGE, + number=61, + oneof="response", + message=smart_campaign_setting_service.MutateSmartCampaignSettingResult, + ) + user_list_result: user_list_service.MutateUserListResult = proto.Field( + proto.MESSAGE, + number=16, + oneof="response", + message=user_list_service.MutateUserListResult, + ) + + +class SearchSettings(proto.Message): + r"""Indicates search settings in request parameter. + + Attributes: + omit_results (bool): + If true, results will be excluded from the + response. Otherwise, results will be returned. + Default is false. + return_summary_row (bool): + If true, summary row will be included in the + response and sent in a response by itself after + all other query results are returned. Default is + false. + return_total_results_count (bool): + If true, the total number of results that + match the query ignoring the LIMIT clause will + be included in the response. Default is false. + """ + + omit_results: bool = proto.Field( + proto.BOOL, + number=1, + ) + return_summary_row: bool = proto.Field( + proto.BOOL, + number=2, + ) + return_total_results_count: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class MetricAttributes(proto.Message): + r"""Indicates the attributes of metrics. + + Attributes: + name (str): + The name of the metric. + attributes (MutableSequence[google.ads.googleads.v24.services.types.MetricAttributes.Attribute]): + The attributes of the metric. + """ + + class Attribute(proto.Message): + r"""The attribute of the metric in key value pair format. + + Attributes: + key (str): + The key of the attribute. + value (str): + The value of the attribute. + """ + + key: str = proto.Field( + proto.STRING, + number=1, + ) + value: str = proto.Field( + proto.STRING, + number=2, + ) + + name: str = proto.Field( + proto.STRING, + number=1, + ) + attributes: MutableSequence[Attribute] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=Attribute, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/identity_verification_service.py b/google/ads/googleads/v24/services/types/identity_verification_service.py new file mode 100644 index 000000000..3727c6c19 --- /dev/null +++ b/google/ads/googleads/v24/services/types/identity_verification_service.py @@ -0,0 +1,200 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import identity_verification_program +from google.ads.googleads.v24.enums.types import ( + identity_verification_program_status, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "StartIdentityVerificationRequest", + "GetIdentityVerificationRequest", + "GetIdentityVerificationResponse", + "IdentityVerification", + "IdentityVerificationProgress", + "IdentityVerificationRequirement", + }, +) + + +class StartIdentityVerificationRequest(proto.Message): + r"""Request message for + [StartIdentityVerification][google.ads.googleads.v24.services.IdentityVerificationService.StartIdentityVerification]. + + Attributes: + customer_id (str): + Required. The Id of the customer for whom we + are creating this verification. + verification_program (google.ads.googleads.v24.enums.types.IdentityVerificationProgramEnum.IdentityVerificationProgram): + Required. The verification program type for + which we want to start the verification. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + verification_program: ( + identity_verification_program.IdentityVerificationProgramEnum.IdentityVerificationProgram + ) = proto.Field( + proto.ENUM, + number=2, + enum=identity_verification_program.IdentityVerificationProgramEnum.IdentityVerificationProgram, + ) + + +class GetIdentityVerificationRequest(proto.Message): + r"""Request message for + [GetIdentityVerification][google.ads.googleads.v24.services.IdentityVerificationService.GetIdentityVerification]. + + Attributes: + customer_id (str): + Required. The ID of the customer for whom we + are requesting verification information. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + + +class GetIdentityVerificationResponse(proto.Message): + r"""Response message for + [GetIdentityVerification][google.ads.googleads.v24.services.IdentityVerificationService.GetIdentityVerification]. + + Attributes: + identity_verification (MutableSequence[google.ads.googleads.v24.services.types.IdentityVerification]): + List of identity verifications for the + customer. + """ + + identity_verification: MutableSequence["IdentityVerification"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="IdentityVerification", + ) + ) + + +class IdentityVerification(proto.Message): + r"""An identity verification for a customer. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + verification_program (google.ads.googleads.v24.enums.types.IdentityVerificationProgramEnum.IdentityVerificationProgram): + The verification program type. + identity_verification_requirement (google.ads.googleads.v24.services.types.IdentityVerificationRequirement): + The verification requirement for this + verification program for this customer. + + This field is a member of `oneof`_ ``_identity_verification_requirement``. + verification_progress (google.ads.googleads.v24.services.types.IdentityVerificationProgress): + Information regarding progress for this + verification program for this customer. + + This field is a member of `oneof`_ ``_verification_progress``. + """ + + verification_program: ( + identity_verification_program.IdentityVerificationProgramEnum.IdentityVerificationProgram + ) = proto.Field( + proto.ENUM, + number=1, + enum=identity_verification_program.IdentityVerificationProgramEnum.IdentityVerificationProgram, + ) + identity_verification_requirement: "IdentityVerificationRequirement" = ( + proto.Field( + proto.MESSAGE, + number=2, + optional=True, + message="IdentityVerificationRequirement", + ) + ) + verification_progress: "IdentityVerificationProgress" = proto.Field( + proto.MESSAGE, + number=3, + optional=True, + message="IdentityVerificationProgress", + ) + + +class IdentityVerificationProgress(proto.Message): + r"""Information regarding the verification progress for a + verification program type. + + Attributes: + program_status (google.ads.googleads.v24.enums.types.IdentityVerificationProgramStatusEnum.IdentityVerificationProgramStatus): + Current Status (PENDING_USER_ACTION, SUCCESS, FAILURE etc) + invitation_link_expiration_time (str): + The timestamp when the action url will expire + in "yyyy-MM-dd HH:mm:ss" format. + action_url (str): + Action URL for user to complete verification + for the given verification program type. + """ + + program_status: ( + identity_verification_program_status.IdentityVerificationProgramStatusEnum.IdentityVerificationProgramStatus + ) = proto.Field( + proto.ENUM, + number=1, + enum=identity_verification_program_status.IdentityVerificationProgramStatusEnum.IdentityVerificationProgramStatus, + ) + invitation_link_expiration_time: str = proto.Field( + proto.STRING, + number=2, + ) + action_url: str = proto.Field( + proto.STRING, + number=3, + ) + + +class IdentityVerificationRequirement(proto.Message): + r"""Information regarding the verification requirement for a + verification program type. + + Attributes: + verification_start_deadline_time (str): + The deadline to start verification in + "yyyy-MM-dd HH:mm:ss" format. + verification_completion_deadline_time (str): + The deadline to submit verification. + """ + + verification_start_deadline_time: str = proto.Field( + proto.STRING, + number=1, + ) + verification_completion_deadline_time: str = proto.Field( + proto.STRING, + number=2, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/incentive_service.py b/google/ads/googleads/v24/services/types/incentive_service.py new file mode 100644 index 000000000..142dca4ee --- /dev/null +++ b/google/ads/googleads/v24/services/types/incentive_service.py @@ -0,0 +1,434 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.type import money_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "FetchIncentiveRequest", + "Incentive", + "CyoIncentives", + "IncentiveOffer", + "FetchIncentiveResponse", + "ApplyIncentiveRequest", + "ApplyIncentiveResponse", + }, +) + + +class FetchIncentiveRequest(proto.Message): + r"""Request for getting the acquisition incentive for a user. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + language_code (str): + Optional. User's language code. + If not provided, the server will default to + "en". Possible language codes: + + https://developers.google.com/google-ads/api/data/codes-formats#languages + + This field is a member of `oneof`_ ``_language_code``. + country_code (str): + Optional. User's country code. If not provided, the server + will default to "US". Possible country codes: + https://developers.google.com/google-ads/api/data/codes-formats#country_codes + + This field is a member of `oneof`_ ``_country_code``. + email (str): + Optional. Email of the user that the + requested incentive is meant for. Will be used + for channel partners who do NOT use OAuth to + authenticate on behalf of user. + + This field is a member of `oneof`_ ``_email``. + type_ (google.ads.googleads.v24.services.types.FetchIncentiveRequest.IncentiveType): + Optional. The type of incentive to get. + Defaults to ACQUISITION. + + This field is a member of `oneof`_ ``_type``. + """ + + class IncentiveType(proto.Enum): + r"""Types of incentives offered + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Unknown incentive type. Should not be used as + a value explicitly. + ACQUISITION (2): + An acquisition incentive. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ACQUISITION = 2 + + language_code: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + country_code: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + email: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + type_: IncentiveType = proto.Field( + proto.ENUM, + number=4, + optional=True, + enum=IncentiveType, + ) + + +class Incentive(proto.Message): + r"""An incentive that a user can claim for their account. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + incentive_id (int): + The incentive ID of this incentive. This is + used to identify which incentive is selected by + the user in the CYO flow. + + This field is a member of `oneof`_ ``_incentive_id``. + requirement (google.ads.googleads.v24.services.types.Incentive.Requirement): + The requirement for this incentive. + + This field is a member of `oneof`_ ``_requirement``. + incentive_terms_and_conditions_url (str): + The URL of the terms and conditions for THIS incentive offer + ONLY. + + This is different from the terms_and_conditions_url field in + AcquisitionIncentiveOffer which is a combination of all the + Incentive offers in a CYO offer. + + This field is a member of `oneof`_ ``_incentive_terms_and_conditions_url``. + type_ (google.ads.googleads.v24.services.types.FetchIncentiveRequest.IncentiveType): + The type of the incentive. + + This field is a member of `oneof`_ ``_type``. + """ + + class Requirement(proto.Message): + r"""Requirement for an incentive. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + spend (google.ads.googleads.v24.services.types.Incentive.Requirement.Spend): + Optional. Spend requirement for an incentive. + + This field is a member of `oneof`_ ``requirement``. + """ + + class Spend(proto.Message): + r"""Spend requirements for an incentive. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + award_amount (google.type.money_pb2.Money): + Required. Amount in free spend that user will + be granted after spending target amount. + Denominated in the currency of the country + passed in the get request. + + This field is a member of `oneof`_ ``_award_amount``. + required_amount (google.type.money_pb2.Money): + Required. Amount that user must spend to + receive the award amount. Denominated in the + currency of the country passed in the get + request. + + This field is a member of `oneof`_ ``_required_amount``. + """ + + award_amount: money_pb2.Money = proto.Field( + proto.MESSAGE, + number=1, + optional=True, + message=money_pb2.Money, + ) + required_amount: money_pb2.Money = proto.Field( + proto.MESSAGE, + number=2, + optional=True, + message=money_pb2.Money, + ) + + spend: "Incentive.Requirement.Spend" = proto.Field( + proto.MESSAGE, + number=1, + oneof="requirement", + message="Incentive.Requirement.Spend", + ) + + incentive_id: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + requirement: Requirement = proto.Field( + proto.MESSAGE, + number=2, + optional=True, + message=Requirement, + ) + incentive_terms_and_conditions_url: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + type_: "FetchIncentiveRequest.IncentiveType" = proto.Field( + proto.ENUM, + number=4, + optional=True, + enum="FetchIncentiveRequest.IncentiveType", + ) + + +class CyoIncentives(proto.Message): + r"""An incentive offer in the Choose-Your-Own Incentive feature + where a user can select from a set of incentives with different + money amounts. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + low_offer (google.ads.googleads.v24.services.types.Incentive): + Required. The CYO incentive with low target + and award amounts. + + This field is a member of `oneof`_ ``_low_offer``. + medium_offer (google.ads.googleads.v24.services.types.Incentive): + Required. The CYO incentive with medium + target and award amounts. + + This field is a member of `oneof`_ ``_medium_offer``. + high_offer (google.ads.googleads.v24.services.types.Incentive): + Required. The CYO incentive with high target + and award amounts. + + This field is a member of `oneof`_ ``_high_offer``. + """ + + low_offer: "Incentive" = proto.Field( + proto.MESSAGE, + number=1, + optional=True, + message="Incentive", + ) + medium_offer: "Incentive" = proto.Field( + proto.MESSAGE, + number=2, + optional=True, + message="Incentive", + ) + high_offer: "Incentive" = proto.Field( + proto.MESSAGE, + number=3, + optional=True, + message="Incentive", + ) + + +class IncentiveOffer(proto.Message): + r"""An acquisition incentive offer for a user. An offer means how + the user is treated. An offer can have no incentive or multiple + incentives. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + type_ (google.ads.googleads.v24.services.types.IncentiveOffer.OfferType): + Required. The type of this acquisition + incentive offer. + + This field is a member of `oneof`_ ``_type``. + consolidated_terms_and_conditions_url (str): + Optional. The URL of the terms and conditions + for the incentive offer. + + This field is a member of `oneof`_ ``_consolidated_terms_and_conditions_url``. + cyo_incentives (google.ads.googleads.v24.services.types.CyoIncentives): + CYO incentives. Set when type is CYO_INCENTIVE. + + This field is a member of `oneof`_ ``incentive_details``. + """ + + class OfferType(proto.Enum): + r"""Types of acquisition incentive offers. + + Values: + UNSPECIFIED (0): + Unknown offer type. Should not be used as a + value explicitly. + UNKNOWN (1): + Unknown offer type. + NO_INCENTIVE (2): + An offer with no incentive. + CYO_INCENTIVE (3): + A CYO (Choose-Your-Own) offer with multiple + incentives to choose from. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NO_INCENTIVE = 2 + CYO_INCENTIVE = 3 + + type_: OfferType = proto.Field( + proto.ENUM, + number=1, + optional=True, + enum=OfferType, + ) + consolidated_terms_and_conditions_url: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + cyo_incentives: "CyoIncentives" = proto.Field( + proto.MESSAGE, + number=3, + oneof="incentive_details", + message="CyoIncentives", + ) + + +class FetchIncentiveResponse(proto.Message): + r"""Response from getting the acquisition incentive for a user + when they visit a specific marketing page. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + incentive_offer (google.ads.googleads.v24.services.types.IncentiveOffer): + Required. The acquisition incentive offer for + the user. + + This field is a member of `oneof`_ ``_incentive_offer``. + """ + + incentive_offer: "IncentiveOffer" = proto.Field( + proto.MESSAGE, + number=1, + optional=True, + message="IncentiveOffer", + ) + + +class ApplyIncentiveRequest(proto.Message): + r"""Request message for applying an incentive. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + selected_incentive_id (int): + The incentive ID of this incentive. This is + used to identify which incentive is selected by + the user in the CYO flow. + + This field is a member of `oneof`_ ``_selected_incentive_id``. + customer_id (str): + The customer ID of the account that the + incentive is being applied to. + + This field is a member of `oneof`_ ``_customer_id``. + country_code (str): + Required. User's country code. Required. This field must be + equal to the Google Ads account's billing country. Incentive + eligibility, terms of service, and reward values are often + country-specific. This country code is used to ensure the + selected incentive is applicable to the user. Possible + country codes: + https://developers.google.com/google-ads/api/data/codes-formats#country_codes + + This field is a member of `oneof`_ ``_country_code``. + """ + + selected_incentive_id: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + customer_id: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + country_code: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + + +class ApplyIncentiveResponse(proto.Message): + r"""Response for applying an incentive. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + coupon_code (str): + The coupon code of the applied incentive. A globally unique + identifier of the applied incentive. This code is separate + and distinct from the selected_incentive_id in the request. + + This field is a member of `oneof`_ ``_coupon_code``. + creation_time (str): + The timestamp when this incentive was + applied. The timestamp is in UTC timezone and in + "yyyy-MM-dd HH:mm:ss" format. + + This field is a member of `oneof`_ ``_creation_time``. + """ + + coupon_code: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + creation_time: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/invoice_service.py b/google/ads/googleads/v24/services/types/invoice_service.py new file mode 100644 index 000000000..ffb927632 --- /dev/null +++ b/google/ads/googleads/v24/services/types/invoice_service.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import month_of_year +from google.ads.googleads.v24.resources.types import invoice + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "ListInvoicesRequest", + "ListInvoicesResponse", + }, +) + + +class ListInvoicesRequest(proto.Message): + r"""Request message for fetching the invoices of a given billing + setup that were issued during a given month. + + Attributes: + customer_id (str): + Required. The ID of the customer to fetch + invoices for. + billing_setup (str): + Required. The billing setup resource name of the requested + invoices. + + ``customers/{customer_id}/billingSetups/{billing_setup_id}`` + issue_year (str): + Required. The issue year to retrieve + invoices, in yyyy format. Only invoices issued + in 2019 or later can be retrieved. + issue_month (google.ads.googleads.v24.enums.types.MonthOfYearEnum.MonthOfYear): + Required. The issue month to retrieve + invoices. + include_granular_level_invoice_details (bool): + Optional. When true, the response will + include more granular level invoice details such + as campaign level cost breakdown, itemized + regulatory costs and adjustments. The default + value is false. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + billing_setup: str = proto.Field( + proto.STRING, + number=2, + ) + issue_year: str = proto.Field( + proto.STRING, + number=3, + ) + issue_month: month_of_year.MonthOfYearEnum.MonthOfYear = proto.Field( + proto.ENUM, + number=4, + enum=month_of_year.MonthOfYearEnum.MonthOfYear, + ) + include_granular_level_invoice_details: bool = proto.Field( + proto.BOOL, + number=5, + ) + + +class ListInvoicesResponse(proto.Message): + r"""Response message for + [InvoiceService.ListInvoices][google.ads.googleads.v24.services.InvoiceService.ListInvoices]. + + Attributes: + invoices (MutableSequence[google.ads.googleads.v24.resources.types.Invoice]): + The list of invoices that match the billing + setup and time period. + """ + + invoices: MutableSequence[invoice.Invoice] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=invoice.Invoice, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/keyword_plan_ad_group_keyword_service.py b/google/ads/googleads/v24/services/types/keyword_plan_ad_group_keyword_service.py new file mode 100644 index 000000000..8397c1a93 --- /dev/null +++ b/google/ads/googleads/v24/services/types/keyword_plan_ad_group_keyword_service.py @@ -0,0 +1,191 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import ( + keyword_plan_ad_group_keyword, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateKeywordPlanAdGroupKeywordsRequest", + "KeywordPlanAdGroupKeywordOperation", + "MutateKeywordPlanAdGroupKeywordsResponse", + "MutateKeywordPlanAdGroupKeywordResult", + }, +) + + +class MutateKeywordPlanAdGroupKeywordsRequest(proto.Message): + r"""Request message for + [KeywordPlanAdGroupKeywordService.MutateKeywordPlanAdGroupKeywords][google.ads.googleads.v24.services.KeywordPlanAdGroupKeywordService.MutateKeywordPlanAdGroupKeywords]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + Keyword Plan ad group keywords are being + modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanAdGroupKeywordOperation]): + Required. The list of operations to perform + on individual Keyword Plan ad group keywords. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["KeywordPlanAdGroupKeywordOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="KeywordPlanAdGroupKeywordOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class KeywordPlanAdGroupKeywordOperation(proto.Message): + r"""A single operation (create, update, remove) on a Keyword Plan + ad group keyword. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + The FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.KeywordPlanAdGroupKeyword): + Create operation: No resource name is + expected for the new Keyword Plan ad group + keyword. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.KeywordPlanAdGroupKeyword): + Update operation: The Keyword Plan ad group + keyword is expected to have a valid resource + name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed Keyword + Plan ad group keyword is expected, in this format: + + ``customers/{customer_id}/keywordPlanAdGroupKeywords/{kp_ad_group_keyword_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: keyword_plan_ad_group_keyword.KeywordPlanAdGroupKeyword = ( + proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=keyword_plan_ad_group_keyword.KeywordPlanAdGroupKeyword, + ) + ) + update: keyword_plan_ad_group_keyword.KeywordPlanAdGroupKeyword = ( + proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=keyword_plan_ad_group_keyword.KeywordPlanAdGroupKeyword, + ) + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateKeywordPlanAdGroupKeywordsResponse(proto.Message): + r"""Response message for a Keyword Plan ad group keyword mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateKeywordPlanAdGroupKeywordResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateKeywordPlanAdGroupKeywordResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateKeywordPlanAdGroupKeywordResult", + ) + ) + + +class MutateKeywordPlanAdGroupKeywordResult(proto.Message): + r"""The result for the Keyword Plan ad group keyword mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/keyword_plan_ad_group_service.py b/google/ads/googleads/v24/services/types/keyword_plan_ad_group_service.py new file mode 100644 index 000000000..abd0273b2 --- /dev/null +++ b/google/ads/googleads/v24/services/types/keyword_plan_ad_group_service.py @@ -0,0 +1,184 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import keyword_plan_ad_group +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateKeywordPlanAdGroupsRequest", + "KeywordPlanAdGroupOperation", + "MutateKeywordPlanAdGroupsResponse", + "MutateKeywordPlanAdGroupResult", + }, +) + + +class MutateKeywordPlanAdGroupsRequest(proto.Message): + r"""Request message for + [KeywordPlanAdGroupService.MutateKeywordPlanAdGroups][google.ads.googleads.v24.services.KeywordPlanAdGroupService.MutateKeywordPlanAdGroups]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + Keyword Plan ad groups are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanAdGroupOperation]): + Required. The list of operations to perform + on individual Keyword Plan ad groups. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["KeywordPlanAdGroupOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="KeywordPlanAdGroupOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class KeywordPlanAdGroupOperation(proto.Message): + r"""A single operation (create, update, remove) on a Keyword Plan + ad group. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + The FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.KeywordPlanAdGroup): + Create operation: No resource name is + expected for the new Keyword Plan ad group. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.KeywordPlanAdGroup): + Update operation: The Keyword Plan ad group + is expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed Keyword + Plan ad group is expected, in this format: + + ``customers/{customer_id}/keywordPlanAdGroups/{kp_ad_group_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: keyword_plan_ad_group.KeywordPlanAdGroup = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=keyword_plan_ad_group.KeywordPlanAdGroup, + ) + update: keyword_plan_ad_group.KeywordPlanAdGroup = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=keyword_plan_ad_group.KeywordPlanAdGroup, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateKeywordPlanAdGroupsResponse(proto.Message): + r"""Response message for a Keyword Plan ad group mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateKeywordPlanAdGroupResult]): + All results for the mutate. The order of the + results is determined by the order of the + keywords in the original request. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateKeywordPlanAdGroupResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateKeywordPlanAdGroupResult", + ) + ) + + +class MutateKeywordPlanAdGroupResult(proto.Message): + r"""The result for the Keyword Plan ad group mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/keyword_plan_campaign_keyword_service.py b/google/ads/googleads/v24/services/types/keyword_plan_campaign_keyword_service.py new file mode 100644 index 000000000..7b47e6065 --- /dev/null +++ b/google/ads/googleads/v24/services/types/keyword_plan_campaign_keyword_service.py @@ -0,0 +1,189 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import ( + keyword_plan_campaign_keyword, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateKeywordPlanCampaignKeywordsRequest", + "KeywordPlanCampaignKeywordOperation", + "MutateKeywordPlanCampaignKeywordsResponse", + "MutateKeywordPlanCampaignKeywordResult", + }, +) + + +class MutateKeywordPlanCampaignKeywordsRequest(proto.Message): + r"""Request message for + [KeywordPlanCampaignKeywordService.MutateKeywordPlanCampaignKeywords][google.ads.googleads.v24.services.KeywordPlanCampaignKeywordService.MutateKeywordPlanCampaignKeywords]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign keywords are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanCampaignKeywordOperation]): + Required. The list of operations to perform + on individual Keyword Plan campaign keywords. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["KeywordPlanCampaignKeywordOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="KeywordPlanCampaignKeywordOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class KeywordPlanCampaignKeywordOperation(proto.Message): + r"""A single operation (create, update, remove) on a Keyword Plan + campaign keyword. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + The FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.KeywordPlanCampaignKeyword): + Create operation: No resource name is + expected for the new Keyword Plan campaign + keyword. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.KeywordPlanCampaignKeyword): + Update operation: The Keyword Plan campaign + keyword expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed Keyword + Plan campaign keywords expected in this format: + + ``customers/{customer_id}/keywordPlanCampaignKeywords/{kp_campaign_keyword_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: keyword_plan_campaign_keyword.KeywordPlanCampaignKeyword = ( + proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=keyword_plan_campaign_keyword.KeywordPlanCampaignKeyword, + ) + ) + update: keyword_plan_campaign_keyword.KeywordPlanCampaignKeyword = ( + proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=keyword_plan_campaign_keyword.KeywordPlanCampaignKeyword, + ) + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateKeywordPlanCampaignKeywordsResponse(proto.Message): + r"""Response message for a Keyword Plan campaign keyword mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateKeywordPlanCampaignKeywordResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateKeywordPlanCampaignKeywordResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateKeywordPlanCampaignKeywordResult", + ) + ) + + +class MutateKeywordPlanCampaignKeywordResult(proto.Message): + r"""The result for the Keyword Plan campaign keyword mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/keyword_plan_campaign_service.py b/google/ads/googleads/v24/services/types/keyword_plan_campaign_service.py new file mode 100644 index 000000000..d68320a78 --- /dev/null +++ b/google/ads/googleads/v24/services/types/keyword_plan_campaign_service.py @@ -0,0 +1,182 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import keyword_plan_campaign +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateKeywordPlanCampaignsRequest", + "KeywordPlanCampaignOperation", + "MutateKeywordPlanCampaignsResponse", + "MutateKeywordPlanCampaignResult", + }, +) + + +class MutateKeywordPlanCampaignsRequest(proto.Message): + r"""Request message for + [KeywordPlanCampaignService.MutateKeywordPlanCampaigns][google.ads.googleads.v24.services.KeywordPlanCampaignService.MutateKeywordPlanCampaigns]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + Keyword Plan campaigns are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanCampaignOperation]): + Required. The list of operations to perform + on individual Keyword Plan campaigns. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["KeywordPlanCampaignOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="KeywordPlanCampaignOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class KeywordPlanCampaignOperation(proto.Message): + r"""A single operation (create, update, remove) on a Keyword Plan + campaign. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + The FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.KeywordPlanCampaign): + Create operation: No resource name is + expected for the new Keyword Plan campaign. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.KeywordPlanCampaign): + Update operation: The Keyword Plan campaign + is expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed Keyword + Plan campaign is expected, in this format: + + ``customers/{customer_id}/keywordPlanCampaigns/{keywordPlan_campaign_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: keyword_plan_campaign.KeywordPlanCampaign = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=keyword_plan_campaign.KeywordPlanCampaign, + ) + update: keyword_plan_campaign.KeywordPlanCampaign = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=keyword_plan_campaign.KeywordPlanCampaign, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateKeywordPlanCampaignsResponse(proto.Message): + r"""Response message for a Keyword Plan campaign mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateKeywordPlanCampaignResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateKeywordPlanCampaignResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateKeywordPlanCampaignResult", + ) + ) + + +class MutateKeywordPlanCampaignResult(proto.Message): + r"""The result for the Keyword Plan campaign mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/keyword_plan_idea_service.py b/google/ads/googleads/v24/services/types/keyword_plan_idea_service.py new file mode 100644 index 000000000..0904a7098 --- /dev/null +++ b/google/ads/googleads/v24/services/types/keyword_plan_idea_service.py @@ -0,0 +1,1010 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.common.types import dates +from google.ads.googleads.v24.common.types import keyword_plan_common +from google.ads.googleads.v24.enums.types import keyword_match_type +from google.ads.googleads.v24.enums.types import keyword_plan_keyword_annotation +from google.ads.googleads.v24.enums.types import ( + keyword_plan_network as gage_keyword_plan_network, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "GenerateKeywordIdeasRequest", + "KeywordAndUrlSeed", + "KeywordSeed", + "SiteSeed", + "UrlSeed", + "GenerateKeywordIdeaResponse", + "GenerateKeywordIdeaResult", + "GenerateKeywordHistoricalMetricsRequest", + "GenerateKeywordHistoricalMetricsResponse", + "GenerateKeywordHistoricalMetricsResult", + "GenerateAdGroupThemesRequest", + "GenerateAdGroupThemesResponse", + "AdGroupKeywordSuggestion", + "UnusableAdGroup", + "GenerateKeywordForecastMetricsRequest", + "CampaignToForecast", + "ForecastAdGroup", + "ManualCpcBiddingStrategy", + "MaximizeClicksBiddingStrategy", + "MaximizeConversionsBiddingStrategy", + "GenerateKeywordForecastMetricsResponse", + "KeywordForecastMetrics", + }, +) + + +class GenerateKeywordIdeasRequest(proto.Message): + r"""Request message for + [KeywordPlanIdeaService.GenerateKeywordIdeas][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordIdeas]. + + 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: + customer_id (str): + The ID of the customer with the + recommendation. + language (str): + The resource name of the language to target. + Each keyword belongs to some set of languages; a + keyword is included if language is one of its + languages. + If not set, all keywords will be included. + + This field is a member of `oneof`_ ``_language``. + geo_target_constants (MutableSequence[str]): + The resource names of the location to target. + Maximum is 10. An empty list MAY be used to + specify all targeting geos. + include_adult_keywords (bool): + If true, adult keywords will be included in + response. The default value is false. + page_token (str): + Token of the page to retrieve. If not specified, the first + page of results will be returned. To request next page of + results use the value obtained from ``next_page_token`` in + the previous response. The request fields must match across + pages. + page_size (int): + Number of results to retrieve in a single page. A maximum of + 10,000 results may be returned, if the page_size exceeds + this, it is ignored. If unspecified, at most 10,000 results + will be returned. The server may decide to further limit the + number of returned resources. If the response contains fewer + than 10,000 results it may not be assumed as last page of + results. + keyword_plan_network (google.ads.googleads.v24.enums.types.KeywordPlanNetworkEnum.KeywordPlanNetwork): + Targeting network. + If not set, Google Search And Partners Network + will be used. + keyword_annotation (MutableSequence[google.ads.googleads.v24.enums.types.KeywordPlanKeywordAnnotationEnum.KeywordPlanKeywordAnnotation]): + The keyword annotations to include in + response. + aggregate_metrics (google.ads.googleads.v24.common.types.KeywordPlanAggregateMetrics): + The aggregate fields to include in response. + historical_metrics_options (google.ads.googleads.v24.common.types.HistoricalMetricsOptions): + The options for historical metrics data. + keyword_and_url_seed (google.ads.googleads.v24.services.types.KeywordAndUrlSeed): + A Keyword and a specific Url to generate + ideas from for example, cars, + www.example.com/cars. + + This field is a member of `oneof`_ ``seed``. + keyword_seed (google.ads.googleads.v24.services.types.KeywordSeed): + A Keyword or phrase to generate ideas from, + for example, cars. + + This field is a member of `oneof`_ ``seed``. + url_seed (google.ads.googleads.v24.services.types.UrlSeed): + A specific url to generate ideas from, for + example, www.example.com/cars. + + This field is a member of `oneof`_ ``seed``. + site_seed (google.ads.googleads.v24.services.types.SiteSeed): + The site to generate ideas from, for example, + www.example.com. + + This field is a member of `oneof`_ ``seed``. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + language: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + geo_target_constants: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=15, + ) + include_adult_keywords: bool = proto.Field( + proto.BOOL, + number=10, + ) + page_token: str = proto.Field( + proto.STRING, + number=12, + ) + page_size: int = proto.Field( + proto.INT32, + number=13, + ) + keyword_plan_network: ( + gage_keyword_plan_network.KeywordPlanNetworkEnum.KeywordPlanNetwork + ) = proto.Field( + proto.ENUM, + number=9, + enum=gage_keyword_plan_network.KeywordPlanNetworkEnum.KeywordPlanNetwork, + ) + keyword_annotation: MutableSequence[ + keyword_plan_keyword_annotation.KeywordPlanKeywordAnnotationEnum.KeywordPlanKeywordAnnotation + ] = proto.RepeatedField( + proto.ENUM, + number=17, + enum=keyword_plan_keyword_annotation.KeywordPlanKeywordAnnotationEnum.KeywordPlanKeywordAnnotation, + ) + aggregate_metrics: keyword_plan_common.KeywordPlanAggregateMetrics = ( + proto.Field( + proto.MESSAGE, + number=16, + message=keyword_plan_common.KeywordPlanAggregateMetrics, + ) + ) + historical_metrics_options: keyword_plan_common.HistoricalMetricsOptions = ( + proto.Field( + proto.MESSAGE, + number=18, + message=keyword_plan_common.HistoricalMetricsOptions, + ) + ) + keyword_and_url_seed: "KeywordAndUrlSeed" = proto.Field( + proto.MESSAGE, + number=2, + oneof="seed", + message="KeywordAndUrlSeed", + ) + keyword_seed: "KeywordSeed" = proto.Field( + proto.MESSAGE, + number=3, + oneof="seed", + message="KeywordSeed", + ) + url_seed: "UrlSeed" = proto.Field( + proto.MESSAGE, + number=5, + oneof="seed", + message="UrlSeed", + ) + site_seed: "SiteSeed" = proto.Field( + proto.MESSAGE, + number=11, + oneof="seed", + message="SiteSeed", + ) + + +class KeywordAndUrlSeed(proto.Message): + r"""Keyword And Url Seed + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + url (str): + The URL to crawl in order to generate keyword + ideas. + + This field is a member of `oneof`_ ``_url``. + keywords (MutableSequence[str]): + Requires at least one keyword and no more + than 20 keywords. + """ + + url: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + keywords: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=4, + ) + + +class KeywordSeed(proto.Message): + r"""Keyword Seed + + Attributes: + keywords (MutableSequence[str]): + Requires at least one keyword and no more + than 20 keywords. + """ + + keywords: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + + +class SiteSeed(proto.Message): + r"""Site Seed + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + site (str): + The domain name of the site. If the customer + requesting the ideas doesn't own the site + provided only public information is returned. + + This field is a member of `oneof`_ ``_site``. + """ + + site: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class UrlSeed(proto.Message): + r"""Url Seed + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + url (str): + The URL to crawl in order to generate keyword + ideas. + + This field is a member of `oneof`_ ``_url``. + """ + + url: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class GenerateKeywordIdeaResponse(proto.Message): + r"""Response message for + [KeywordPlanIdeaService.GenerateKeywordIdeas][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordIdeas]. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.GenerateKeywordIdeaResult]): + Results of generating keyword ideas. + aggregate_metric_results (google.ads.googleads.v24.common.types.KeywordPlanAggregateMetricResults): + The aggregate metrics for all keyword ideas. + next_page_token (str): + Pagination token used to retrieve the next page of results. + Pass the content of this string as the ``page_token`` + attribute of the next request. ``next_page_token`` is not + returned for the last page. + total_size (int): + Total number of results available. + """ + + @property + def raw_page(self): + return self + + results: MutableSequence["GenerateKeywordIdeaResult"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="GenerateKeywordIdeaResult", + ) + aggregate_metric_results: ( + keyword_plan_common.KeywordPlanAggregateMetricResults + ) = proto.Field( + proto.MESSAGE, + number=4, + message=keyword_plan_common.KeywordPlanAggregateMetricResults, + ) + next_page_token: str = proto.Field( + proto.STRING, + number=2, + ) + total_size: int = proto.Field( + proto.INT64, + number=3, + ) + + +class GenerateKeywordIdeaResult(proto.Message): + r"""The result of generating keyword ideas. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + text (str): + Text of the keyword idea. + As in Keyword Plan historical metrics, this text + may not be an actual keyword, but the canonical + form of multiple keywords. See + KeywordPlanKeywordHistoricalMetrics message in + KeywordPlanService. + + This field is a member of `oneof`_ ``_text``. + keyword_idea_metrics (google.ads.googleads.v24.common.types.KeywordPlanHistoricalMetrics): + The historical metrics for the keyword. + keyword_annotations (google.ads.googleads.v24.common.types.KeywordAnnotations): + The annotations for the keyword. + The annotation data is only provided if + requested. + close_variants (MutableSequence[str]): + The list of close variants from the requested + keywords that are combined into this + GenerateKeywordIdeaResult. See + https://support.google.com/google-ads/answer/9342105 + for the definition of "close variants". + """ + + text: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + keyword_idea_metrics: keyword_plan_common.KeywordPlanHistoricalMetrics = ( + proto.Field( + proto.MESSAGE, + number=3, + message=keyword_plan_common.KeywordPlanHistoricalMetrics, + ) + ) + keyword_annotations: keyword_plan_common.KeywordAnnotations = proto.Field( + proto.MESSAGE, + number=6, + message=keyword_plan_common.KeywordAnnotations, + ) + close_variants: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=7, + ) + + +class GenerateKeywordHistoricalMetricsRequest(proto.Message): + r"""Request message for + [KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer_id (str): + The ID of the customer with the + recommendation. + keywords (MutableSequence[str]): + A list of keywords to get historical metrics. + Not all inputs will be returned as a result of + near-exact deduplication. For example, if stats + for "car" and "cars" are requested, only "car" + will be returned. + A maximum of 10,000 keywords can be used. + language (str): + The resource name of the language to target. + Each keyword belongs to some set of languages; a + keyword is included if language is one of its + languages. + If not set, all keywords will be included. + + This field is a member of `oneof`_ ``_language``. + include_adult_keywords (bool): + If true, adult keywords will be included in + response. The default value is false. + geo_target_constants (MutableSequence[str]): + The resource names of the location to target. + Maximum is 10. An empty list MAY be used to + specify all targeting geos. + keyword_plan_network (google.ads.googleads.v24.enums.types.KeywordPlanNetworkEnum.KeywordPlanNetwork): + Targeting network. + If not set, Google Search And Partners Network + will be used. + aggregate_metrics (google.ads.googleads.v24.common.types.KeywordPlanAggregateMetrics): + The aggregate fields to include in response. + historical_metrics_options (google.ads.googleads.v24.common.types.HistoricalMetricsOptions): + The options for historical metrics data. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + keywords: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + language: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + include_adult_keywords: bool = proto.Field( + proto.BOOL, + number=5, + ) + geo_target_constants: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=6, + ) + keyword_plan_network: ( + gage_keyword_plan_network.KeywordPlanNetworkEnum.KeywordPlanNetwork + ) = proto.Field( + proto.ENUM, + number=7, + enum=gage_keyword_plan_network.KeywordPlanNetworkEnum.KeywordPlanNetwork, + ) + aggregate_metrics: keyword_plan_common.KeywordPlanAggregateMetrics = ( + proto.Field( + proto.MESSAGE, + number=8, + message=keyword_plan_common.KeywordPlanAggregateMetrics, + ) + ) + historical_metrics_options: keyword_plan_common.HistoricalMetricsOptions = ( + proto.Field( + proto.MESSAGE, + number=3, + message=keyword_plan_common.HistoricalMetricsOptions, + ) + ) + + +class GenerateKeywordHistoricalMetricsResponse(proto.Message): + r"""Response message for + [KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics]. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.GenerateKeywordHistoricalMetricsResult]): + List of keywords and their historical + metrics. + aggregate_metric_results (google.ads.googleads.v24.common.types.KeywordPlanAggregateMetricResults): + The aggregate metrics for all keywords. + """ + + results: MutableSequence["GenerateKeywordHistoricalMetricsResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="GenerateKeywordHistoricalMetricsResult", + ) + ) + aggregate_metric_results: ( + keyword_plan_common.KeywordPlanAggregateMetricResults + ) = proto.Field( + proto.MESSAGE, + number=2, + message=keyword_plan_common.KeywordPlanAggregateMetricResults, + ) + + +class GenerateKeywordHistoricalMetricsResult(proto.Message): + r"""The result of generating keyword historical metrics. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + text (str): + The text of the query associated with one or more keywords. + Note that we de-dupe your keywords list, eliminating close + variants before returning the keywords as text. For example, + if your request originally contained the keywords "car" and + "cars", the returned search query will only contain "cars". + The list of de-duped queries will be included in + close_variants field. + + This field is a member of `oneof`_ ``_text``. + close_variants (MutableSequence[str]): + The list of close variants from the requested + keywords whose stats are combined into this + GenerateKeywordHistoricalMetricsResult. + keyword_metrics (google.ads.googleads.v24.common.types.KeywordPlanHistoricalMetrics): + The historical metrics for text and its close + variants + """ + + text: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + close_variants: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + keyword_metrics: keyword_plan_common.KeywordPlanHistoricalMetrics = ( + proto.Field( + proto.MESSAGE, + number=2, + message=keyword_plan_common.KeywordPlanHistoricalMetrics, + ) + ) + + +class GenerateAdGroupThemesRequest(proto.Message): + r"""Request message for + [KeywordPlanIdeaService.GenerateAdGroupThemes][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateAdGroupThemes]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + keywords (MutableSequence[str]): + Required. A list of keywords to group into + the provided AdGroups. + ad_groups (MutableSequence[str]): + Required. A list of resource names of AdGroups to group + keywords into. Resource name format: + ``customers/{customer_id}/adGroups/{ad_group_id}`` + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + keywords: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + ad_groups: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + + +class GenerateAdGroupThemesResponse(proto.Message): + r"""Response message for + [KeywordPlanIdeaService.GenerateAdGroupThemes][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateAdGroupThemes]. + + Attributes: + ad_group_keyword_suggestions (MutableSequence[google.ads.googleads.v24.services.types.AdGroupKeywordSuggestion]): + A list of suggested AdGroup/keyword pairings. + unusable_ad_groups (MutableSequence[google.ads.googleads.v24.services.types.UnusableAdGroup]): + A list of provided AdGroups that could not be + used as suggestions. + """ + + ad_group_keyword_suggestions: MutableSequence[ + "AdGroupKeywordSuggestion" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="AdGroupKeywordSuggestion", + ) + unusable_ad_groups: MutableSequence["UnusableAdGroup"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="UnusableAdGroup", + ) + ) + + +class AdGroupKeywordSuggestion(proto.Message): + r"""The suggested text and AdGroup/Campaign pairing for a given + keyword. + + Attributes: + keyword_text (str): + The original keyword text. + suggested_keyword_text (str): + The normalized version of keyword_text for + BROAD/EXACT/PHRASE suggestions. + suggested_match_type (google.ads.googleads.v24.enums.types.KeywordMatchTypeEnum.KeywordMatchType): + The suggested keyword match type. + suggested_ad_group (str): + The suggested AdGroup for the keyword. Resource name format: + ``customers/{customer_id}/adGroups/{ad_group_id}`` + suggested_campaign (str): + The suggested Campaign for the keyword. Resource name + format: ``customers/{customer_id}/campaigns/{campaign_id}`` + """ + + keyword_text: str = proto.Field( + proto.STRING, + number=1, + ) + suggested_keyword_text: str = proto.Field( + proto.STRING, + number=2, + ) + suggested_match_type: ( + keyword_match_type.KeywordMatchTypeEnum.KeywordMatchType + ) = proto.Field( + proto.ENUM, + number=3, + enum=keyword_match_type.KeywordMatchTypeEnum.KeywordMatchType, + ) + suggested_ad_group: str = proto.Field( + proto.STRING, + number=4, + ) + suggested_campaign: str = proto.Field( + proto.STRING, + number=5, + ) + + +class UnusableAdGroup(proto.Message): + r"""An AdGroup/Campaign pair that could not be used as a suggestion for + keywords. + + AdGroups may not be usable if the AdGroup + + - belongs to a Campaign that is not ENABLED or PAUSED + - is itself not ENABLED + + Attributes: + ad_group (str): + The AdGroup resource name. Resource name format: + ``customers/{customer_id}/adGroups/{ad_group_id}`` + campaign (str): + The Campaign resource name. Resource name format: + ``customers/{customer_id}/campaigns/{campaign_id}`` + """ + + ad_group: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=2, + ) + + +class GenerateKeywordForecastMetricsRequest(proto.Message): + r"""Request message for + [KeywordPlanIdeaService.GenerateKeywordForecastMetrics][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordForecastMetrics]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer_id (str): + The ID of the customer. + currency_code (str): + The currency used for exchange rate + conversion. By default, the account currency of + the customer is used. Set this field only if the + currency is different from the account currency. + The list of valid currency codes can be found at + https://developers.google.com/google-ads/api/data/codes-formats#currency-codes. + + This field is a member of `oneof`_ ``_currency_code``. + forecast_period (google.ads.googleads.v24.common.types.DateRange): + The date range for the forecast. The start + date must be in the future and end date must be + within 1 year from today. The reference timezone + used is the one of the Google Ads account + belonging to the customer. If not set, a default + date range from next Sunday to the following + Saturday will be used. + campaign (google.ads.googleads.v24.services.types.CampaignToForecast): + Required. The campaign used in the forecast. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + currency_code: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + forecast_period: dates.DateRange = proto.Field( + proto.MESSAGE, + number=3, + message=dates.DateRange, + ) + campaign: "CampaignToForecast" = proto.Field( + proto.MESSAGE, + number=4, + message="CampaignToForecast", + ) + + +class CampaignToForecast(proto.Message): + r"""A campaign to do a keyword campaign forecast. + + Attributes: + language_constants (MutableSequence[str]): + The list of resource names of languages to be targeted. The + resource name is of the format + "languageConstants/{criterion_id}". See + https://developers.google.com/google-ads/api/data/codes-formats#languages + for the list of language criterion codes. + geo_target_constants (MutableSequence[str]): + Locations to be targeted. Locations must be unique. The + resource name is of the format + "geoTargetConstants/{criterion_id}". + bidding_strategy (google.ads.googleads.v24.services.types.CampaignToForecast.CampaignBiddingStrategy): + Required. The bidding strategy for the + campaign. + ad_groups (MutableSequence[google.ads.googleads.v24.services.types.ForecastAdGroup]): + The ad groups in the new campaign to + forecast. + """ + + class CampaignBiddingStrategy(proto.Message): + r"""Supported bidding strategies for new campaign forecasts. + + 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: + manual_cpc_bidding_strategy (google.ads.googleads.v24.services.types.ManualCpcBiddingStrategy): + Use manual CPC bidding strategy for + forecasting. + + This field is a member of `oneof`_ ``bidding_strategy``. + maximize_clicks_bidding_strategy (google.ads.googleads.v24.services.types.MaximizeClicksBiddingStrategy): + Use maximize clicks bidding strategy for + forecasting. + + This field is a member of `oneof`_ ``bidding_strategy``. + maximize_conversions_bidding_strategy (google.ads.googleads.v24.services.types.MaximizeConversionsBiddingStrategy): + Use maximize conversions bidding strategy for + forecasting. + + This field is a member of `oneof`_ ``bidding_strategy``. + """ + + manual_cpc_bidding_strategy: "ManualCpcBiddingStrategy" = proto.Field( + proto.MESSAGE, + number=1, + oneof="bidding_strategy", + message="ManualCpcBiddingStrategy", + ) + maximize_clicks_bidding_strategy: "MaximizeClicksBiddingStrategy" = ( + proto.Field( + proto.MESSAGE, + number=2, + oneof="bidding_strategy", + message="MaximizeClicksBiddingStrategy", + ) + ) + maximize_conversions_bidding_strategy: ( + "MaximizeConversionsBiddingStrategy" + ) = proto.Field( + proto.MESSAGE, + number=3, + oneof="bidding_strategy", + message="MaximizeConversionsBiddingStrategy", + ) + + language_constants: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + geo_target_constants: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=8, + ) + bidding_strategy: CampaignBiddingStrategy = proto.Field( + proto.MESSAGE, + number=5, + message=CampaignBiddingStrategy, + ) + ad_groups: MutableSequence["ForecastAdGroup"] = proto.RepeatedField( + proto.MESSAGE, + number=7, + message="ForecastAdGroup", + ) + + +class ForecastAdGroup(proto.Message): + r"""An ad group that is part of a campaign to be forecasted. + + Attributes: + keywords (MutableSequence[google.ads.googleads.v24.common.types.KeywordInfo]): + Required. The list of keywords to be used in + the ad group when doing the forecast. Requires + at least one keyword. + """ + + keywords: MutableSequence[criteria.KeywordInfo] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=criteria.KeywordInfo, + ) + + +class ManualCpcBiddingStrategy(proto.Message): + r"""Manual CPC Bidding Strategy. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + daily_budget_micros (int): + Campaign level budget in micros. If set, a + minimum value is enforced for the local currency + used in the campaign. An error will occur + showing the minimum value if this field is set + too low. + + This field is a member of `oneof`_ ``_daily_budget_micros``. + max_cpc_bid_micros (int): + Required. A bid in micros to be applied to ad + groups within the campaign for a manual CPC + bidding strategy. + """ + + daily_budget_micros: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + max_cpc_bid_micros: int = proto.Field( + proto.INT64, + number=2, + ) + + +class MaximizeClicksBiddingStrategy(proto.Message): + r"""Maximize Clicks Bidding Strategy. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + daily_target_spend_micros (int): + Required. The daily target spend in micros to + be used for estimation. A minimum value is + enforced for the local currency used in the + campaign. An error will occur showing the + minimum value if this field is set too low. + max_cpc_bid_ceiling_micros (int): + Ceiling on max CPC bids in micros. + + This field is a member of `oneof`_ ``_max_cpc_bid_ceiling_micros``. + """ + + daily_target_spend_micros: int = proto.Field( + proto.INT64, + number=1, + ) + max_cpc_bid_ceiling_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + +class MaximizeConversionsBiddingStrategy(proto.Message): + r"""Maximize Conversions Bidding Strategy. + + Attributes: + daily_target_spend_micros (int): + Required. The daily target spend in micros to + be used for estimation. This value must be + greater than zero. + """ + + daily_target_spend_micros: int = proto.Field( + proto.INT64, + number=1, + ) + + +class GenerateKeywordForecastMetricsResponse(proto.Message): + r"""Response message for + [KeywordPlanIdeaService.GenerateKeywordForecastMetrics][google.ads.googleads.v24.services.KeywordPlanIdeaService.GenerateKeywordForecastMetrics]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + campaign_forecast_metrics (google.ads.googleads.v24.services.types.KeywordForecastMetrics): + Results of the campaign forecast. + + This field is a member of `oneof`_ ``_campaign_forecast_metrics``. + """ + + campaign_forecast_metrics: "KeywordForecastMetrics" = proto.Field( + proto.MESSAGE, + number=1, + optional=True, + message="KeywordForecastMetrics", + ) + + +class KeywordForecastMetrics(proto.Message): + r"""The forecast metrics for the planless keyword campaign. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + average_cpc_micros (int): + The average cpc. Available only if clicks > + 0. + + This field is a member of `oneof`_ ``_average_cpc_micros``. + clicks (float): + The total number of clicks. This field is only available if + the bidding strategy is + [MaximizeClicksBiddingStrategy][google.ads.googleads.v24.services.MaximizeClicksBiddingStrategy] + or + [ManualCpcBiddingStrategy][google.ads.googleads.v24.services.ManualCpcBiddingStrategy]. + + This field is a member of `oneof`_ ``_clicks``. + cost_micros (int): + The total cost. + + This field is a member of `oneof`_ ``_cost_micros``. + conversions (float): + Forecasted number of conversions. This field is only + available if the bidding strategy is + [MaximizeConversionsBiddingStrategy][google.ads.googleads.v24.services.MaximizeConversionsBiddingStrategy]. + + This field is a member of `oneof`_ ``_conversions``. + average_cpa_micros (int): + Average cost per acquisition calculated as cost_micros / + conversions. + + This field is a member of `oneof`_ ``_average_cpa_micros``. + """ + + average_cpc_micros: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + clicks: float = proto.Field( + proto.DOUBLE, + number=4, + optional=True, + ) + cost_micros: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + conversions: float = proto.Field( + proto.DOUBLE, + number=6, + optional=True, + ) + average_cpa_micros: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/keyword_plan_service.py b/google/ads/googleads/v24/services/types/keyword_plan_service.py new file mode 100644 index 000000000..055834519 --- /dev/null +++ b/google/ads/googleads/v24/services/types/keyword_plan_service.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import keyword_plan +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateKeywordPlansRequest", + "KeywordPlanOperation", + "MutateKeywordPlansResponse", + "MutateKeywordPlansResult", + }, +) + + +class MutateKeywordPlansRequest(proto.Message): + r"""Request message for + [KeywordPlanService.MutateKeywordPlans][google.ads.googleads.v24.services.KeywordPlanService.MutateKeywordPlans]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + keyword plans are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.KeywordPlanOperation]): + Required. The list of operations to perform + on individual keyword plans. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["KeywordPlanOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="KeywordPlanOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class KeywordPlanOperation(proto.Message): + r"""A single operation (create, update, remove) on a keyword + plan. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + The FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.KeywordPlan): + Create operation: No resource name is + expected for the new keyword plan. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.KeywordPlan): + Update operation: The keyword plan is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed keyword + plan is expected in this format: + + ``customers/{customer_id}/keywordPlans/{keyword_plan_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: keyword_plan.KeywordPlan = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=keyword_plan.KeywordPlan, + ) + update: keyword_plan.KeywordPlan = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=keyword_plan.KeywordPlan, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateKeywordPlansResponse(proto.Message): + r"""Response message for a keyword plan mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateKeywordPlansResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateKeywordPlansResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateKeywordPlansResult", + ) + + +class MutateKeywordPlansResult(proto.Message): + r"""The result for the keyword plan mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/keyword_theme_constant_service.py b/google/ads/googleads/v24/services/types/keyword_theme_constant_service.py new file mode 100644 index 000000000..20f968d79 --- /dev/null +++ b/google/ads/googleads/v24/services/types/keyword_theme_constant_service.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import keyword_theme_constant + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "SuggestKeywordThemeConstantsRequest", + "SuggestKeywordThemeConstantsResponse", + }, +) + + +class SuggestKeywordThemeConstantsRequest(proto.Message): + r"""Request message for + [KeywordThemeConstantService.SuggestKeywordThemeConstants][google.ads.googleads.v24.services.KeywordThemeConstantService.SuggestKeywordThemeConstants]. + + Attributes: + query_text (str): + The query text of a keyword theme that will + be used to map to similar keyword themes. For + example, "plumber" or "roofer". + country_code (str): + Upper-case, two-letter country code as + defined by ISO-3166. This for refining the scope + of the query, default to 'US' if not set. + language_code (str): + The two letter language code for get + corresponding keyword theme for refining the + scope of the query, default to 'en' if not set. + """ + + query_text: str = proto.Field( + proto.STRING, + number=1, + ) + country_code: str = proto.Field( + proto.STRING, + number=2, + ) + language_code: str = proto.Field( + proto.STRING, + number=3, + ) + + +class SuggestKeywordThemeConstantsResponse(proto.Message): + r"""Response message for + [KeywordThemeConstantService.SuggestKeywordThemeConstants][google.ads.googleads.v24.services.KeywordThemeConstantService.SuggestKeywordThemeConstants]. + + Attributes: + keyword_theme_constants (MutableSequence[google.ads.googleads.v24.resources.types.KeywordThemeConstant]): + Smart Campaign keyword theme suggestions. + """ + + keyword_theme_constants: MutableSequence[ + keyword_theme_constant.KeywordThemeConstant + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=keyword_theme_constant.KeywordThemeConstant, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/label_service.py b/google/ads/googleads/v24/services/types/label_service.py new file mode 100644 index 000000000..e04b81344 --- /dev/null +++ b/google/ads/googleads/v24/services/types/label_service.py @@ -0,0 +1,200 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import label as gagr_label +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateLabelsRequest", + "LabelOperation", + "MutateLabelsResponse", + "MutateLabelResult", + }, +) + + +class MutateLabelsRequest(proto.Message): + r"""Request message for + [LabelService.MutateLabels][google.ads.googleads.v24.services.LabelService.MutateLabels]. + + Attributes: + customer_id (str): + Required. ID of the customer whose labels are + being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.LabelOperation]): + Required. The list of operations to perform + on labels. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["LabelOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="LabelOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class LabelOperation(proto.Message): + r"""A single operation (create, remove, update) on a label. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.Label): + Create operation: No resource name is + expected for the new label. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.Label): + Update operation: The label is expected to + have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the label being + removed, in this format: + + ``customers/{customer_id}/labels/{label_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_label.Label = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_label.Label, + ) + update: gagr_label.Label = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_label.Label, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateLabelsResponse(proto.Message): + r"""Response message for a labels mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateLabelResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateLabelResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateLabelResult", + ) + + +class MutateLabelResult(proto.Message): + r"""The result for a label mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + label (google.ads.googleads.v24.resources.types.Label): + The mutated label with only mutable fields after mutate. The + field will only be returned when response_content_type is + set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + label: gagr_label.Label = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_label.Label, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/local_services_lead_service.py b/google/ads/googleads/v24/services/types/local_services_lead_service.py new file mode 100644 index 000000000..bd713ffa1 --- /dev/null +++ b/google/ads/googleads/v24/services/types/local_services_lead_service.py @@ -0,0 +1,284 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + local_services_lead_credit_issuance_decision, +) +from google.ads.googleads.v24.enums.types import ( + local_services_lead_survey_answer, +) +from google.ads.googleads.v24.enums.types import ( + local_services_lead_survey_dissatisfied_reason, +) +from google.ads.googleads.v24.enums.types import ( + local_services_lead_survey_satisfied_reason, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "AppendLeadConversationRequest", + "AppendLeadConversationResponse", + "Conversation", + "ConversationOrError", + "SurveySatisfied", + "SurveyDissatisfied", + "ProvideLeadFeedbackRequest", + "ProvideLeadFeedbackResponse", + }, +) + + +class AppendLeadConversationRequest(proto.Message): + r"""Request message for + [LocalServicesLeadService.AppendLeadConversation][google.ads.googleads.v24.services.LocalServicesLeadService.AppendLeadConversation]. + + Attributes: + customer_id (str): + Required. The Id of the customer which owns + the leads onto which the conversations will be + appended. + conversations (MutableSequence[google.ads.googleads.v24.services.types.Conversation]): + Required. Conversations that are being + appended. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + conversations: MutableSequence["Conversation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="Conversation", + ) + + +class AppendLeadConversationResponse(proto.Message): + r"""Response message for + [LocalServicesLeadService.AppendLeadConversation][google.ads.googleads.v24.services.LocalServicesLeadService.AppendLeadConversation]. + + Attributes: + responses (MutableSequence[google.ads.googleads.v24.services.types.ConversationOrError]): + Required. List of append conversation + operation results. + """ + + responses: MutableSequence["ConversationOrError"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ConversationOrError", + ) + + +class Conversation(proto.Message): + r"""Details of the conversation that needs to be appended. + + Attributes: + local_services_lead (str): + Required. The resource name of the local + services lead that the conversation should be + applied to. + text (str): + Required. Text message that user wanted to + append to lead. + """ + + local_services_lead: str = proto.Field( + proto.STRING, + number=1, + ) + text: str = proto.Field( + proto.STRING, + number=2, + ) + + +class ConversationOrError(proto.Message): + r"""Result of the append conversation operation. + + 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: + local_services_lead_conversation (str): + The resource name of the appended local + services lead conversation. + + This field is a member of `oneof`_ ``append_lead_conversation_response``. + partial_failure_error (google.rpc.status_pb2.Status): + Failure status when the request could not be + processed. + + This field is a member of `oneof`_ ``append_lead_conversation_response``. + """ + + local_services_lead_conversation: str = proto.Field( + proto.STRING, + number=1, + oneof="append_lead_conversation_response", + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + oneof="append_lead_conversation_response", + message=status_pb2.Status, + ) + + +class SurveySatisfied(proto.Message): + r"""Details about various factors for being satisfied with the + lead. + + Attributes: + survey_satisfied_reason (google.ads.googleads.v24.enums.types.LocalServicesLeadSurveySatisfiedReasonEnum.SurveySatisfiedReason): + Required. Provider's reason for being + satisfied with the lead. + other_reason_comment (str): + Optional. Provider's free form comments. This field is + required when OTHER_SATISFIED_REASON is selected as the + reason. + """ + + survey_satisfied_reason: ( + local_services_lead_survey_satisfied_reason.LocalServicesLeadSurveySatisfiedReasonEnum.SurveySatisfiedReason + ) = proto.Field( + proto.ENUM, + number=1, + enum=local_services_lead_survey_satisfied_reason.LocalServicesLeadSurveySatisfiedReasonEnum.SurveySatisfiedReason, + ) + other_reason_comment: str = proto.Field( + proto.STRING, + number=2, + ) + + +class SurveyDissatisfied(proto.Message): + r"""Details about various factors for not being satisfied with + the lead. + + Attributes: + survey_dissatisfied_reason (google.ads.googleads.v24.enums.types.LocalServicesLeadSurveyDissatisfiedReasonEnum.SurveyDissatisfiedReason): + Required. Provider's reason for not being + satisfied with the lead. + other_reason_comment (str): + Optional. Provider's free form comments. This field is + required when OTHER_DISSATISFIED_REASON is selected as the + reason. + """ + + survey_dissatisfied_reason: ( + local_services_lead_survey_dissatisfied_reason.LocalServicesLeadSurveyDissatisfiedReasonEnum.SurveyDissatisfiedReason + ) = proto.Field( + proto.ENUM, + number=1, + enum=local_services_lead_survey_dissatisfied_reason.LocalServicesLeadSurveyDissatisfiedReasonEnum.SurveyDissatisfiedReason, + ) + other_reason_comment: str = proto.Field( + proto.STRING, + number=2, + ) + + +class ProvideLeadFeedbackRequest(proto.Message): + r"""Request message for + [LocalServicesLeadService.ProvideLeadFeedback][google.ads.googleads.v24.services.LocalServicesLeadService.ProvideLeadFeedback]. + + 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: + resource_name (str): + Required. The resource name of the local + services lead that for which the feedback is + being provided. + survey_answer (google.ads.googleads.v24.enums.types.LocalServicesLeadSurveyAnswerEnum.SurveyAnswer): + Required. Survey answer for Local Services + Ads Lead. + survey_satisfied (google.ads.googleads.v24.services.types.SurveySatisfied): + Details about various factors for being + satisfied with the lead. + + This field is a member of `oneof`_ ``survey_details``. + survey_dissatisfied (google.ads.googleads.v24.services.types.SurveyDissatisfied): + Details about various factors for not being + satisfied with the lead. + + This field is a member of `oneof`_ ``survey_details``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + survey_answer: ( + local_services_lead_survey_answer.LocalServicesLeadSurveyAnswerEnum.SurveyAnswer + ) = proto.Field( + proto.ENUM, + number=2, + enum=local_services_lead_survey_answer.LocalServicesLeadSurveyAnswerEnum.SurveyAnswer, + ) + survey_satisfied: "SurveySatisfied" = proto.Field( + proto.MESSAGE, + number=3, + oneof="survey_details", + message="SurveySatisfied", + ) + survey_dissatisfied: "SurveyDissatisfied" = proto.Field( + proto.MESSAGE, + number=4, + oneof="survey_details", + message="SurveyDissatisfied", + ) + + +class ProvideLeadFeedbackResponse(proto.Message): + r"""Response message for + [LocalServicesLeadService.ProvideLeadFeedback][google.ads.googleads.v24.services.LocalServicesLeadService.ProvideLeadFeedback]. + + Attributes: + credit_issuance_decision (google.ads.googleads.v24.enums.types.LocalServicesLeadCreditIssuanceDecisionEnum.CreditIssuanceDecision): + Required. Decision of bonus credit issued or + rejected. If a bonus credit is issued, it will + be available for use in about two months. + """ + + credit_issuance_decision: ( + local_services_lead_credit_issuance_decision.LocalServicesLeadCreditIssuanceDecisionEnum.CreditIssuanceDecision + ) = proto.Field( + proto.ENUM, + number=1, + enum=local_services_lead_credit_issuance_decision.LocalServicesLeadCreditIssuanceDecisionEnum.CreditIssuanceDecision, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/offline_user_data_job_service.py b/google/ads/googleads/v24/services/types/offline_user_data_job_service.py new file mode 100644 index 000000000..56c1ef448 --- /dev/null +++ b/google/ads/googleads/v24/services/types/offline_user_data_job_service.py @@ -0,0 +1,254 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import offline_user_data +from google.ads.googleads.v24.resources.types import offline_user_data_job +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "CreateOfflineUserDataJobRequest", + "CreateOfflineUserDataJobResponse", + "RunOfflineUserDataJobRequest", + "AddOfflineUserDataJobOperationsRequest", + "OfflineUserDataJobOperation", + "AddOfflineUserDataJobOperationsResponse", + }, +) + + +class CreateOfflineUserDataJobRequest(proto.Message): + r"""Request message for + [OfflineUserDataJobService.CreateOfflineUserDataJob][google.ads.googleads.v24.services.OfflineUserDataJobService.CreateOfflineUserDataJob]. + + Attributes: + customer_id (str): + Required. The ID of the customer for which to + create an offline user data job. + job (google.ads.googleads.v24.resources.types.OfflineUserDataJob): + Required. The offline user data job to be + created. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + enable_match_rate_range_preview (bool): + If true, match rate range for the offline + user data job is calculated and made available + in the resource. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + job: offline_user_data_job.OfflineUserDataJob = proto.Field( + proto.MESSAGE, + number=2, + message=offline_user_data_job.OfflineUserDataJob, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + enable_match_rate_range_preview: bool = proto.Field( + proto.BOOL, + number=5, + ) + + +class CreateOfflineUserDataJobResponse(proto.Message): + r"""Response message for + [OfflineUserDataJobService.CreateOfflineUserDataJob][google.ads.googleads.v24.services.OfflineUserDataJobService.CreateOfflineUserDataJob]. + + Attributes: + resource_name (str): + The resource name of the OfflineUserDataJob. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class RunOfflineUserDataJobRequest(proto.Message): + r"""Request message for + [OfflineUserDataJobService.RunOfflineUserDataJob][google.ads.googleads.v24.services.OfflineUserDataJobService.RunOfflineUserDataJob]. + + Attributes: + resource_name (str): + Required. The resource name of the + OfflineUserDataJob to run. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=2, + ) + + +class AddOfflineUserDataJobOperationsRequest(proto.Message): + r"""Request message for + [OfflineUserDataJobService.AddOfflineUserDataJobOperations][google.ads.googleads.v24.services.OfflineUserDataJobService.AddOfflineUserDataJobOperations]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + resource_name (str): + Required. The resource name of the + OfflineUserDataJob. + enable_partial_failure (bool): + True to enable partial failure for the + offline user data job. + + This field is a member of `oneof`_ ``_enable_partial_failure``. + enable_warnings (bool): + True to enable warnings for the offline user + data job. When enabled, a warning will not block + the OfflineUserDataJobOperation, and will also + return warning messages about malformed field + values. + + This field is a member of `oneof`_ ``_enable_warnings``. + operations (MutableSequence[google.ads.googleads.v24.services.types.OfflineUserDataJobOperation]): + Required. The list of operations to be done. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + enable_partial_failure: bool = proto.Field( + proto.BOOL, + number=4, + optional=True, + ) + enable_warnings: bool = proto.Field( + proto.BOOL, + number=6, + optional=True, + ) + operations: MutableSequence["OfflineUserDataJobOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=3, + message="OfflineUserDataJobOperation", + ) + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=5, + ) + + +class OfflineUserDataJobOperation(proto.Message): + r"""Operation to be made for the + AddOfflineUserDataJobOperationsRequest. + + 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: + create (google.ads.googleads.v24.common.types.UserData): + Add the provided data to the transaction. + Data cannot be retrieved after being uploaded. + + This field is a member of `oneof`_ ``operation``. + remove (google.ads.googleads.v24.common.types.UserData): + Remove the provided data from the + transaction. Data cannot be retrieved after + being uploaded. + + This field is a member of `oneof`_ ``operation``. + remove_all (bool): + Remove all previously provided data. This is + only supported for Customer Match. + + This field is a member of `oneof`_ ``operation``. + """ + + create: offline_user_data.UserData = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=offline_user_data.UserData, + ) + remove: offline_user_data.UserData = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=offline_user_data.UserData, + ) + remove_all: bool = proto.Field( + proto.BOOL, + number=3, + oneof="operation", + ) + + +class AddOfflineUserDataJobOperationsResponse(proto.Message): + r"""Response message for + [OfflineUserDataJobService.AddOfflineUserDataJobOperations][google.ads.googleads.v24.services.OfflineUserDataJobService.AddOfflineUserDataJobOperations]. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + warning (google.rpc.status_pb2.Status): + Non blocking errors that pertain to operation failures in + the warnings mode. Returned only when enable_warnings = + true. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + warning: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/payments_account_service.py b/google/ads/googleads/v24/services/types/payments_account_service.py new file mode 100644 index 000000000..7e09b6e20 --- /dev/null +++ b/google/ads/googleads/v24/services/types/payments_account_service.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import payments_account + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "ListPaymentsAccountsRequest", + "ListPaymentsAccountsResponse", + }, +) + + +class ListPaymentsAccountsRequest(proto.Message): + r"""Request message for fetching all accessible payments + accounts. + + Attributes: + customer_id (str): + Required. The ID of the customer to apply the + PaymentsAccount list operation to. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + + +class ListPaymentsAccountsResponse(proto.Message): + r"""Response message for + [PaymentsAccountService.ListPaymentsAccounts][google.ads.googleads.v24.services.PaymentsAccountService.ListPaymentsAccounts]. + + Attributes: + payments_accounts (MutableSequence[google.ads.googleads.v24.resources.types.PaymentsAccount]): + The list of accessible payments accounts. + """ + + payments_accounts: MutableSequence[payments_account.PaymentsAccount] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=payments_account.PaymentsAccount, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/product_link_invitation_service.py b/google/ads/googleads/v24/services/types/product_link_invitation_service.py new file mode 100644 index 000000000..31e11ac44 --- /dev/null +++ b/google/ads/googleads/v24/services/types/product_link_invitation_service.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + product_link_invitation_status as gage_product_link_invitation_status, +) +from google.ads.googleads.v24.resources.types import ( + product_link_invitation as gagr_product_link_invitation, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "CreateProductLinkInvitationRequest", + "CreateProductLinkInvitationResponse", + "UpdateProductLinkInvitationRequest", + "UpdateProductLinkInvitationResponse", + "RemoveProductLinkInvitationRequest", + "RemoveProductLinkInvitationResponse", + }, +) + + +class CreateProductLinkInvitationRequest(proto.Message): + r"""Request message for + [ProductLinkInvitationService.CreateProductLinkInvitation][google.ads.googleads.v24.services.ProductLinkInvitationService.CreateProductLinkInvitation]. + + Attributes: + customer_id (str): + Required. The ID of the customer being + modified. + product_link_invitation (google.ads.googleads.v24.resources.types.ProductLinkInvitation): + Required. The product link invitation to be + created. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + product_link_invitation: ( + gagr_product_link_invitation.ProductLinkInvitation + ) = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_product_link_invitation.ProductLinkInvitation, + ) + + +class CreateProductLinkInvitationResponse(proto.Message): + r"""Response message for product link invitation create. + + Attributes: + resource_name (str): + Resource name of the product link invitation. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class UpdateProductLinkInvitationRequest(proto.Message): + r"""Request message for + [ProductLinkInvitationService.UpdateProductLinkInvitation][google.ads.googleads.v24.services.ProductLinkInvitationService.UpdateProductLinkInvitation]. + + Attributes: + customer_id (str): + Required. The ID of the customer being + modified. + product_link_invitation_status (google.ads.googleads.v24.enums.types.ProductLinkInvitationStatusEnum.ProductLinkInvitationStatus): + Required. The product link invitation to be + created. + resource_name (str): + Required. Resource name of the product link + invitation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + product_link_invitation_status: ( + gage_product_link_invitation_status.ProductLinkInvitationStatusEnum.ProductLinkInvitationStatus + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_product_link_invitation_status.ProductLinkInvitationStatusEnum.ProductLinkInvitationStatus, + ) + resource_name: str = proto.Field( + proto.STRING, + number=3, + ) + + +class UpdateProductLinkInvitationResponse(proto.Message): + r"""Response message for product link invitation update. + + Attributes: + resource_name (str): + Result of the update. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class RemoveProductLinkInvitationRequest(proto.Message): + r"""Request message for + [ProductLinkInvitationService.RemoveProductLinkInvitation][google.ads.googleads.v24.services.ProductLinkInvitationService.RemoveProductLinkInvitation]. + + Attributes: + customer_id (str): + Required. The ID of the product link + invitation being removed. + resource_name (str): + Required. The resource name of the product link invitation + being removed. expected, in this format: + + ``customers/{customer_id}/productLinkInvitations/{product_link_invitation_id}`` + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + resource_name: str = proto.Field( + proto.STRING, + number=2, + ) + + +class RemoveProductLinkInvitationResponse(proto.Message): + r"""Response message for product link invitation removeal. + + Attributes: + resource_name (str): + Result for the remove request. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/product_link_service.py b/google/ads/googleads/v24/services/types/product_link_service.py new file mode 100644 index 000000000..61485776b --- /dev/null +++ b/google/ads/googleads/v24/services/types/product_link_service.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import ( + product_link as gagr_product_link, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "CreateProductLinkRequest", + "CreateProductLinkResponse", + "RemoveProductLinkRequest", + "RemoveProductLinkResponse", + }, +) + + +class CreateProductLinkRequest(proto.Message): + r"""Request message for + [ProductLinkService.CreateProductLink][google.ads.googleads.v24.services.ProductLinkService.CreateProductLink]. + + Attributes: + customer_id (str): + Required. The ID of the customer for which + the product link is created. + product_link (google.ads.googleads.v24.resources.types.ProductLink): + Required. The product link to be created. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + product_link: gagr_product_link.ProductLink = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_product_link.ProductLink, + ) + + +class CreateProductLinkResponse(proto.Message): + r"""Response message for + [ProductLinkService.CreateProductLink][google.ads.googleads.v24.services.ProductLinkService.CreateProductLink]. + + Attributes: + resource_name (str): + Returned for successful operations. Resource + name of the product link. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class RemoveProductLinkRequest(proto.Message): + r"""Request message for + [ProductLinkService.RemoveProductLink][google.ads.googleads.v24.services.ProductLinkService.RemoveProductLink]. + + Attributes: + customer_id (str): + Required. The ID of the customer being + modified. + resource_name (str): + Required. Remove operation: A resource name for the product + link to remove is expected, in this format: + + ``customers/{customer_id}/productLinks/{product_link_id}`` + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + resource_name: str = proto.Field( + proto.STRING, + number=2, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class RemoveProductLinkResponse(proto.Message): + r"""Response message for product link removal. + + Attributes: + resource_name (str): + Result for the remove request. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/reach_plan_service.py b/google/ads/googleads/v24/services/types/reach_plan_service.py new file mode 100644 index 000000000..e278451d6 --- /dev/null +++ b/google/ads/googleads/v24/services/types/reach_plan_service.py @@ -0,0 +1,1920 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import additional_application_info +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.common.types import dates +from google.ads.googleads.v24.enums.types import frequency_cap_time_unit +from google.ads.googleads.v24.enums.types import reach_plan_age_range +from google.ads.googleads.v24.enums.types import reach_plan_buying_method +from google.ads.googleads.v24.enums.types import ( + reach_plan_conversion_rate_model, +) +from google.ads.googleads.v24.enums.types import reach_plan_cost_model +from google.ads.googleads.v24.enums.types import reach_plan_marketing_objective +from google.ads.googleads.v24.enums.types import reach_plan_network +from google.ads.googleads.v24.enums.types import ( + reach_plan_plannable_user_list_status, +) +from google.ads.googleads.v24.enums.types import reach_plan_surface +from google.ads.googleads.v24.enums.types import target_frequency_time_unit +from google.ads.googleads.v24.enums.types import user_interest_taxonomy_type +from google.ads.googleads.v24.enums.types import ( + user_list_crm_data_source_type as gage_user_list_crm_data_source_type, +) +from google.ads.googleads.v24.enums.types import ( + user_list_type as gage_user_list_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "GenerateConversionRatesRequest", + "GenerateConversionRatesResponse", + "ConversionRateSuggestion", + "ListPlannableLocationsRequest", + "ListPlannableLocationsResponse", + "PlannableLocation", + "ListPlannableProductsRequest", + "ListPlannableProductsResponse", + "ProductMetadata", + "ProductCoreAttributes", + "ListPlannableUserListsRequest", + "ListPlannableUserListsResponse", + "PlannableUserList", + "PlannableUserListMetadata", + "PlannableTargeting", + "ListPlannableUserInterestsRequest", + "ListPlannableUserInterestsResponse", + "PlannableUserInterest", + "GenerateReachForecastRequest", + "EffectiveFrequencyLimit", + "FrequencyCap", + "Targeting", + "CampaignDuration", + "PlannedProduct", + "GenerateReachForecastResponse", + "ReachCurve", + "ReachForecast", + "Forecast", + "PlannedProductReachForecast", + "PlannedProductForecast", + "OnTargetAudienceMetrics", + "EffectiveFrequencyBreakdown", + "ForecastMetricOptions", + "AudienceTargeting", + "AdvancedProductTargeting", + "YouTubeSelectSettings", + "YouTubeSelectLineUp", + "YouTubeSelectLineUpTargeting", + "SurfaceTargetingCombinations", + "SurfaceTargeting", + "TargetFrequencySettings", + }, +) + + +class GenerateConversionRatesRequest(proto.Message): + r"""Request message for + [ReachPlanService.GenerateConversionRates][google.ads.googleads.v24.services.ReachPlanService.GenerateConversionRates]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer_id (str): + Required. The ID of the customer. A + conversion rate based on the historical data of + this customer may be suggested. + customer_reach_group (str): + The name of the customer being planned for. + This is a user-defined value. + + This field is a member of `oneof`_ ``_customer_reach_group``. + reach_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + customer_reach_group: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + reach_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=3, + message=additional_application_info.AdditionalApplicationInfo, + ) + + +class GenerateConversionRatesResponse(proto.Message): + r"""Response message for + [ReachPlanService.GenerateConversionRates][google.ads.googleads.v24.services.ReachPlanService.GenerateConversionRates], + containing conversion rate suggestions for supported plannable + products. + + Attributes: + conversion_rate_suggestions (MutableSequence[google.ads.googleads.v24.services.types.ConversionRateSuggestion]): + A list containing conversion rate + suggestions. Each repeated element will have an + associated product code. Multiple suggestions + may share the same product code. + """ + + conversion_rate_suggestions: MutableSequence["ConversionRateSuggestion"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ConversionRateSuggestion", + ) + ) + + +class ConversionRateSuggestion(proto.Message): + r"""A conversion rate suggestion. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + conversion_rate_model (google.ads.googleads.v24.enums.types.ReachPlanConversionRateModelEnum.ReachPlanConversionRateModel): + Model type used to calculate the suggested + conversion rate. + plannable_product_code (str): + The code associated with the plannable product (for example: + DEMAND_GEN). To list all plannable product codes, use + [ReachPlanService.ListPlannableProducts][google.ads.googleads.v24.services.ReachPlanService.ListPlannableProducts]. + surface_targeting (google.ads.googleads.v24.services.types.SurfaceTargeting): + The surfaces associated with the plannable + product. If not present, the conversion rate is + considered surface agnostic for this product. + + This field is a member of `oneof`_ ``_surface_targeting``. + conversion_rate (float): + The suggested conversion rate. The value is + between 0 and 1 (exclusive). + """ + + conversion_rate_model: ( + reach_plan_conversion_rate_model.ReachPlanConversionRateModelEnum.ReachPlanConversionRateModel + ) = proto.Field( + proto.ENUM, + number=1, + enum=reach_plan_conversion_rate_model.ReachPlanConversionRateModelEnum.ReachPlanConversionRateModel, + ) + plannable_product_code: str = proto.Field( + proto.STRING, + number=2, + ) + surface_targeting: "SurfaceTargeting" = proto.Field( + proto.MESSAGE, + number=4, + optional=True, + message="SurfaceTargeting", + ) + conversion_rate: float = proto.Field( + proto.DOUBLE, + number=3, + ) + + +class ListPlannableLocationsRequest(proto.Message): + r"""Request message for + [ReachPlanService.ListPlannableLocations][google.ads.googleads.v24.services.ReachPlanService.ListPlannableLocations]. + + Attributes: + reach_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + """ + + reach_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=1, + message=additional_application_info.AdditionalApplicationInfo, + ) + + +class ListPlannableLocationsResponse(proto.Message): + r"""The list of plannable locations. + + Attributes: + plannable_locations (MutableSequence[google.ads.googleads.v24.services.types.PlannableLocation]): + The list of locations available for planning. + See + https://developers.google.com/google-ads/api/reference/data/geotargets + for sample locations. + """ + + plannable_locations: MutableSequence["PlannableLocation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="PlannableLocation", + ) + ) + + +class PlannableLocation(proto.Message): + r"""A plannable location: country, metro region, province, etc. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + id (str): + The location identifier. + + This field is a member of `oneof`_ ``_id``. + name (str): + The unique location name in English. + + This field is a member of `oneof`_ ``_name``. + parent_country_id (int): + The parent country (not present if location is a country). + If present, will always be a GeoTargetConstant ID. + Additional information such as country name is provided by + [ReachPlanService.ListPlannableLocations][google.ads.googleads.v24.services.ReachPlanService.ListPlannableLocations] + or GoogleAdsService.Search/SearchStream. + + This field is a member of `oneof`_ ``_parent_country_id``. + country_code (str): + The ISO-3166-1 alpha-2 country code that is + associated with the location. + + This field is a member of `oneof`_ ``_country_code``. + location_type (str): + The location's type. Location types correspond to + target_type returned by searching location type in + GoogleAdsService.Search/SearchStream. + + This field is a member of `oneof`_ ``_location_type``. + """ + + id: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + parent_country_id: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + country_code: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + location_type: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + + +class ListPlannableProductsRequest(proto.Message): + r"""Request to list available products in a given location. + + Attributes: + plannable_location_id (str): + Required. The ID of the selected location for planning. To + list the available plannable location IDs use + [ReachPlanService.ListPlannableLocations][google.ads.googleads.v24.services.ReachPlanService.ListPlannableLocations]. + reach_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + """ + + plannable_location_id: str = proto.Field( + proto.STRING, + number=2, + ) + reach_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=3, + message=additional_application_info.AdditionalApplicationInfo, + ) + + +class ListPlannableProductsResponse(proto.Message): + r"""A response with all available products. + + Attributes: + product_metadata (MutableSequence[google.ads.googleads.v24.services.types.ProductMetadata]): + The list of products available for planning + and related targeting metadata. + """ + + product_metadata: MutableSequence["ProductMetadata"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ProductMetadata", + ) + + +class ProductMetadata(proto.Message): + r"""The metadata associated with an available plannable product. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + plannable_product_code (str): + The code associated with the ad product. + + For example: "VIDEO_VIEW_CAMPAIGN". To list the available + plannable product codes use + [ReachPlanService.ListPlannableProducts][google.ads.googleads.v24.services.ReachPlanService.ListPlannableProducts]. + + This field is a member of `oneof`_ ``_plannable_product_code``. + plannable_product_name (str): + The name associated with the ad product. + + For example: "Video View Campaign". + plannable_product_description (str): + The plain-text description of the ad product. + + For example: "Video view campaign allows you to + plan for a configurable mix of skippable + in-stream, in-feed, and Shorts video ads in a + single campaign designed to drive more views.". + + This field is a member of `oneof`_ ``_plannable_product_description``. + plannable_product_core_attributes (google.ads.googleads.v24.services.types.ProductCoreAttributes): + Descriptive attributes of the ad product to + further describe its capabilities. + + This field is a member of `oneof`_ ``_plannable_product_core_attributes``. + plannable_targeting (google.ads.googleads.v24.services.types.PlannableTargeting): + The allowed plannable targeting for this + product. + """ + + plannable_product_code: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + plannable_product_name: str = proto.Field( + proto.STRING, + number=3, + ) + plannable_product_description: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + plannable_product_core_attributes: "ProductCoreAttributes" = proto.Field( + proto.MESSAGE, + number=6, + optional=True, + message="ProductCoreAttributes", + ) + plannable_targeting: "PlannableTargeting" = proto.Field( + proto.MESSAGE, + number=2, + message="PlannableTargeting", + ) + + +class ProductCoreAttributes(proto.Message): + r"""A collection of attributes that offer more information about + a specific product. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + marketing_objective (google.ads.googleads.v24.enums.types.ReachPlanMarketingObjectiveEnum.ReachPlanMarketingObjective): + A specific, measurable goal that a company + wants to achieve through its marketing efforts. + + This field is a member of `oneof`_ ``_marketing_objective``. + cost_model (google.ads.googleads.v24.enums.types.ReachPlanCostModelEnum.ReachPlanCostModel): + How an advertiser pays for their ad campaign. + + This field is a member of `oneof`_ ``_cost_model``. + buying_method (google.ads.googleads.v24.enums.types.ReachPlanBuyingMethodEnum.ReachPlanBuyingMethod): + The method of buying this product. + + For example, Auction pricing is dynamic and + Reservation is booked at a fixed price. + + This field is a member of `oneof`_ ``_buying_method``. + """ + + marketing_objective: ( + reach_plan_marketing_objective.ReachPlanMarketingObjectiveEnum.ReachPlanMarketingObjective + ) = proto.Field( + proto.ENUM, + number=1, + optional=True, + enum=reach_plan_marketing_objective.ReachPlanMarketingObjectiveEnum.ReachPlanMarketingObjective, + ) + cost_model: ( + reach_plan_cost_model.ReachPlanCostModelEnum.ReachPlanCostModel + ) = proto.Field( + proto.ENUM, + number=2, + optional=True, + enum=reach_plan_cost_model.ReachPlanCostModelEnum.ReachPlanCostModel, + ) + buying_method: ( + reach_plan_buying_method.ReachPlanBuyingMethodEnum.ReachPlanBuyingMethod + ) = proto.Field( + proto.ENUM, + number=3, + optional=True, + enum=reach_plan_buying_method.ReachPlanBuyingMethodEnum.ReachPlanBuyingMethod, + ) + + +class ListPlannableUserListsRequest(proto.Message): + r"""Request message for + [ReachPlanService.ListPlannableUserLists][google.ads.googleads.v24.services.ReachPlanService.ListPlannableUserLists] + that lists the available user lists for a customer. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer_id (str): + Required. The ID of the customer. + customer_reach_group (str): + The name of the customer being planned for. + This is a user-defined value. + + This field is a member of `oneof`_ ``_customer_reach_group``. + reach_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + customer_reach_group: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + reach_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=3, + message=additional_application_info.AdditionalApplicationInfo, + ) + + +class ListPlannableUserListsResponse(proto.Message): + r"""A response with all available user lists with their plannable + status. + + Attributes: + plannable_user_lists (MutableSequence[google.ads.googleads.v24.services.types.PlannableUserList]): + The list of user lists available for planning + and related targeting metadata. + """ + + plannable_user_lists: MutableSequence["PlannableUserList"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="PlannableUserList", + ) + ) + + +class PlannableUserList(proto.Message): + r"""A plannable user list. + + Attributes: + user_list_info (google.ads.googleads.v24.common.types.UserListInfo): + The user list ID. + display_name (str): + The name of the user list. + user_list_type (google.ads.googleads.v24.enums.types.UserListTypeEnum.UserListType): + The user list type. + plannable_status (google.ads.googleads.v24.enums.types.ReachPlanPlannableUserListStatusEnum.ReachPlanPlannableUserListStatus): + The plannable status of the user list. + plannable_user_list_metadata (google.ads.googleads.v24.services.types.PlannableUserListMetadata): + The relevant metadata for this user list. + """ + + user_list_info: criteria.UserListInfo = proto.Field( + proto.MESSAGE, + number=1, + message=criteria.UserListInfo, + ) + display_name: str = proto.Field( + proto.STRING, + number=2, + ) + user_list_type: gage_user_list_type.UserListTypeEnum.UserListType = ( + proto.Field( + proto.ENUM, + number=3, + enum=gage_user_list_type.UserListTypeEnum.UserListType, + ) + ) + plannable_status: ( + reach_plan_plannable_user_list_status.ReachPlanPlannableUserListStatusEnum.ReachPlanPlannableUserListStatus + ) = proto.Field( + proto.ENUM, + number=4, + enum=reach_plan_plannable_user_list_status.ReachPlanPlannableUserListStatusEnum.ReachPlanPlannableUserListStatus, + ) + plannable_user_list_metadata: "PlannableUserListMetadata" = proto.Field( + proto.MESSAGE, + number=5, + message="PlannableUserListMetadata", + ) + + +class PlannableUserListMetadata(proto.Message): + r"""The metadata associated with a plannable user list. + + Attributes: + user_list_crm_data_source_type (google.ads.googleads.v24.enums.types.UserListCrmDataSourceTypeEnum.UserListCrmDataSourceType): + The data source type of a CRM based user + list. + """ + + user_list_crm_data_source_type: ( + gage_user_list_crm_data_source_type.UserListCrmDataSourceTypeEnum.UserListCrmDataSourceType + ) = proto.Field( + proto.ENUM, + number=1, + enum=gage_user_list_crm_data_source_type.UserListCrmDataSourceTypeEnum.UserListCrmDataSourceType, + ) + + +class PlannableTargeting(proto.Message): + r"""The targeting for which traffic metrics will be reported. + + Attributes: + age_ranges (MutableSequence[google.ads.googleads.v24.enums.types.ReachPlanAgeRangeEnum.ReachPlanAgeRange]): + Allowed plannable age ranges for the product + for which metrics will be reported. Actual + targeting is computed by mapping this age range + onto standard Google common.AgeRangeInfo values. + genders (MutableSequence[google.ads.googleads.v24.common.types.GenderInfo]): + Targetable genders for the ad product. + devices (MutableSequence[google.ads.googleads.v24.common.types.DeviceInfo]): + Targetable devices for the ad product. TABLET device + targeting is automatically applied to reported metrics when + MOBILE targeting is selected for CPM_MASTHEAD, + GOOGLE_PREFERRED_BUMPER, and GOOGLE_PREFERRED_SHORT + products. + networks (MutableSequence[google.ads.googleads.v24.enums.types.ReachPlanNetworkEnum.ReachPlanNetwork]): + Targetable networks for the ad product. + youtube_select_lineup_targeting (google.ads.googleads.v24.services.types.YouTubeSelectLineUpTargeting): + Targetable YouTube Select Lineups for the ad product. + + This field replaces the deprecated + ``youtube_select_lineups`` field. + surface_targeting (google.ads.googleads.v24.services.types.SurfaceTargetingCombinations): + Targetable surface combinations for the ad + product. + """ + + age_ranges: MutableSequence[ + reach_plan_age_range.ReachPlanAgeRangeEnum.ReachPlanAgeRange + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum=reach_plan_age_range.ReachPlanAgeRangeEnum.ReachPlanAgeRange, + ) + genders: MutableSequence[criteria.GenderInfo] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=criteria.GenderInfo, + ) + devices: MutableSequence[criteria.DeviceInfo] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=criteria.DeviceInfo, + ) + networks: MutableSequence[ + reach_plan_network.ReachPlanNetworkEnum.ReachPlanNetwork + ] = proto.RepeatedField( + proto.ENUM, + number=4, + enum=reach_plan_network.ReachPlanNetworkEnum.ReachPlanNetwork, + ) + youtube_select_lineup_targeting: "YouTubeSelectLineUpTargeting" = ( + proto.Field( + proto.MESSAGE, + number=7, + message="YouTubeSelectLineUpTargeting", + ) + ) + surface_targeting: "SurfaceTargetingCombinations" = proto.Field( + proto.MESSAGE, + number=6, + message="SurfaceTargetingCombinations", + ) + + +class ListPlannableUserInterestsRequest(proto.Message): + r"""Request message for + [ReachPlanService.ListPlannableUserInterests][google.ads.googleads.v24.services.ReachPlanService.ListPlannableUserInterests]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer_id (str): + Required. The ID of the customer. + user_interest_taxonomy_types (MutableSequence[google.ads.googleads.v24.enums.types.UserInterestTaxonomyTypeEnum.UserInterestTaxonomyType]): + Optional. A filter by user interest type. If set, only user + interests with a type listed in the filter will be returned. + If not set, user interests of all supported types will be + returned. Supported user interest types are AFFINITY and + IN_MARKET. Each type must be specified at most once. + name_query (str): + A filter by user interest name. If set, only + user interests with a name containing the + literal string (case insensitive) in the filter + will be returned. Maximum length is 200 + characters. + + This field is a member of `oneof`_ ``_name_query``. + path_query (str): + A filter by user interest path. If set, only + user interests with a path containing the + literal string (case insensitive) in the filter + will be returned. Maximum length is 200 + characters. + + This field is a member of `oneof`_ ``_path_query``. + reach_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + user_interest_taxonomy_types: MutableSequence[ + user_interest_taxonomy_type.UserInterestTaxonomyTypeEnum.UserInterestTaxonomyType + ] = proto.RepeatedField( + proto.ENUM, + number=2, + enum=user_interest_taxonomy_type.UserInterestTaxonomyTypeEnum.UserInterestTaxonomyType, + ) + name_query: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + path_query: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + reach_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=5, + message=additional_application_info.AdditionalApplicationInfo, + ) + + +class ListPlannableUserInterestsResponse(proto.Message): + r"""Response message for + [ReachPlanService.ListPlannableUserInterests][google.ads.googleads.v24.services.ReachPlanService.ListPlannableUserInterests]. + + Attributes: + plannable_user_interests (MutableSequence[google.ads.googleads.v24.services.types.PlannableUserInterest]): + The list of plannable user interests. + """ + + plannable_user_interests: MutableSequence["PlannableUserInterest"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="PlannableUserInterest", + ) + ) + + +class PlannableUserInterest(proto.Message): + r"""A plannable user interest that can be targeted in a reach forecast + using + [ReachPlanService.GenerateReachForecast][google.ads.googleads.v24.services.ReachPlanService.GenerateReachForecast]. + + Attributes: + user_interest (google.ads.googleads.v24.common.types.UserInterestInfo): + The user interest id. + user_interest_type (google.ads.googleads.v24.enums.types.UserInterestTaxonomyTypeEnum.UserInterestTaxonomyType): + The user interest type. + user_interest_display_name (str): + The user interest display name. + For example, "Autos & Vehicles". + user_interest_path (str): + The user interest path. + For example, "/Autos & Vehicles/Motor + Vehicles/Motor Vehicles by Type/Off-Road + Vehicles". + """ + + user_interest: criteria.UserInterestInfo = proto.Field( + proto.MESSAGE, + number=1, + message=criteria.UserInterestInfo, + ) + user_interest_type: ( + user_interest_taxonomy_type.UserInterestTaxonomyTypeEnum.UserInterestTaxonomyType + ) = proto.Field( + proto.ENUM, + number=2, + enum=user_interest_taxonomy_type.UserInterestTaxonomyTypeEnum.UserInterestTaxonomyType, + ) + user_interest_display_name: str = proto.Field( + proto.STRING, + number=3, + ) + user_interest_path: str = proto.Field( + proto.STRING, + number=4, + ) + + +class GenerateReachForecastRequest(proto.Message): + r"""Request message for + [ReachPlanService.GenerateReachForecast][google.ads.googleads.v24.services.ReachPlanService.GenerateReachForecast]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer_id (str): + Required. The ID of the customer. + currency_code (str): + The currency code. + Three-character ISO 4217 currency code. + + This field is a member of `oneof`_ ``_currency_code``. + campaign_duration (google.ads.googleads.v24.services.types.CampaignDuration): + Required. Campaign duration. + cookie_frequency_cap (int): + Chosen cookie frequency cap to be applied to each planned + product. This is equivalent to the frequency cap exposed in + Google Ads when creating a campaign, it represents the + maximum number of times an ad can be shown to the same user. + If not specified, no cap is applied. + + This field is deprecated and will eventually be removed. Use + cookie_frequency_cap_setting instead. + + This field is a member of `oneof`_ ``_cookie_frequency_cap``. + cookie_frequency_cap_setting (google.ads.googleads.v24.services.types.FrequencyCap): + Chosen cookie frequency cap to be applied to each planned + product. This is equivalent to the frequency cap exposed in + Google Ads when creating a campaign, it represents the + maximum number of times an ad can be shown to the same user + during a specified time interval. If not specified, a + default of 0 (no cap) is applied. + + This field replaces the deprecated ``cookie_frequency_cap`` + field. + min_effective_frequency (int): + Chosen minimum effective frequency (the number of times a + person was exposed to the ad) for the reported reach metrics + [1-10]. This won't affect the targeting, but just the + reporting. If not specified, a default of 1 is applied. + + This field cannot be combined with the + effective_frequency_limit field. + + This field is a member of `oneof`_ ``_min_effective_frequency``. + effective_frequency_limit (google.ads.googleads.v24.services.types.EffectiveFrequencyLimit): + The highest minimum effective frequency (the number of times + a person was exposed to the ad) value [1-10] to include in + Forecast.effective_frequency_breakdowns. If not specified, + Forecast.effective_frequency_breakdowns will not be + provided. + + The effective frequency value provided here will also be + used as the minimum effective frequency for the reported + reach metrics. + + This field cannot be combined with the + min_effective_frequency field. + + This field is a member of `oneof`_ ``_effective_frequency_limit``. + targeting (google.ads.googleads.v24.services.types.Targeting): + The targeting to be applied to all products + selected in the product mix. + This is planned targeting: execution details + might vary based on the advertising product, + consult an implementation specialist. + + See specific metrics for details on how + targeting affects them. + planned_products (MutableSequence[google.ads.googleads.v24.services.types.PlannedProduct]): + Required. The products to be forecast. + The max number of allowed planned products is + 15. + forecast_metric_options (google.ads.googleads.v24.services.types.ForecastMetricOptions): + Controls the forecast metrics returned in the + response. + customer_reach_group (str): + The name of the customer being planned for. + This is a user-defined value. + + This field is a member of `oneof`_ ``_customer_reach_group``. + reach_application_info (google.ads.googleads.v24.common.types.AdditionalApplicationInfo): + Optional. Additional information on the + application issuing the request. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + currency_code: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + campaign_duration: "CampaignDuration" = proto.Field( + proto.MESSAGE, + number=3, + message="CampaignDuration", + ) + cookie_frequency_cap: int = proto.Field( + proto.INT32, + number=10, + optional=True, + ) + cookie_frequency_cap_setting: "FrequencyCap" = proto.Field( + proto.MESSAGE, + number=8, + message="FrequencyCap", + ) + min_effective_frequency: int = proto.Field( + proto.INT32, + number=11, + optional=True, + ) + effective_frequency_limit: "EffectiveFrequencyLimit" = proto.Field( + proto.MESSAGE, + number=12, + optional=True, + message="EffectiveFrequencyLimit", + ) + targeting: "Targeting" = proto.Field( + proto.MESSAGE, + number=6, + message="Targeting", + ) + planned_products: MutableSequence["PlannedProduct"] = proto.RepeatedField( + proto.MESSAGE, + number=7, + message="PlannedProduct", + ) + forecast_metric_options: "ForecastMetricOptions" = proto.Field( + proto.MESSAGE, + number=13, + message="ForecastMetricOptions", + ) + customer_reach_group: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + reach_application_info: ( + additional_application_info.AdditionalApplicationInfo + ) = proto.Field( + proto.MESSAGE, + number=15, + message=additional_application_info.AdditionalApplicationInfo, + ) + + +class EffectiveFrequencyLimit(proto.Message): + r"""Effective frequency limit. + + Attributes: + effective_frequency_breakdown_limit (int): + The highest effective frequency value to include in + Forecast.effective_frequency_breakdowns. This field supports + frequencies 1-10, inclusive. + """ + + effective_frequency_breakdown_limit: int = proto.Field( + proto.INT32, + number=1, + ) + + +class FrequencyCap(proto.Message): + r"""A rule specifying the maximum number of times an ad can be + shown to a user over a particular time period. + + Attributes: + impressions (int): + Required. The number of impressions, + inclusive. + time_unit (google.ads.googleads.v24.enums.types.FrequencyCapTimeUnitEnum.FrequencyCapTimeUnit): + Required. The type of time unit. + """ + + impressions: int = proto.Field( + proto.INT32, + number=3, + ) + time_unit: ( + frequency_cap_time_unit.FrequencyCapTimeUnitEnum.FrequencyCapTimeUnit + ) = proto.Field( + proto.ENUM, + number=2, + enum=frequency_cap_time_unit.FrequencyCapTimeUnitEnum.FrequencyCapTimeUnit, + ) + + +class Targeting(proto.Message): + r"""The targeting for which traffic metrics will be reported. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + plannable_location_id (str): + The ID of the selected location. Plannable location IDs can + be obtained from + [ReachPlanService.ListPlannableLocations][google.ads.googleads.v24.services.ReachPlanService.ListPlannableLocations]. + + Requests must set either this field or + ``plannable_location_ids``. + + This field is deprecated and will be removed in a future + release. Use ``plannable_location_ids`` instead. + + This field is a member of `oneof`_ ``_plannable_location_id``. + plannable_location_ids (MutableSequence[str]): + The list of plannable location IDs to target with this + forecast. + + If more than one ID is provided, all IDs must have the same + ``parent_country_id``. Planning for more than + ``parent_county`` is not supported. Plannable location IDs + and their ``parent_country_id`` can be obtained from + [ReachPlanService.ListPlannableLocations][google.ads.googleads.v24.services.ReachPlanService.ListPlannableLocations]. + + Requests must set either this field or + ``plannable_location_id``. + age_range (google.ads.googleads.v24.enums.types.ReachPlanAgeRangeEnum.ReachPlanAgeRange): + Targeted age range. + An unset value is equivalent to targeting all + ages. + genders (MutableSequence[google.ads.googleads.v24.common.types.GenderInfo]): + Targeted genders. + An unset value is equivalent to targeting MALE + and FEMALE. + devices (MutableSequence[google.ads.googleads.v24.common.types.DeviceInfo]): + Targeted devices. If not specified, targets all applicable + devices. Applicable devices vary by product and region and + can be obtained from + [ReachPlanService.ListPlannableProducts][google.ads.googleads.v24.services.ReachPlanService.ListPlannableProducts]. + network (google.ads.googleads.v24.enums.types.ReachPlanNetworkEnum.ReachPlanNetwork): + Targetable network for the ad product. If not specified, + targets all applicable networks. Applicable networks vary by + product and region and can be obtained from + [ReachPlanService.ListPlannableProducts][google.ads.googleads.v24.services.ReachPlanService.ListPlannableProducts]. + audience_targeting (google.ads.googleads.v24.services.types.AudienceTargeting): + Targeted audiences. + If not specified, does not target any specific + audience. + """ + + plannable_location_id: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + plannable_location_ids: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=8, + ) + age_range: reach_plan_age_range.ReachPlanAgeRangeEnum.ReachPlanAgeRange = ( + proto.Field( + proto.ENUM, + number=2, + enum=reach_plan_age_range.ReachPlanAgeRangeEnum.ReachPlanAgeRange, + ) + ) + genders: MutableSequence[criteria.GenderInfo] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=criteria.GenderInfo, + ) + devices: MutableSequence[criteria.DeviceInfo] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=criteria.DeviceInfo, + ) + network: reach_plan_network.ReachPlanNetworkEnum.ReachPlanNetwork = ( + proto.Field( + proto.ENUM, + number=5, + enum=reach_plan_network.ReachPlanNetworkEnum.ReachPlanNetwork, + ) + ) + audience_targeting: "AudienceTargeting" = proto.Field( + proto.MESSAGE, + number=7, + message="AudienceTargeting", + ) + + +class CampaignDuration(proto.Message): + r"""The duration of a planned campaign. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + duration_in_days (int): + The duration value in days. + + This field cannot be combined with the date_range field. + + This field is a member of `oneof`_ ``_duration_in_days``. + date_range (google.ads.googleads.v24.common.types.DateRange): + Date range of the campaign. Dates are in the yyyy-mm-dd + format and inclusive. The end date must be < 1 year in the + future and the date range must be <= 92 days long. + + This field cannot be combined with the duration_in_days + field. + """ + + duration_in_days: int = proto.Field( + proto.INT32, + number=2, + optional=True, + ) + date_range: dates.DateRange = proto.Field( + proto.MESSAGE, + number=3, + message=dates.DateRange, + ) + + +class PlannedProduct(proto.Message): + r"""A product being planned for reach. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + plannable_product_code (str): + Required. Selected product for planning. The code associated + with the ad product (for example: Trueview, Bumper). To list + the available plannable product codes use + [ReachPlanService.ListPlannableProducts][google.ads.googleads.v24.services.ReachPlanService.ListPlannableProducts]. + + This field is a member of `oneof`_ ``_plannable_product_code``. + budget_micros (int): + Required. Maximum budget allocation in micros for the + selected product. The value is specified in the selected + planning currency_code. For example: 1 000 000$ = 1 000 000 + 000 000 micros. + + This field is a member of `oneof`_ ``_budget_micros``. + conversion_rate (float): + Conversion rate as a decimal between 0 and 1, exclusive. For + example: if 2% of ad interactions are expected to lead to + conversions, conversion_rate should be 0.02. This field is + required for DEMAND_GEN plannable products. It is not + supported for other plannable products. + + This field is a member of `oneof`_ ``_conversion_rate``. + advanced_product_targeting (google.ads.googleads.v24.services.types.AdvancedProductTargeting): + Targeting settings for the selected product. To list the + available targeting for each product use + [ReachPlanService.ListPlannableProducts][google.ads.googleads.v24.services.ReachPlanService.ListPlannableProducts]. + """ + + plannable_product_code: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + budget_micros: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + conversion_rate: float = proto.Field( + proto.DOUBLE, + number=6, + optional=True, + ) + advanced_product_targeting: "AdvancedProductTargeting" = proto.Field( + proto.MESSAGE, + number=5, + message="AdvancedProductTargeting", + ) + + +class GenerateReachForecastResponse(proto.Message): + r"""Response message containing the generated reach curve. + + Attributes: + on_target_audience_metrics (google.ads.googleads.v24.services.types.OnTargetAudienceMetrics): + Reference on target audiences for this curve. + reach_curve (google.ads.googleads.v24.services.types.ReachCurve): + The generated reach curve for the planned + product mix. + """ + + on_target_audience_metrics: "OnTargetAudienceMetrics" = proto.Field( + proto.MESSAGE, + number=1, + message="OnTargetAudienceMetrics", + ) + reach_curve: "ReachCurve" = proto.Field( + proto.MESSAGE, + number=2, + message="ReachCurve", + ) + + +class ReachCurve(proto.Message): + r"""The reach curve for the planned products. + + Attributes: + reach_forecasts (MutableSequence[google.ads.googleads.v24.services.types.ReachForecast]): + All points on the reach curve. + """ + + reach_forecasts: MutableSequence["ReachForecast"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ReachForecast", + ) + + +class ReachForecast(proto.Message): + r"""A point on reach curve. + + Attributes: + cost_micros (int): + The cost in micros. + forecast (google.ads.googleads.v24.services.types.Forecast): + Forecasted traffic metrics for this point. + planned_product_reach_forecasts (MutableSequence[google.ads.googleads.v24.services.types.PlannedProductReachForecast]): + The forecasted allocation and traffic metrics + for each planned product at this point on the + reach curve. + """ + + cost_micros: int = proto.Field( + proto.INT64, + number=5, + ) + forecast: "Forecast" = proto.Field( + proto.MESSAGE, + number=2, + message="Forecast", + ) + planned_product_reach_forecasts: MutableSequence[ + "PlannedProductReachForecast" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="PlannedProductReachForecast", + ) + + +class Forecast(proto.Message): + r"""Forecasted traffic metrics for the planned products and + targeting. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + on_target_reach (int): + Number of unique people reached at least + GenerateReachForecastRequest.min_effective_frequency or + GenerateReachForecastRequest.effective_frequency_limit times + that exactly matches the Targeting. + + Note that a minimum number of unique people must be reached + in order for data to be reported. If the minimum number is + not met, the on_target_reach value will be rounded to 0. + + This field is a member of `oneof`_ ``_on_target_reach``. + total_reach (int): + Total number of unique people reached at least + GenerateReachForecastRequest.min_effective_frequency or + GenerateReachForecastRequest.effective_frequency_limit + times. This includes people that may fall outside the + specified Targeting. + + Note that a minimum number of unique people must be reached + in order for data to be reported. If the minimum number is + not met, the total_reach value will be rounded to 0. + + This field is a member of `oneof`_ ``_total_reach``. + on_target_impressions (int): + Number of ad impressions that exactly matches + the Targeting. + + This field is a member of `oneof`_ ``_on_target_impressions``. + total_impressions (int): + Total number of ad impressions. This includes + impressions that may fall outside the specified + Targeting, due to insufficient information on + signed-in users. + + This field is a member of `oneof`_ ``_total_impressions``. + viewable_impressions (int): + Number of times the ad's impressions were + considered viewable. See + https://support.google.com/google-ads/answer/7029393 + for more information about what makes an ad + viewable and how viewability is measured. + + This field is a member of `oneof`_ ``_viewable_impressions``. + effective_frequency_breakdowns (MutableSequence[google.ads.googleads.v24.services.types.EffectiveFrequencyBreakdown]): + A list of effective frequency forecasts. The list is ordered + starting with 1+ and ending with the value set in + GenerateReachForecastRequest.effective_frequency_limit. If + no effective_frequency_limit was set, this list will be + empty. + on_target_coview_reach (int): + Number of unique people reached that exactly + matches the Targeting including co-viewers. + + This field is a member of `oneof`_ ``_on_target_coview_reach``. + total_coview_reach (int): + Number of unique people reached including + co-viewers. This includes people that may fall + outside the specified Targeting. + + This field is a member of `oneof`_ ``_total_coview_reach``. + on_target_coview_impressions (int): + Number of ad impressions that exactly matches + the Targeting including co-viewers. + + This field is a member of `oneof`_ ``_on_target_coview_impressions``. + total_coview_impressions (int): + Total number of ad impressions including + co-viewers. This includes impressions that may + fall outside the specified Targeting, due to + insufficient information on signed-in users. + + This field is a member of `oneof`_ ``_total_coview_impressions``. + conversions (float): + The number of conversions. This metric is only available for + DEMAND_GEN plannable products. + + See https://support.google.com/google-ads/answer/2375431 for + more information on conversions. + + This field is a member of `oneof`_ ``_conversions``. + trueview_views (int): + Number of ad views forecasted for the + specified product and targeting. A TrueView View + is counted when a viewer views a larger portion + or the entirety of an ad beyond an impression. + + See + https://support.google.com/google-ads/answer/2375431 + for more information on TrueView Views. + + This field is a member of `oneof`_ ``_trueview_views``. + clicks (int): + The number of clicks, which is the main user + action associated with an ad format of bid type + CPC (Cost-Per-Click). + + See + https://support.google.com/google-ads/answer/31799 + for more information on clicks. + + This field is a member of `oneof`_ ``_clicks``. + """ + + on_target_reach: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + total_reach: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + on_target_impressions: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + total_impressions: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + viewable_impressions: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + effective_frequency_breakdowns: MutableSequence[ + "EffectiveFrequencyBreakdown" + ] = proto.RepeatedField( + proto.MESSAGE, + number=10, + message="EffectiveFrequencyBreakdown", + ) + on_target_coview_reach: int = proto.Field( + proto.INT64, + number=11, + optional=True, + ) + total_coview_reach: int = proto.Field( + proto.INT64, + number=12, + optional=True, + ) + on_target_coview_impressions: int = proto.Field( + proto.INT64, + number=13, + optional=True, + ) + total_coview_impressions: int = proto.Field( + proto.INT64, + number=14, + optional=True, + ) + conversions: float = proto.Field( + proto.DOUBLE, + number=16, + optional=True, + ) + trueview_views: int = proto.Field( + proto.INT64, + number=17, + optional=True, + ) + clicks: int = proto.Field( + proto.INT64, + number=18, + optional=True, + ) + + +class PlannedProductReachForecast(proto.Message): + r"""The forecasted allocation and traffic metrics for a specific + product at a point on the reach curve. + + Attributes: + plannable_product_code (str): + Selected product for planning. The product + codes returned are within the set of the ones + returned by ListPlannableProducts when using the + same location ID. + cost_micros (int): + The cost in micros. This may differ from the + product's input allocation if one or more + planned products cannot fulfill the budget + because of limited inventory. + planned_product_forecast (google.ads.googleads.v24.services.types.PlannedProductForecast): + Forecasted traffic metrics for this product. + """ + + plannable_product_code: str = proto.Field( + proto.STRING, + number=1, + ) + cost_micros: int = proto.Field( + proto.INT64, + number=2, + ) + planned_product_forecast: "PlannedProductForecast" = proto.Field( + proto.MESSAGE, + number=3, + message="PlannedProductForecast", + ) + + +class PlannedProductForecast(proto.Message): + r"""Forecasted traffic metrics for a planned product. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + on_target_reach (int): + Number of unique people reached that exactly matches the + Targeting. + + Note that a minimum number of unique people must be reached + in order for data to be reported. If the minimum number is + not met, the on_target_reach value will be rounded to 0. + total_reach (int): + Number of unique people reached. This includes people that + may fall outside the specified Targeting. + + Note that a minimum number of unique people must be reached + in order for data to be reported. If the minimum number is + not met, the total_reach value will be rounded to 0. + on_target_impressions (int): + Number of ad impressions that exactly matches + the Targeting. + total_impressions (int): + Total number of ad impressions. This includes + impressions that may fall outside the specified + Targeting, due to insufficient information on + signed-in users. + viewable_impressions (int): + Number of times the ad's impressions were + considered viewable. See + https://support.google.com/google-ads/answer/7029393 + for more information about what makes an ad + viewable and how viewability is measured. + + This field is a member of `oneof`_ ``_viewable_impressions``. + on_target_coview_reach (int): + Number of unique people reached that exactly + matches the Targeting including co-viewers. + + This field is a member of `oneof`_ ``_on_target_coview_reach``. + total_coview_reach (int): + Number of unique people reached including + co-viewers. This includes people that may fall + outside the specified Targeting. + + This field is a member of `oneof`_ ``_total_coview_reach``. + on_target_coview_impressions (int): + Number of ad impressions that exactly matches + the Targeting including co-viewers. + + This field is a member of `oneof`_ ``_on_target_coview_impressions``. + total_coview_impressions (int): + Total number of ad impressions including + co-viewers. This includes impressions that may + fall outside the specified Targeting, due to + insufficient information on signed-in users. + + This field is a member of `oneof`_ ``_total_coview_impressions``. + average_frequency (float): + The number of times per selected time unit a + user will see an ad, averaged over the number of + time units in the forecast length. This field + will only be populated for a Target Frequency + campaign. + + See + https://support.google.com/google-ads/answer/12400225 + for more information about Target Frequency + campaigns. + + This field is a member of `oneof`_ ``_average_frequency``. + conversions (float): + The number of conversions. This metric is only available for + DEMAND_GEN plannable products. + + See https://support.google.com/google-ads/answer/2375431 for + more information on conversions. + + This field is a member of `oneof`_ ``_conversions``. + trueview_views (int): + Number of ad views forecasted for the + specified product and targeting. A TrueView View + is counted when a viewer views a larger portion + or the entirety of an ad beyond an impression. + + See + https://support.google.com/google-ads/answer/2375431 + for more information on TrueView Views. + + This field is a member of `oneof`_ ``_trueview_views``. + clicks (int): + The number of clicks, which is the main user + action associated with an ad format of bid type + CPC (Cost-Per-Click). + + See + https://support.google.com/google-ads/answer/31799 + for more information on clicks. + + This field is a member of `oneof`_ ``_clicks``. + """ + + on_target_reach: int = proto.Field( + proto.INT64, + number=1, + ) + total_reach: int = proto.Field( + proto.INT64, + number=2, + ) + on_target_impressions: int = proto.Field( + proto.INT64, + number=3, + ) + total_impressions: int = proto.Field( + proto.INT64, + number=4, + ) + viewable_impressions: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + on_target_coview_reach: int = proto.Field( + proto.INT64, + number=6, + optional=True, + ) + total_coview_reach: int = proto.Field( + proto.INT64, + number=7, + optional=True, + ) + on_target_coview_impressions: int = proto.Field( + proto.INT64, + number=8, + optional=True, + ) + total_coview_impressions: int = proto.Field( + proto.INT64, + number=9, + optional=True, + ) + average_frequency: float = proto.Field( + proto.DOUBLE, + number=10, + optional=True, + ) + conversions: float = proto.Field( + proto.DOUBLE, + number=12, + optional=True, + ) + trueview_views: int = proto.Field( + proto.INT64, + number=13, + optional=True, + ) + clicks: int = proto.Field( + proto.INT64, + number=14, + optional=True, + ) + + +class OnTargetAudienceMetrics(proto.Message): + r"""Audience metrics for the planned products. These metrics consider + the following targeting dimensions: + + - Location + - PlannableAgeRange + - Gender + - AudienceTargeting (only for youtube_audience_size) + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + youtube_audience_size (int): + Reference audience size matching the + considered targeting for YouTube. + + This field is a member of `oneof`_ ``_youtube_audience_size``. + census_audience_size (int): + Reference audience size matching the + considered targeting for Census. + + This field is a member of `oneof`_ ``_census_audience_size``. + """ + + youtube_audience_size: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + census_audience_size: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + + +class EffectiveFrequencyBreakdown(proto.Message): + r"""A breakdown of the number of unique people reached at a given + effective frequency. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + effective_frequency (int): + The effective frequency [1-10]. + on_target_reach (int): + The number of unique people reached at least + effective_frequency times that exactly matches the + Targeting. + + Note that a minimum number of unique people must be reached + in order for data to be reported. If the minimum number is + not met, the on_target_reach value will be rounded to 0. + total_reach (int): + Total number of unique people reached at least + effective_frequency times. This includes people that may + fall outside the specified Targeting. + + Note that a minimum number of unique people must be reached + in order for data to be reported. If the minimum number is + not met, the total_reach value will be rounded to 0. + effective_coview_reach (int): + The number of users (including co-viewing users) reached for + the associated effective_frequency value. + + This field is a member of `oneof`_ ``_effective_coview_reach``. + on_target_effective_coview_reach (int): + The number of users (including co-viewing users) reached for + the associated effective_frequency value within the + specified plan demographic. + + This field is a member of `oneof`_ ``_on_target_effective_coview_reach``. + """ + + effective_frequency: int = proto.Field( + proto.INT32, + number=1, + ) + on_target_reach: int = proto.Field( + proto.INT64, + number=2, + ) + total_reach: int = proto.Field( + proto.INT64, + number=3, + ) + effective_coview_reach: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + on_target_effective_coview_reach: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + + +class ForecastMetricOptions(proto.Message): + r"""Controls forecast metrics to return. + + Attributes: + include_coview (bool): + Indicates whether to include co-view metrics + in the response forecast. + """ + + include_coview: bool = proto.Field( + proto.BOOL, + number=1, + ) + + +class AudienceTargeting(proto.Message): + r"""Audience targeting for reach forecast. + + Attributes: + user_interest (MutableSequence[google.ads.googleads.v24.common.types.UserInterestInfo]): + List of audiences based on user interests to + be targeted. + user_lists (MutableSequence[google.ads.googleads.v24.common.types.UserListInfo]): + List of audiences based on user lists to be + targeted. + """ + + user_interest: MutableSequence[criteria.UserInterestInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=criteria.UserInterestInfo, + ) + ) + user_lists: MutableSequence[criteria.UserListInfo] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=criteria.UserListInfo, + ) + + +class AdvancedProductTargeting(proto.Message): + r"""Advanced targeting settings for products. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + surface_targeting_settings (google.ads.googleads.v24.services.types.SurfaceTargeting): + Surface targeting settings for this product. + target_frequency_settings (google.ads.googleads.v24.services.types.TargetFrequencySettings): + Settings for a Target frequency campaign. Must be set when + selecting the TARGET_FREQUENCY product. + + See https://support.google.com/google-ads/answer/12400225 + for more information about Target Frequency campaigns. + youtube_select_settings (google.ads.googleads.v24.services.types.YouTubeSelectSettings): + Settings for YouTube Select targeting. + + This field is a member of `oneof`_ ``advanced_targeting``. + """ + + surface_targeting_settings: "SurfaceTargeting" = proto.Field( + proto.MESSAGE, + number=2, + message="SurfaceTargeting", + ) + target_frequency_settings: "TargetFrequencySettings" = proto.Field( + proto.MESSAGE, + number=3, + message="TargetFrequencySettings", + ) + youtube_select_settings: "YouTubeSelectSettings" = proto.Field( + proto.MESSAGE, + number=1, + oneof="advanced_targeting", + message="YouTubeSelectSettings", + ) + + +class YouTubeSelectSettings(proto.Message): + r"""Request settings for YouTube Select Lineups + + Attributes: + lineup_id (int): + Lineup for YouTube Select Targeting. + """ + + lineup_id: int = proto.Field( + proto.INT64, + number=1, + ) + + +class YouTubeSelectLineUp(proto.Message): + r"""A Plannable YouTube Select Lineup for product targeting. + + Attributes: + lineup_id (int): + The ID of the YouTube Select Lineup. + lineup_name (str): + The unique name of the YouTube Select Lineup. + """ + + lineup_id: int = proto.Field( + proto.INT64, + number=1, + ) + lineup_name: str = proto.Field( + proto.STRING, + number=2, + ) + + +class YouTubeSelectLineUpTargeting(proto.Message): + r"""Targetable YouTube Select Lineups for the ad product and the + default Lineup. + + Attributes: + youtube_select_lineups (MutableSequence[google.ads.googleads.v24.services.types.YouTubeSelectLineUp]): + Targetable YouTube Select Lineups for the ad + product. + default_youtube_select_lineup (google.ads.googleads.v24.services.types.YouTubeSelectLineUp): + The default YouTube Select Lineup for the ad + product if available. + """ + + youtube_select_lineups: MutableSequence["YouTubeSelectLineUp"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="YouTubeSelectLineUp", + ) + ) + default_youtube_select_lineup: "YouTubeSelectLineUp" = proto.Field( + proto.MESSAGE, + number=2, + message="YouTubeSelectLineUp", + ) + + +class SurfaceTargetingCombinations(proto.Message): + r"""The surface targeting combinations available for an ad + product. + + Attributes: + default_targeting (google.ads.googleads.v24.services.types.SurfaceTargeting): + Default surface targeting applied to the ad + product. + available_targeting_combinations (MutableSequence[google.ads.googleads.v24.services.types.SurfaceTargeting]): + Available surface target combinations for the + ad product. + """ + + default_targeting: "SurfaceTargeting" = proto.Field( + proto.MESSAGE, + number=1, + message="SurfaceTargeting", + ) + available_targeting_combinations: MutableSequence["SurfaceTargeting"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="SurfaceTargeting", + ) + ) + + +class SurfaceTargeting(proto.Message): + r"""Container for surfaces for a product. Surfaces refer to the + available types of ad inventories such as In-Feed, In-Stream, + and Shorts. + + Attributes: + surfaces (MutableSequence[google.ads.googleads.v24.enums.types.ReachPlanSurfaceEnum.ReachPlanSurface]): + List of surfaces available to target. + """ + + surfaces: MutableSequence[ + reach_plan_surface.ReachPlanSurfaceEnum.ReachPlanSurface + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum=reach_plan_surface.ReachPlanSurfaceEnum.ReachPlanSurface, + ) + + +class TargetFrequencySettings(proto.Message): + r"""Target Frequency settings for a supported product. + + Attributes: + time_unit (google.ads.googleads.v24.enums.types.TargetFrequencyTimeUnitEnum.TargetFrequencyTimeUnit): + Required. The time unit used to describe the time frame for + target_frequency. + target_frequency (int): + Required. The target frequency goal per + selected time unit. + """ + + time_unit: ( + target_frequency_time_unit.TargetFrequencyTimeUnitEnum.TargetFrequencyTimeUnit + ) = proto.Field( + proto.ENUM, + number=1, + enum=target_frequency_time_unit.TargetFrequencyTimeUnitEnum.TargetFrequencyTimeUnit, + ) + target_frequency: int = proto.Field( + proto.INT32, + number=2, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/recommendation_service.py b/google/ads/googleads/v24/services/types/recommendation_service.py new file mode 100644 index 000000000..2223ca577 --- /dev/null +++ b/google/ads/googleads/v24/services/types/recommendation_service.py @@ -0,0 +1,1573 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.common.types import extensions +from google.ads.googleads.v24.enums.types import ( + ad_group_type as gage_ad_group_type, +) +from google.ads.googleads.v24.enums.types import ( + advertising_channel_type as gage_advertising_channel_type, +) +from google.ads.googleads.v24.enums.types import ( + bidding_strategy_type as gage_bidding_strategy_type, +) +from google.ads.googleads.v24.enums.types import conversion_tracking_status_enum +from google.ads.googleads.v24.enums.types import keyword_match_type +from google.ads.googleads.v24.enums.types import recommendation_type +from google.ads.googleads.v24.enums.types import ( + target_impression_share_location, +) +from google.ads.googleads.v24.resources.types import ad as gagr_ad +from google.ads.googleads.v24.resources.types import asset +from google.ads.googleads.v24.resources.types import recommendation +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "ApplyRecommendationRequest", + "ApplyRecommendationOperation", + "ApplyRecommendationResponse", + "ApplyRecommendationResult", + "DismissRecommendationRequest", + "DismissRecommendationResponse", + "GenerateRecommendationsRequest", + "GenerateRecommendationsResponse", + }, +) + + +class ApplyRecommendationRequest(proto.Message): + r"""Request message for + [RecommendationService.ApplyRecommendation][google.ads.googleads.v24.services.RecommendationService.ApplyRecommendation]. + + Attributes: + customer_id (str): + Required. The ID of the customer with the + recommendation. + operations (MutableSequence[google.ads.googleads.v24.services.types.ApplyRecommendationOperation]): + Required. The list of operations to apply recommendations. + If partial_failure=false all recommendations should be of + the same type There is a limit of 100 operations per + request. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, operations will be carried out + as a transaction if and only if they are all + valid. Default is false. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["ApplyRecommendationOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ApplyRecommendationOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class ApplyRecommendationOperation(proto.Message): + r"""Information about the operation to apply a recommendation and + any parameters to customize it. + + 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: + resource_name (str): + The resource name of the recommendation to + apply. + campaign_budget (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.CampaignBudgetParameters): + Optional parameters to use when applying a + campaign budget recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + text_ad (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.TextAdParameters): + Optional parameters to use when applying a + text ad recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + keyword (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.KeywordParameters): + Optional parameters to use when applying + keyword recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + target_cpa_opt_in (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.TargetCpaOptInParameters): + Optional parameters to use when applying + target CPA opt-in recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + target_roas_opt_in (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.TargetRoasOptInParameters): + Optional parameters to use when applying + target ROAS opt-in recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + callout_extension (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.CalloutExtensionParameters): + Parameters to use when applying callout + extension recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + call_extension (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.CallExtensionParameters): + Parameters to use when applying call + extension recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + sitelink_extension (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.SitelinkExtensionParameters): + Parameters to use when applying sitelink + recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + move_unused_budget (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.MoveUnusedBudgetParameters): + Parameters to use when applying move unused + budget recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + responsive_search_ad (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.ResponsiveSearchAdParameters): + Parameters to use when applying a responsive + search ad recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + use_broad_match_keyword (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.UseBroadMatchKeywordParameters): + Parameters to use when applying a use broad + match keyword recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + responsive_search_ad_asset (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.ResponsiveSearchAdAssetParameters): + Parameters to use when applying a responsive + search ad asset recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + responsive_search_ad_improve_ad_strength (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.ResponsiveSearchAdImproveAdStrengthParameters): + Parameters to use when applying a responsive + search ad improve ad strength recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + raise_target_cpa_bid_too_low (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.RaiseTargetCpaBidTooLowParameters): + Parameters to use when applying a raise + target CPA bid too low recommendation. The apply + is asynchronous and can take minutes depending + on the number of ad groups there is in the + related campaign. + + This field is a member of `oneof`_ ``apply_parameters``. + forecasting_set_target_roas (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.ForecastingSetTargetRoasParameters): + Parameters to use when applying a forecasting + set target ROAS recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + callout_asset (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.CalloutAssetParameters): + Parameters to use when applying callout asset + recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + call_asset (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.CallAssetParameters): + Parameters to use when applying call asset + recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + sitelink_asset (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.SitelinkAssetParameters): + Parameters to use when applying sitelink + asset recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + raise_target_cpa (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.RaiseTargetCpaParameters): + Parameters to use when applying raise Target + CPA recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + lower_target_roas (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.LowerTargetRoasParameters): + Parameters to use when applying lower Target + ROAS recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + forecasting_set_target_cpa (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.ForecastingSetTargetCpaParameters): + Parameters to use when applying forecasting + set target CPA recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + set_target_cpa (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.ForecastingSetTargetCpaParameters): + Parameters to use when applying set target + CPA recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + set_target_roas (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.ForecastingSetTargetRoasParameters): + Parameters to use when applying set target + ROAS recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + lead_form_asset (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.LeadFormAssetParameters): + Parameters to use when applying lead form + asset recommendation. + + This field is a member of `oneof`_ ``apply_parameters``. + """ + + class CampaignBudgetParameters(proto.Message): + r"""Parameters to use when applying a campaign budget + recommendation. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + new_budget_amount_micros (int): + New budget amount to set for target budget + resource. This is a required field. + + This field is a member of `oneof`_ ``_new_budget_amount_micros``. + """ + + new_budget_amount_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + class ForecastingSetTargetRoasParameters(proto.Message): + r"""Parameters to use when applying a forecasting set target roas + recommendation. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_roas (float): + New target ROAS (revenue per unit of spend) + to set for a campaign resource. + The value is between 0.01 and 1000.0, inclusive. + + This field is a member of `oneof`_ ``_target_roas``. + campaign_budget_amount_micros (int): + New campaign budget amount to set for a + campaign resource. + + This field is a member of `oneof`_ ``_campaign_budget_amount_micros``. + """ + + target_roas: float = proto.Field( + proto.DOUBLE, + number=1, + optional=True, + ) + campaign_budget_amount_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + class TextAdParameters(proto.Message): + r"""Parameters to use when applying a text ad recommendation. + + Attributes: + ad (google.ads.googleads.v24.resources.types.Ad): + New ad to add to recommended ad group. All + necessary fields need to be set in this message. + This is a required field. + """ + + ad: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=1, + message=gagr_ad.Ad, + ) + + class KeywordParameters(proto.Message): + r"""Parameters to use when applying keyword recommendation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + ad_group (str): + The ad group resource to add keyword to. This + is a required field. + + This field is a member of `oneof`_ ``_ad_group``. + match_type (google.ads.googleads.v24.enums.types.KeywordMatchTypeEnum.KeywordMatchType): + The match type of the keyword. This is a + required field. + cpc_bid_micros (int): + Optional, CPC bid to set for the keyword. If + not set, keyword will use bid based on bidding + strategy used by target ad group. + + This field is a member of `oneof`_ ``_cpc_bid_micros``. + """ + + ad_group: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + match_type: keyword_match_type.KeywordMatchTypeEnum.KeywordMatchType = ( + proto.Field( + proto.ENUM, + number=2, + enum=keyword_match_type.KeywordMatchTypeEnum.KeywordMatchType, + ) + ) + cpc_bid_micros: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + + class TargetCpaOptInParameters(proto.Message): + r"""Parameters to use when applying Target CPA recommendation. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_cpa_micros (int): + Average CPA to use for Target CPA bidding + strategy. This is a required field. + + This field is a member of `oneof`_ ``_target_cpa_micros``. + new_campaign_budget_amount_micros (int): + Optional, budget amount to set for the + campaign. + + This field is a member of `oneof`_ ``_new_campaign_budget_amount_micros``. + """ + + target_cpa_micros: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + new_campaign_budget_amount_micros: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + + class TargetRoasOptInParameters(proto.Message): + r"""Parameters to use when applying a Target ROAS opt-in + recommendation. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_roas (float): + Average ROAS (revenue per unit of spend) to use for Target + ROAS bidding strategy. The value is between 0.01 and 1000.0, + inclusive. This is a required field, unless + new_campaign_budget_amount_micros is set. + + This field is a member of `oneof`_ ``_target_roas``. + new_campaign_budget_amount_micros (int): + Optional, budget amount to set for the + campaign. + + This field is a member of `oneof`_ ``_new_campaign_budget_amount_micros``. + """ + + target_roas: float = proto.Field( + proto.DOUBLE, + number=1, + optional=True, + ) + new_campaign_budget_amount_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + class CalloutExtensionParameters(proto.Message): + r"""Parameters to use when applying callout extension + recommendation. + + Attributes: + callout_extensions (MutableSequence[google.ads.googleads.v24.common.types.CalloutFeedItem]): + Callout extensions to be added. This is a + required field. + """ + + callout_extensions: MutableSequence[extensions.CalloutFeedItem] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=extensions.CalloutFeedItem, + ) + ) + + class CallExtensionParameters(proto.Message): + r"""Parameters to use when applying call extension + recommendation. + + Attributes: + call_extensions (MutableSequence[google.ads.googleads.v24.common.types.CallFeedItem]): + Call extensions to be added. This is a + required field. + """ + + call_extensions: MutableSequence[extensions.CallFeedItem] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=extensions.CallFeedItem, + ) + ) + + class SitelinkExtensionParameters(proto.Message): + r"""Parameters to use when applying sitelink recommendation. + + Attributes: + sitelink_extensions (MutableSequence[google.ads.googleads.v24.common.types.SitelinkFeedItem]): + Sitelinks to be added. This is a required + field. + """ + + sitelink_extensions: MutableSequence[extensions.SitelinkFeedItem] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=extensions.SitelinkFeedItem, + ) + ) + + class CalloutAssetParameters(proto.Message): + r"""Parameters to use when applying callout asset + recommendations. + + Attributes: + ad_asset_apply_parameters (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.AdAssetApplyParameters): + Required. Callout assets to be added. This is + a required field. + """ + + ad_asset_apply_parameters: ( + "ApplyRecommendationOperation.AdAssetApplyParameters" + ) = proto.Field( + proto.MESSAGE, + number=1, + message="ApplyRecommendationOperation.AdAssetApplyParameters", + ) + + class CallAssetParameters(proto.Message): + r"""Parameters to use when applying call asset recommendations. + + Attributes: + ad_asset_apply_parameters (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.AdAssetApplyParameters): + Required. Call assets to be added. This is a + required field. + """ + + ad_asset_apply_parameters: ( + "ApplyRecommendationOperation.AdAssetApplyParameters" + ) = proto.Field( + proto.MESSAGE, + number=1, + message="ApplyRecommendationOperation.AdAssetApplyParameters", + ) + + class SitelinkAssetParameters(proto.Message): + r"""Parameters to use when applying sitelink asset + recommendations. + + Attributes: + ad_asset_apply_parameters (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.AdAssetApplyParameters): + Required. Sitelink assets to be added. This + is a required field. + """ + + ad_asset_apply_parameters: ( + "ApplyRecommendationOperation.AdAssetApplyParameters" + ) = proto.Field( + proto.MESSAGE, + number=1, + message="ApplyRecommendationOperation.AdAssetApplyParameters", + ) + + class RaiseTargetCpaParameters(proto.Message): + r"""Parameters to use when applying raise Target CPA + recommendations. + + Attributes: + target_cpa_multiplier (float): + Required. Target to set CPA multiplier to. + This is a required field. + """ + + target_cpa_multiplier: float = proto.Field( + proto.DOUBLE, + number=1, + ) + + class LowerTargetRoasParameters(proto.Message): + r"""Parameters to use when applying lower Target ROAS + recommendations. + + Attributes: + target_roas_multiplier (float): + Required. Target to set ROAS multiplier to. + This is a required field. + """ + + target_roas_multiplier: float = proto.Field( + proto.DOUBLE, + number=1, + ) + + class AdAssetApplyParameters(proto.Message): + r"""Common parameters used when applying ad asset + recommendations. + + Attributes: + new_assets (MutableSequence[google.ads.googleads.v24.resources.types.Asset]): + The assets to create and attach to a scope. This may be + combined with existing_assets in the same call. + existing_assets (MutableSequence[str]): + The resource names of existing assets to attach to a scope. + This may be combined with new_assets in the same call. + scope (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.AdAssetApplyParameters.ApplyScope): + Required. The scope at which to apply the + assets. Assets at the campaign scope level will + be applied to the campaign associated with the + recommendation. Assets at the customer scope + will apply to the entire account. Assets at the + campaign scope will override any attached at the + customer scope. + """ + + class ApplyScope(proto.Enum): + r"""Scope to apply the assets to. + + Values: + UNSPECIFIED (0): + The apply scope has not been specified. + UNKNOWN (1): + Unknown. + CUSTOMER (2): + Apply at the customer scope. + CAMPAIGN (3): + Apply at the campaign scope. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER = 2 + CAMPAIGN = 3 + + new_assets: MutableSequence[asset.Asset] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=asset.Asset, + ) + existing_assets: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + scope: ( + "ApplyRecommendationOperation.AdAssetApplyParameters.ApplyScope" + ) = proto.Field( + proto.ENUM, + number=3, + enum="ApplyRecommendationOperation.AdAssetApplyParameters.ApplyScope", + ) + + class MoveUnusedBudgetParameters(proto.Message): + r"""Parameters to use when applying move unused budget + recommendation. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + budget_micros_to_move (int): + Budget amount to move from excess budget to + constrained budget. This is a required field. + + This field is a member of `oneof`_ ``_budget_micros_to_move``. + """ + + budget_micros_to_move: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + class ResponsiveSearchAdAssetParameters(proto.Message): + r"""Parameters to use when applying a responsive search ad asset + recommendation. + + Attributes: + updated_ad (google.ads.googleads.v24.resources.types.Ad): + Updated ad. The current ad's content will be + replaced. + """ + + updated_ad: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=1, + message=gagr_ad.Ad, + ) + + class ResponsiveSearchAdImproveAdStrengthParameters(proto.Message): + r"""Parameters to use when applying a responsive search ad + improve ad strength recommendation. + + Attributes: + updated_ad (google.ads.googleads.v24.resources.types.Ad): + Updated ad. The current ad's content will be + replaced. + """ + + updated_ad: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=1, + message=gagr_ad.Ad, + ) + + class ResponsiveSearchAdParameters(proto.Message): + r"""Parameters to use when applying a responsive search ad + recommendation. + + Attributes: + ad (google.ads.googleads.v24.resources.types.Ad): + Required. New ad to add to recommended ad + group. + """ + + ad: gagr_ad.Ad = proto.Field( + proto.MESSAGE, + number=1, + message=gagr_ad.Ad, + ) + + class RaiseTargetCpaBidTooLowParameters(proto.Message): + r"""Parameters to use when applying a raise target CPA bid too + low recommendation. The apply is asynchronous and can take + minutes depending on the number of ad groups there is in the + related campaign.. + + Attributes: + target_multiplier (float): + Required. A number greater than 1.0 + indicating the factor by which to increase the + target CPA. This is a required field. + """ + + target_multiplier: float = proto.Field( + proto.DOUBLE, + number=1, + ) + + class UseBroadMatchKeywordParameters(proto.Message): + r"""Parameters to use when applying a use broad match keyword + recommendation. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + new_budget_amount_micros (int): + New budget amount to set for target budget + resource. + + This field is a member of `oneof`_ ``_new_budget_amount_micros``. + """ + + new_budget_amount_micros: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + + class ForecastingSetTargetCpaParameters(proto.Message): + r"""Parameters to use when applying a set target CPA + recommendation. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + target_cpa_micros (int): + Average CPA to use for Target CPA bidding + strategy. + + This field is a member of `oneof`_ ``_target_cpa_micros``. + campaign_budget_amount_micros (int): + New campaign budget amount to set for a + campaign resource. + + This field is a member of `oneof`_ ``_campaign_budget_amount_micros``. + """ + + target_cpa_micros: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + campaign_budget_amount_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + class LeadFormAssetParameters(proto.Message): + r"""Parameters to use when applying a lead form asset + recommendation. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + ad_asset_apply_parameters (google.ads.googleads.v24.services.types.ApplyRecommendationOperation.AdAssetApplyParameters): + Required. Lead form assets to be added. This + is a required field. + set_submit_lead_form_asset_campaign_goal (bool): + If true, the "Submit Lead Form" goal will be + set on the target campaign. As a result, ads + will be shown as lead form creative ads. If + false, the "Submit Lead Form" goal will not be + set on the campaign and ads will contain lead + form assets. + + This field is a member of `oneof`_ ``_set_submit_lead_form_asset_campaign_goal``. + """ + + ad_asset_apply_parameters: ( + "ApplyRecommendationOperation.AdAssetApplyParameters" + ) = proto.Field( + proto.MESSAGE, + number=1, + message="ApplyRecommendationOperation.AdAssetApplyParameters", + ) + set_submit_lead_form_asset_campaign_goal: bool = proto.Field( + proto.BOOL, + number=2, + optional=True, + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + campaign_budget: CampaignBudgetParameters = proto.Field( + proto.MESSAGE, + number=2, + oneof="apply_parameters", + message=CampaignBudgetParameters, + ) + text_ad: TextAdParameters = proto.Field( + proto.MESSAGE, + number=3, + oneof="apply_parameters", + message=TextAdParameters, + ) + keyword: KeywordParameters = proto.Field( + proto.MESSAGE, + number=4, + oneof="apply_parameters", + message=KeywordParameters, + ) + target_cpa_opt_in: TargetCpaOptInParameters = proto.Field( + proto.MESSAGE, + number=5, + oneof="apply_parameters", + message=TargetCpaOptInParameters, + ) + target_roas_opt_in: TargetRoasOptInParameters = proto.Field( + proto.MESSAGE, + number=10, + oneof="apply_parameters", + message=TargetRoasOptInParameters, + ) + callout_extension: CalloutExtensionParameters = proto.Field( + proto.MESSAGE, + number=6, + oneof="apply_parameters", + message=CalloutExtensionParameters, + ) + call_extension: CallExtensionParameters = proto.Field( + proto.MESSAGE, + number=7, + oneof="apply_parameters", + message=CallExtensionParameters, + ) + sitelink_extension: SitelinkExtensionParameters = proto.Field( + proto.MESSAGE, + number=8, + oneof="apply_parameters", + message=SitelinkExtensionParameters, + ) + move_unused_budget: MoveUnusedBudgetParameters = proto.Field( + proto.MESSAGE, + number=9, + oneof="apply_parameters", + message=MoveUnusedBudgetParameters, + ) + responsive_search_ad: ResponsiveSearchAdParameters = proto.Field( + proto.MESSAGE, + number=11, + oneof="apply_parameters", + message=ResponsiveSearchAdParameters, + ) + use_broad_match_keyword: UseBroadMatchKeywordParameters = proto.Field( + proto.MESSAGE, + number=12, + oneof="apply_parameters", + message=UseBroadMatchKeywordParameters, + ) + responsive_search_ad_asset: ResponsiveSearchAdAssetParameters = proto.Field( + proto.MESSAGE, + number=13, + oneof="apply_parameters", + message=ResponsiveSearchAdAssetParameters, + ) + responsive_search_ad_improve_ad_strength: ( + ResponsiveSearchAdImproveAdStrengthParameters + ) = proto.Field( + proto.MESSAGE, + number=14, + oneof="apply_parameters", + message=ResponsiveSearchAdImproveAdStrengthParameters, + ) + raise_target_cpa_bid_too_low: RaiseTargetCpaBidTooLowParameters = ( + proto.Field( + proto.MESSAGE, + number=15, + oneof="apply_parameters", + message=RaiseTargetCpaBidTooLowParameters, + ) + ) + forecasting_set_target_roas: ForecastingSetTargetRoasParameters = ( + proto.Field( + proto.MESSAGE, + number=16, + oneof="apply_parameters", + message=ForecastingSetTargetRoasParameters, + ) + ) + callout_asset: CalloutAssetParameters = proto.Field( + proto.MESSAGE, + number=17, + oneof="apply_parameters", + message=CalloutAssetParameters, + ) + call_asset: CallAssetParameters = proto.Field( + proto.MESSAGE, + number=18, + oneof="apply_parameters", + message=CallAssetParameters, + ) + sitelink_asset: SitelinkAssetParameters = proto.Field( + proto.MESSAGE, + number=19, + oneof="apply_parameters", + message=SitelinkAssetParameters, + ) + raise_target_cpa: RaiseTargetCpaParameters = proto.Field( + proto.MESSAGE, + number=20, + oneof="apply_parameters", + message=RaiseTargetCpaParameters, + ) + lower_target_roas: LowerTargetRoasParameters = proto.Field( + proto.MESSAGE, + number=21, + oneof="apply_parameters", + message=LowerTargetRoasParameters, + ) + forecasting_set_target_cpa: ForecastingSetTargetCpaParameters = proto.Field( + proto.MESSAGE, + number=22, + oneof="apply_parameters", + message=ForecastingSetTargetCpaParameters, + ) + set_target_cpa: ForecastingSetTargetCpaParameters = proto.Field( + proto.MESSAGE, + number=23, + oneof="apply_parameters", + message=ForecastingSetTargetCpaParameters, + ) + set_target_roas: ForecastingSetTargetRoasParameters = proto.Field( + proto.MESSAGE, + number=24, + oneof="apply_parameters", + message=ForecastingSetTargetRoasParameters, + ) + lead_form_asset: LeadFormAssetParameters = proto.Field( + proto.MESSAGE, + number=25, + oneof="apply_parameters", + message=LeadFormAssetParameters, + ) + + +class ApplyRecommendationResponse(proto.Message): + r"""Response message for + [RecommendationService.ApplyRecommendation][google.ads.googleads.v24.services.RecommendationService.ApplyRecommendation]. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.ApplyRecommendationResult]): + Results of operations to apply + recommendations. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors) we return + the RPC level error. + """ + + results: MutableSequence["ApplyRecommendationResult"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ApplyRecommendationResult", + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class ApplyRecommendationResult(proto.Message): + r"""The result of applying a recommendation. + + Attributes: + resource_name (str): + Returned for successful applies. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class DismissRecommendationRequest(proto.Message): + r"""Request message for + [RecommendationService.DismissRecommendation][google.ads.googleads.v24.services.RecommendationService.DismissRecommendation]. + + Attributes: + customer_id (str): + Required. The ID of the customer with the + recommendation. + operations (MutableSequence[google.ads.googleads.v24.services.types.DismissRecommendationRequest.DismissRecommendationOperation]): + Required. The list of operations to dismiss recommendations. + If partial_failure=false all recommendations should be of + the same type There is a limit of 100 operations per + request. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, operations will be carried in + a single transaction if and only if they are all + valid. Default is false. + """ + + class DismissRecommendationOperation(proto.Message): + r"""Operation to dismiss a single recommendation identified by + resource_name. + + Attributes: + resource_name (str): + The resource name of the recommendation to + dismiss. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence[DismissRecommendationOperation] = ( + proto.RepeatedField( + proto.MESSAGE, + number=3, + message=DismissRecommendationOperation, + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=2, + ) + + +class DismissRecommendationResponse(proto.Message): + r"""Response message for + [RecommendationService.DismissRecommendation][google.ads.googleads.v24.services.RecommendationService.DismissRecommendation]. + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.DismissRecommendationResponse.DismissRecommendationResult]): + Results of operations to dismiss + recommendations. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors) we return + the RPC level error. + """ + + class DismissRecommendationResult(proto.Message): + r"""The result of dismissing a recommendation. + + Attributes: + resource_name (str): + Returned for successful dismissals. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + results: MutableSequence[DismissRecommendationResult] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=DismissRecommendationResult, + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class GenerateRecommendationsRequest(proto.Message): + r"""Request message for + [RecommendationService.GenerateRecommendations][google.ads.googleads.v24.services.RecommendationService.GenerateRecommendations]. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer_id (str): + Required. The ID of the customer generating + recommendations. + recommendation_types (MutableSequence[google.ads.googleads.v24.enums.types.RecommendationTypeEnum.RecommendationType]): + Required. List of eligible recommendation_types to generate. + If the uploaded criteria isn't sufficient to make a + recommendation, or the campaign is already in the + recommended state, no recommendation will be returned for + that type. Generally, a recommendation is returned if all + required fields for that recommendation_type are uploaded, + but there are cases where this is still not sufficient. + + The following recommendation_types are supported for + recommendation generation: CAMPAIGN_BUDGET, KEYWORD, + MAXIMIZE_CLICKS_OPT_IN, MAXIMIZE_CONVERSIONS_OPT_IN, + MAXIMIZE_CONVERSION_VALUE_OPT_IN, SET_TARGET_CPA, + SET_TARGET_ROAS, SITELINK_ASSET, TARGET_CPA_OPT_IN, + TARGET_ROAS_OPT_IN + advertising_channel_type (google.ads.googleads.v24.enums.types.AdvertisingChannelTypeEnum.AdvertisingChannelType): + Required. Advertising channel type of the campaign. The + following advertising_channel_types are supported for + recommendation generation: PERFORMANCE_MAX and SEARCH + campaign_sitelink_count (int): + Optional. Number of sitelinks on the campaign. This field is + necessary for the following recommendation_types: + SITELINK_ASSET + + This field is a member of `oneof`_ ``_campaign_sitelink_count``. + conversion_tracking_status (google.ads.googleads.v24.enums.types.ConversionTrackingStatusEnum.ConversionTrackingStatus): + Optional. Current conversion tracking status. This field is + necessary for the following recommendation_types: + MAXIMIZE_CLICKS_OPT_IN, MAXIMIZE_CONVERSIONS_OPT_IN, + MAXIMIZE_CONVERSION_VALUE_OPT_IN, SET_TARGET_CPA, + SET_TARGET_ROAS, TARGET_CPA_OPT_IN, TARGET_ROAS_OPT_IN + + This field is a member of `oneof`_ ``_conversion_tracking_status``. + bidding_info (google.ads.googleads.v24.services.types.GenerateRecommendationsRequest.BiddingInfo): + Optional. Current bidding information of the campaign. This + field is necessary for the following recommendation_types: + CAMPAIGN_BUDGET, MAXIMIZE_CLICKS_OPT_IN, + MAXIMIZE_CONVERSIONS_OPT_IN, + MAXIMIZE_CONVERSION_VALUE_OPT_IN, SET_TARGET_CPA, + SET_TARGET_ROAS, TARGET_CPA_OPT_IN, TARGET_ROAS_OPT_IN + + This field is a member of `oneof`_ ``_bidding_info``. + ad_group_info (MutableSequence[google.ads.googleads.v24.services.types.GenerateRecommendationsRequest.AdGroupInfo]): + Optional. Current AdGroup Information. Supports information + from a single AdGroup. This field is optional for the + following recommendation_types: KEYWORD This field is + required for the following recommendation_types: + CAMPAIGN_BUDGET if AdvertisingChannelType is SEARCH + seed_info (google.ads.googleads.v24.services.types.GenerateRecommendationsRequest.SeedInfo): + Optional. Seed information for Keywords. This field is + necessary for the following recommendation_types: KEYWORD + + This field is a member of `oneof`_ ``_seed_info``. + budget_info (google.ads.googleads.v24.services.types.GenerateRecommendationsRequest.BudgetInfo): + Optional. Current budget information. This field is optional + for the following recommendation_types: CAMPAIGN_BUDGET + + This field is a member of `oneof`_ ``_budget_info``. + campaign_image_asset_count (int): + Optional. Current campaign image asset count. This field is + optional for the following recommendation_types: + CAMPAIGN_BUDGET + + This field is a member of `oneof`_ ``_campaign_image_asset_count``. + campaign_call_asset_count (int): + Optional. Current campaign call asset count. This field is + optional for the following recommendation_types: + CAMPAIGN_BUDGET + + This field is a member of `oneof`_ ``_campaign_call_asset_count``. + country_codes (MutableSequence[str]): + Optional. Current campaign country codes. This field is + required for the following recommendation_types: + CAMPAIGN_BUDGET if AdvertisingChannelType is SEARCH + language_codes (MutableSequence[str]): + Optional. Current campaign language codes. This field is + required for the following recommendation_types: + CAMPAIGN_BUDGET if AdvertisingChannelType is SEARCH + positive_locations_ids (MutableSequence[int]): + Optional. Current campaign positive location ids. One of + this field OR negative_location_ids is required for the + following recommendation_types: CAMPAIGN_BUDGET if + AdvertisingChannelType is SEARCH + negative_locations_ids (MutableSequence[int]): + Optional. Current campaign negative location ids. One of + this field OR positive_location_ids is required for the + following recommendation_types: CAMPAIGN_BUDGET if + AdvertisingChannelType is SEARCH + asset_group_info (MutableSequence[google.ads.googleads.v24.services.types.GenerateRecommendationsRequest.AssetGroupInfo]): + Optional. Current AssetGroup Information. This field is + required for the following recommendation_types: + CAMPAIGN_BUDGET + target_partner_search_network (bool): + Optional. If true, the campaign is opted into serving ads on + the Google Partner Network. This field is optional for the + following recommendation_types: CAMPAIGN_BUDGET + + This field is a member of `oneof`_ ``_target_partner_search_network``. + target_content_network (bool): + Optional. If true, the campaign is opted into serving ads on + specified placements in the Google Display Network. This + field is optional for the following recommendation_types: + CAMPAIGN_BUDGET + + This field is a member of `oneof`_ ``_target_content_network``. + merchant_center_account_id (int): + Optional. Merchant Center account ID. This field should only + be set when advertising_channel_type is PERFORMANCE_MAX. + Setting this field causes RecommendationService to generate + recommendations for Performance Max for retail instead of + standard Performance Max. This field is optional for the + following recommendation_types: CAMPAIGN_BUDGET + + This field is a member of `oneof`_ ``_merchant_center_account_id``. + is_new_customer (bool): + Optional. Whether or not this customer should be treated as + a "new" customer (that is, a customer who has not yet + created a campaign). + + Setting this to ``true`` will cause the backend to generate + recommendations using a dedicated recommendation model for + onboarding new customers, as opposed to the default model + for existing customers. This is only recommended for + customers with 0 campaigns. + + This field is optional for the following + recommendation_types: CAMPAIGN_BUDGET + + This field is a member of `oneof`_ ``_is_new_customer``. + """ + + class BiddingInfo(proto.Message): + r"""Current bidding information of the campaign. Provides a + wrapper for bidding-related signals that inform recommendations. + + 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: + bidding_strategy_type (google.ads.googleads.v24.enums.types.BiddingStrategyTypeEnum.BiddingStrategyType): + Current bidding strategy. This field is necessary for the + following recommendation_types: CAMPAIGN_BUDGET, + MAXIMIZE_CLICKS_OPT_IN, MAXIMIZE_CONVERSIONS_OPT_IN, + MAXIMIZE_CONVERSION_VALUE_OPT_IN, SET_TARGET_CPA, + SET_TARGET_ROAS, TARGET_CPA_OPT_IN, TARGET_ROAS_OPT_IN + + This field is a member of `oneof`_ ``_bidding_strategy_type``. + target_cpa_micros (int): + Current target_cpa in micros. This can be populated for + campaigns with a bidding strategy type of TARGET_CPA or + MAXIMIZE_CONVERSIONS. + + This field is a member of `oneof`_ ``bidding_strategy_target_info``. + target_roas (float): + Current target_roas. This can be populated for campaigns + with a bidding strategy type of TARGET_ROAS or + MAXIMIZE_CONVERSION_VALUE. + + This field is a member of `oneof`_ ``bidding_strategy_target_info``. + target_impression_share_info (google.ads.googleads.v24.services.types.GenerateRecommendationsRequest.TargetImpressionShareInfo): + Optional. Current Target Impression Share information of the + campaign. This field is necessary for the following + recommendation_types: CAMPAIGN_BUDGET + + This field is a member of `oneof`_ ``bidding_strategy_target_info``. + """ + + bidding_strategy_type: ( + gage_bidding_strategy_type.BiddingStrategyTypeEnum.BiddingStrategyType + ) = proto.Field( + proto.ENUM, + number=1, + optional=True, + enum=gage_bidding_strategy_type.BiddingStrategyTypeEnum.BiddingStrategyType, + ) + target_cpa_micros: int = proto.Field( + proto.INT64, + number=2, + oneof="bidding_strategy_target_info", + ) + target_roas: float = proto.Field( + proto.DOUBLE, + number=3, + oneof="bidding_strategy_target_info", + ) + target_impression_share_info: ( + "GenerateRecommendationsRequest.TargetImpressionShareInfo" + ) = proto.Field( + proto.MESSAGE, + number=4, + oneof="bidding_strategy_target_info", + message="GenerateRecommendationsRequest.TargetImpressionShareInfo", + ) + + class AdGroupInfo(proto.Message): + r"""Current AdGroup Information of the campaign. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + ad_group_type (google.ads.googleads.v24.enums.types.AdGroupTypeEnum.AdGroupType): + Optional. AdGroup Type of the AdGroup. This field is + necessary for the following recommendation_types if + ad_group_info is set: KEYWORD + + This field is a member of `oneof`_ ``_ad_group_type``. + keywords (MutableSequence[google.ads.googleads.v24.common.types.KeywordInfo]): + Optional. Current keywords. This field is optional for the + following recommendation_types if ad_group_info is set: + KEYWORD This field is required for the following + recommendation_types: CAMPAIGN_BUDGET if + AdvertisingChannelType is SEARCH + """ + + ad_group_type: gage_ad_group_type.AdGroupTypeEnum.AdGroupType = ( + proto.Field( + proto.ENUM, + number=1, + optional=True, + enum=gage_ad_group_type.AdGroupTypeEnum.AdGroupType, + ) + ) + keywords: MutableSequence[criteria.KeywordInfo] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=criteria.KeywordInfo, + ) + + class SeedInfo(proto.Message): + r"""A keyword seed and a specific url to generate keywords from. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + url_seed (str): + A specific url to generate ideas from, for + example: www.example.com/cars. + + This field is a member of `oneof`_ ``_url_seed``. + keyword_seeds (MutableSequence[str]): + Optional. Keywords or phrases to generate + ideas from, for example: cars or "car dealership + near me". + """ + + url_seed: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + keyword_seeds: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + + class BudgetInfo(proto.Message): + r"""Current budget information of the campaign. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + current_budget (int): + Required. Current budget amount in micros. This field is + necessary for the following recommendation_types if + budget_info is set: CAMPAIGN_BUDGET + + This field is a member of `oneof`_ ``_current_budget``. + """ + + current_budget: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + + class AssetGroupInfo(proto.Message): + r"""Current AssetGroup information of the campaign. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + final_url (str): + Required. Current url of the asset group. This field is + necessary for the following recommendation_types if + asset_group_info is set: CAMPAIGN_BUDGET + + This field is a member of `oneof`_ ``_final_url``. + headline (MutableSequence[str]): + Optional. Current headlines of the asset group. This field + is optional for the following recommendation_types if + asset_group_info is set: CAMPAIGN_BUDGET + description (MutableSequence[str]): + Optional. Current descriptions of the asset group. This + field is optional for the following recommendation_types if + asset_group_info is set: CAMPAIGN_BUDGET + """ + + final_url: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + headline: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + description: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + + class TargetImpressionShareInfo(proto.Message): + r"""Current Target Impression Share information of the campaign. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + location (google.ads.googleads.v24.enums.types.TargetImpressionShareLocationEnum.TargetImpressionShareLocation): + Required. The targeted location on the search results page. + This is required for campaigns where the + AdvertisingChannelType is SEARCH and the bidding strategy + type is TARGET_IMPRESSION_SHARE. + + This field is a member of `oneof`_ ``_location``. + target_impression_share_micros (int): + Required. The chosen fraction of targeted impression share + in micros. For example, 1% equals 10,000. It must be a value + between 1 and 1,000,000. This is required for campaigns with + an AdvertisingChannelType of SEARCH and a bidding strategy + type of TARGET_IMPRESSION_SHARE. + + This field is a member of `oneof`_ ``_target_impression_share_micros``. + max_cpc_bid_ceiling (int): + Optional. Ceiling of max CPC bids in micros set by automated + bidders. This is optional for campaigns with an + AdvertisingChannelType of SEARCH and a bidding strategy type + of TARGET_IMPRESSION_SHARE. + + This field is a member of `oneof`_ ``_max_cpc_bid_ceiling``. + """ + + location: ( + target_impression_share_location.TargetImpressionShareLocationEnum.TargetImpressionShareLocation + ) = proto.Field( + proto.ENUM, + number=1, + optional=True, + enum=target_impression_share_location.TargetImpressionShareLocationEnum.TargetImpressionShareLocation, + ) + target_impression_share_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + max_cpc_bid_ceiling: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + recommendation_types: MutableSequence[ + recommendation_type.RecommendationTypeEnum.RecommendationType + ] = proto.RepeatedField( + proto.ENUM, + number=2, + enum=recommendation_type.RecommendationTypeEnum.RecommendationType, + ) + advertising_channel_type: ( + gage_advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType + ) = proto.Field( + proto.ENUM, + number=3, + enum=gage_advertising_channel_type.AdvertisingChannelTypeEnum.AdvertisingChannelType, + ) + campaign_sitelink_count: int = proto.Field( + proto.INT32, + number=4, + optional=True, + ) + conversion_tracking_status: ( + conversion_tracking_status_enum.ConversionTrackingStatusEnum.ConversionTrackingStatus + ) = proto.Field( + proto.ENUM, + number=5, + optional=True, + enum=conversion_tracking_status_enum.ConversionTrackingStatusEnum.ConversionTrackingStatus, + ) + bidding_info: BiddingInfo = proto.Field( + proto.MESSAGE, + number=6, + optional=True, + message=BiddingInfo, + ) + ad_group_info: MutableSequence[AdGroupInfo] = proto.RepeatedField( + proto.MESSAGE, + number=7, + message=AdGroupInfo, + ) + seed_info: SeedInfo = proto.Field( + proto.MESSAGE, + number=8, + optional=True, + message=SeedInfo, + ) + budget_info: BudgetInfo = proto.Field( + proto.MESSAGE, + number=9, + optional=True, + message=BudgetInfo, + ) + campaign_image_asset_count: int = proto.Field( + proto.INT32, + number=10, + optional=True, + ) + campaign_call_asset_count: int = proto.Field( + proto.INT32, + number=11, + optional=True, + ) + country_codes: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=13, + ) + language_codes: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=14, + ) + positive_locations_ids: MutableSequence[int] = proto.RepeatedField( + proto.INT64, + number=15, + ) + negative_locations_ids: MutableSequence[int] = proto.RepeatedField( + proto.INT64, + number=16, + ) + asset_group_info: MutableSequence[AssetGroupInfo] = proto.RepeatedField( + proto.MESSAGE, + number=17, + message=AssetGroupInfo, + ) + target_partner_search_network: bool = proto.Field( + proto.BOOL, + number=18, + optional=True, + ) + target_content_network: bool = proto.Field( + proto.BOOL, + number=19, + optional=True, + ) + merchant_center_account_id: int = proto.Field( + proto.INT64, + number=20, + optional=True, + ) + is_new_customer: bool = proto.Field( + proto.BOOL, + number=21, + optional=True, + ) + + +class GenerateRecommendationsResponse(proto.Message): + r"""Response message for + [RecommendationService.GenerateRecommendations][google.ads.googleads.v24.services.RecommendationService.GenerateRecommendations]. + + Attributes: + recommendations (MutableSequence[google.ads.googleads.v24.resources.types.Recommendation]): + List of generated recommendations from the passed in set of + requested recommendation_types. If there isn't sufficient + data to generate a recommendation for the requested + recommendation_types, the result set won't contain a + recommendation for that type. + """ + + recommendations: MutableSequence[recommendation.Recommendation] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message=recommendation.Recommendation, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/recommendation_subscription_service.py b/google/ads/googleads/v24/services/types/recommendation_subscription_service.py new file mode 100644 index 000000000..f317177c1 --- /dev/null +++ b/google/ads/googleads/v24/services/types/recommendation_subscription_service.py @@ -0,0 +1,207 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + recommendation_subscription as gagr_recommendation_subscription, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateRecommendationSubscriptionRequest", + "RecommendationSubscriptionOperation", + "MutateRecommendationSubscriptionResponse", + "MutateRecommendationSubscriptionResult", + }, +) + + +class MutateRecommendationSubscriptionRequest(proto.Message): + r"""Request message for + [RecommendationSubscriptionService.MutateRecommendationSubscription][google.ads.googleads.v24.services.RecommendationSubscriptionService.MutateRecommendationSubscription] + + Attributes: + customer_id (str): + Required. The ID of the subscribing customer. + operations (MutableSequence[google.ads.googleads.v24.services.types.RecommendationSubscriptionOperation]): + Required. The list of create or update + operations. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + The mutable resource will only be returned if + the resource has the appropriate response field. + For example, MutateCampaignResult.campaign. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["RecommendationSubscriptionOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="RecommendationSubscriptionOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class RecommendationSubscriptionOperation(proto.Message): + r"""A single operation (create, update) on a recommendation + subscription. + [RecommendationSubscriptionService.MutateRecommendationSubscription][google.ads.googleads.v24.services.RecommendationSubscriptionService.MutateRecommendationSubscription] + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. FieldMask that determines which + resource fields are modified in an update. + create (google.ads.googleads.v24.resources.types.RecommendationSubscription): + Create operation: No resource name is + expected for the new subscription. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.RecommendationSubscription): + Update operation: The subscription is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=3, + message=field_mask_pb2.FieldMask, + ) + create: gagr_recommendation_subscription.RecommendationSubscription = ( + proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_recommendation_subscription.RecommendationSubscription, + ) + ) + update: gagr_recommendation_subscription.RecommendationSubscription = ( + proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_recommendation_subscription.RecommendationSubscription, + ) + ) + + +class MutateRecommendationSubscriptionResponse(proto.Message): + r"""Response message for + [RecommendationSubscriptionService.MutateRecommendationSubscription][google.ads.googleads.v24.services.RecommendationSubscriptionService.MutateRecommendationSubscription] + + Attributes: + results (MutableSequence[google.ads.googleads.v24.services.types.MutateRecommendationSubscriptionResult]): + Results, one per operation. + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors) we return + the RPC level error. + """ + + results: MutableSequence["MutateRecommendationSubscriptionResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateRecommendationSubscriptionResult", + ) + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateRecommendationSubscriptionResult(proto.Message): + r"""Result message for + [RecommendationSubscriptionService.MutateRecommendationSubscription][google.ads.googleads.v24.services.RecommendationSubscriptionService.MutateRecommendationSubscription] + + Attributes: + resource_name (str): + Resource name of the subscription that was + modified. + recommendation_subscription (google.ads.googleads.v24.resources.types.RecommendationSubscription): + The mutated recommendation subscription with only mutable + fields after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + recommendation_subscription: ( + gagr_recommendation_subscription.RecommendationSubscription + ) = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_recommendation_subscription.RecommendationSubscription, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/remarketing_action_service.py b/google/ads/googleads/v24/services/types/remarketing_action_service.py new file mode 100644 index 000000000..e7e39dcd0 --- /dev/null +++ b/google/ads/googleads/v24/services/types/remarketing_action_service.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import remarketing_action +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateRemarketingActionsRequest", + "RemarketingActionOperation", + "MutateRemarketingActionsResponse", + "MutateRemarketingActionResult", + }, +) + + +class MutateRemarketingActionsRequest(proto.Message): + r"""Request message for + [RemarketingActionService.MutateRemarketingActions][google.ads.googleads.v24.services.RemarketingActionService.MutateRemarketingActions]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + remarketing actions are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.RemarketingActionOperation]): + Required. The list of operations to perform + on individual remarketing actions. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["RemarketingActionOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="RemarketingActionOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class RemarketingActionOperation(proto.Message): + r"""A single operation (create, update) on a remarketing action. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.RemarketingAction): + Create operation: No resource name is + expected for the new remarketing action. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.RemarketingAction): + Update operation: The remarketing action is + expected to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: remarketing_action.RemarketingAction = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=remarketing_action.RemarketingAction, + ) + update: remarketing_action.RemarketingAction = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=remarketing_action.RemarketingAction, + ) + + +class MutateRemarketingActionsResponse(proto.Message): + r"""Response message for remarketing action mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateRemarketingActionResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateRemarketingActionResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateRemarketingActionResult", + ) + ) + + +class MutateRemarketingActionResult(proto.Message): + r"""The result for the remarketing action mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/reservation_service.py b/google/ads/googleads/v24/services/types/reservation_service.py new file mode 100644 index 000000000..fba842ee3 --- /dev/null +++ b/google/ads/googleads/v24/services/types/reservation_service.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.actions.types import book_campaigns +from google.ads.googleads.v24.actions.types import quote_campaigns + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "QuoteCampaignsRequest", + "QuoteCampaignsResponse", + "BookCampaignsRequest", + "BookCampaignsResponse", + }, +) + + +class QuoteCampaignsRequest(proto.Message): + r"""Request message for + [ReservationService.QuoteCampaigns][google.ads.googleads.v24.services.ReservationService.QuoteCampaigns]. + + Attributes: + customer_id (str): + Required. The ID of the customer making the + request. + operation (google.ads.googleads.v24.actions.types.QuoteCampaignsOperation): + The operation to quote the campaigns. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: quote_campaigns.QuoteCampaignsOperation = proto.Field( + proto.MESSAGE, + number=2, + message=quote_campaigns.QuoteCampaignsOperation, + ) + + +class QuoteCampaignsResponse(proto.Message): + r"""Response message for + [ReservationService.QuoteCampaigns][google.ads.googleads.v24.services.ReservationService.QuoteCampaigns]. + + Attributes: + result (google.ads.googleads.v24.actions.types.QuoteCampaignsResult): + The result of the quote campaigns operation. + """ + + result: quote_campaigns.QuoteCampaignsResult = proto.Field( + proto.MESSAGE, + number=1, + message=quote_campaigns.QuoteCampaignsResult, + ) + + +class BookCampaignsRequest(proto.Message): + r"""Request message for + [ReservationService.BookCampaigns][google.ads.googleads.v24.services.ReservationService.BookCampaigns]. + + Attributes: + customer_id (str): + Required. The ID of the customer making the + request. + operation (google.ads.googleads.v24.actions.types.BookCampaignsOperation): + The operation to book the campaigns. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: book_campaigns.BookCampaignsOperation = proto.Field( + proto.MESSAGE, + number=2, + message=book_campaigns.BookCampaignsOperation, + ) + + +class BookCampaignsResponse(proto.Message): + r"""Response message for + [ReservationService.BookCampaigns][google.ads.googleads.v24.services.ReservationService.BookCampaigns]. + + Attributes: + result (google.ads.googleads.v24.actions.types.BookCampaignsResult): + The result of the book campaigns operation. + """ + + result: book_campaigns.BookCampaignsResult = proto.Field( + proto.MESSAGE, + number=1, + message=book_campaigns.BookCampaignsResult, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/shareable_preview_service.py b/google/ads/googleads/v24/services/types/shareable_preview_service.py new file mode 100644 index 000000000..137b7fcd7 --- /dev/null +++ b/google/ads/googleads/v24/services/types/shareable_preview_service.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + +from google.ads.googleads.v24.actions.types import generate_shareable_previews + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "GenerateShareablePreviewsRequest", + "GenerateShareablePreviewsResponse", + }, +) + + +class GenerateShareablePreviewsRequest(proto.Message): + r"""Request message for + [ShareablePreviewService.GenerateShareablePreviews][google.ads.googleads.v24.services.ShareablePreviewService.GenerateShareablePreviews]. + + Attributes: + customer_id (str): + Required. The customer creating the shareable + previews request. + operation (google.ads.googleads.v24.actions.types.GenerateShareablePreviewsOperation): + The operation to generate shareable previews. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: ( + generate_shareable_previews.GenerateShareablePreviewsOperation + ) = proto.Field( + proto.MESSAGE, + number=3, + message=generate_shareable_previews.GenerateShareablePreviewsOperation, + ) + + +class GenerateShareablePreviewsResponse(proto.Message): + r"""Response message for + [ShareablePreviewService.GenerateShareablePreviews][google.ads.googleads.v24.services.ShareablePreviewService.GenerateShareablePreviews]. + + Attributes: + result (google.ads.googleads.v24.actions.types.GenerateShareablePreviewsResult): + The result of the generate shareable previews + action. + """ + + result: generate_shareable_previews.GenerateShareablePreviewsResult = ( + proto.Field( + proto.MESSAGE, + number=3, + message=generate_shareable_previews.GenerateShareablePreviewsResult, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/shared_criterion_service.py b/google/ads/googleads/v24/services/types/shared_criterion_service.py new file mode 100644 index 000000000..f61824bb5 --- /dev/null +++ b/google/ads/googleads/v24/services/types/shared_criterion_service.py @@ -0,0 +1,186 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + shared_criterion as gagr_shared_criterion, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateSharedCriteriaRequest", + "SharedCriterionOperation", + "MutateSharedCriteriaResponse", + "MutateSharedCriterionResult", + }, +) + + +class MutateSharedCriteriaRequest(proto.Message): + r"""Request message for + [SharedCriterionService.MutateSharedCriteria][google.ads.googleads.v24.services.SharedCriterionService.MutateSharedCriteria]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose shared + criteria are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.SharedCriterionOperation]): + Required. The list of operations to perform + on individual shared criteria. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["SharedCriterionOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="SharedCriterionOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class SharedCriterionOperation(proto.Message): + r"""A single operation (create, remove) on an shared criterion. + + 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: + create (google.ads.googleads.v24.resources.types.SharedCriterion): + Create operation: No resource name is + expected for the new shared criterion. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed shared + criterion is expected, in this format: + + ``customers/{customer_id}/sharedCriteria/{shared_set_id}~{criterion_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: gagr_shared_criterion.SharedCriterion = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_shared_criterion.SharedCriterion, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateSharedCriteriaResponse(proto.Message): + r"""Response message for a shared criterion mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateSharedCriterionResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateSharedCriterionResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateSharedCriterionResult", + ) + ) + + +class MutateSharedCriterionResult(proto.Message): + r"""The result for the shared criterion mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + shared_criterion (google.ads.googleads.v24.resources.types.SharedCriterion): + The mutated shared criterion with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + shared_criterion: gagr_shared_criterion.SharedCriterion = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_shared_criterion.SharedCriterion, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/shared_set_service.py b/google/ads/googleads/v24/services/types/shared_set_service.py new file mode 100644 index 000000000..1e34ef26a --- /dev/null +++ b/google/ads/googleads/v24/services/types/shared_set_service.py @@ -0,0 +1,202 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.resources.types import ( + shared_set as gagr_shared_set, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateSharedSetsRequest", + "SharedSetOperation", + "MutateSharedSetsResponse", + "MutateSharedSetResult", + }, +) + + +class MutateSharedSetsRequest(proto.Message): + r"""Request message for + [SharedSetService.MutateSharedSets][google.ads.googleads.v24.services.SharedSetService.MutateSharedSets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose shared + sets are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.SharedSetOperation]): + Required. The list of operations to perform + on individual shared sets. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["SharedSetOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="SharedSetOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class SharedSetOperation(proto.Message): + r"""A single operation (create, update, remove) on an shared set. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.SharedSet): + Create operation: No resource name is + expected for the new shared set. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.SharedSet): + Update operation: The shared set is expected + to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed shared set + is expected, in this format: + + ``customers/{customer_id}/sharedSets/{shared_set_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: gagr_shared_set.SharedSet = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_shared_set.SharedSet, + ) + update: gagr_shared_set.SharedSet = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_shared_set.SharedSet, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateSharedSetsResponse(proto.Message): + r"""Response message for a shared set mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateSharedSetResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateSharedSetResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateSharedSetResult", + ) + + +class MutateSharedSetResult(proto.Message): + r"""The result for the shared set mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + shared_set (google.ads.googleads.v24.resources.types.SharedSet): + The mutated shared set with only mutable fields after + mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + shared_set: gagr_shared_set.SharedSet = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_shared_set.SharedSet, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/smart_campaign_setting_service.py b/google/ads/googleads/v24/services/types/smart_campaign_setting_service.py new file mode 100644 index 000000000..13c4d65c7 --- /dev/null +++ b/google/ads/googleads/v24/services/types/smart_campaign_setting_service.py @@ -0,0 +1,408 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v24.enums.types import ( + smart_campaign_not_eligible_reason, +) +from google.ads.googleads.v24.enums.types import ( + smart_campaign_status as gage_smart_campaign_status, +) +from google.ads.googleads.v24.resources.types import ( + smart_campaign_setting as gagr_smart_campaign_setting, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "GetSmartCampaignStatusRequest", + "SmartCampaignNotEligibleDetails", + "SmartCampaignEligibleDetails", + "SmartCampaignPausedDetails", + "SmartCampaignRemovedDetails", + "SmartCampaignEndedDetails", + "GetSmartCampaignStatusResponse", + "MutateSmartCampaignSettingsRequest", + "SmartCampaignSettingOperation", + "MutateSmartCampaignSettingsResponse", + "MutateSmartCampaignSettingResult", + }, +) + + +class GetSmartCampaignStatusRequest(proto.Message): + r"""Request message for + [SmartCampaignSettingService.GetSmartCampaignStatus][google.ads.googleads.v24.services.SmartCampaignSettingService.GetSmartCampaignStatus]. + + Attributes: + resource_name (str): + Required. The resource name of the Smart + campaign setting belonging to the Smart campaign + to fetch the status of. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class SmartCampaignNotEligibleDetails(proto.Message): + r"""Details related to Smart campaigns that are not eligible to + serve. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + not_eligible_reason (google.ads.googleads.v24.enums.types.SmartCampaignNotEligibleReasonEnum.SmartCampaignNotEligibleReason): + The reason why the Smart campaign is not + eligible to serve. + + This field is a member of `oneof`_ ``_not_eligible_reason``. + """ + + not_eligible_reason: ( + smart_campaign_not_eligible_reason.SmartCampaignNotEligibleReasonEnum.SmartCampaignNotEligibleReason + ) = proto.Field( + proto.ENUM, + number=1, + optional=True, + enum=smart_campaign_not_eligible_reason.SmartCampaignNotEligibleReasonEnum.SmartCampaignNotEligibleReason, + ) + + +class SmartCampaignEligibleDetails(proto.Message): + r"""Details related to Smart campaigns that are eligible to + serve. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + last_impression_date_time (str): + The timestamp of the last impression observed + in the last 48 hours for this campaign. + The timestamp is in the customer’s timezone and + in “yyyy-MM-dd HH:mm:ss” format. + + This field is a member of `oneof`_ ``_last_impression_date_time``. + end_date_time (str): + The timestamp of when the campaign will end, + if applicable. The timestamp is in the + customer’s timezone and in “yyyy-MM-dd HH:mm:ss” + format. + + This field is a member of `oneof`_ ``_end_date_time``. + """ + + last_impression_date_time: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + end_date_time: str = proto.Field( + proto.STRING, + number=2, + optional=True, + ) + + +class SmartCampaignPausedDetails(proto.Message): + r"""Details related to paused Smart campaigns. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + paused_date_time (str): + The timestamp of when the campaign was last + paused. The timestamp is in the customer’s + timezone and in “yyyy-MM-dd HH:mm:ss” format. + + This field is a member of `oneof`_ ``_paused_date_time``. + """ + + paused_date_time: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class SmartCampaignRemovedDetails(proto.Message): + r"""Details related to removed Smart campaigns. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + removed_date_time (str): + The timestamp of when the campaign was + removed. The timestamp is in the customer’s + timezone and in “yyyy-MM-dd HH:mm:ss” format. + + This field is a member of `oneof`_ ``_removed_date_time``. + """ + + removed_date_time: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class SmartCampaignEndedDetails(proto.Message): + r"""Details related to Smart campaigns that have ended. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + end_date_time (str): + The timestamp of when the campaign ended. + The timestamp is in the customer’s timezone and + in “yyyy-MM-dd HH:mm:ss” format. + + This field is a member of `oneof`_ ``_end_date_time``. + """ + + end_date_time: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +class GetSmartCampaignStatusResponse(proto.Message): + r"""Response message for + [SmartCampaignSettingService.GetSmartCampaignStatus][google.ads.googleads.v24.services.SmartCampaignSettingService.GetSmartCampaignStatus]. + + 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: + smart_campaign_status (google.ads.googleads.v24.enums.types.SmartCampaignStatusEnum.SmartCampaignStatus): + The status of this Smart campaign. + not_eligible_details (google.ads.googleads.v24.services.types.SmartCampaignNotEligibleDetails): + Details related to Smart campaigns that are + ineligible to serve. + + This field is a member of `oneof`_ ``smart_campaign_status_details``. + eligible_details (google.ads.googleads.v24.services.types.SmartCampaignEligibleDetails): + Details related to Smart campaigns that are + eligible to serve. + + This field is a member of `oneof`_ ``smart_campaign_status_details``. + paused_details (google.ads.googleads.v24.services.types.SmartCampaignPausedDetails): + Details related to paused Smart campaigns. + + This field is a member of `oneof`_ ``smart_campaign_status_details``. + removed_details (google.ads.googleads.v24.services.types.SmartCampaignRemovedDetails): + Details related to removed Smart campaigns. + + This field is a member of `oneof`_ ``smart_campaign_status_details``. + ended_details (google.ads.googleads.v24.services.types.SmartCampaignEndedDetails): + Details related to Smart campaigns that have + ended. + + This field is a member of `oneof`_ ``smart_campaign_status_details``. + """ + + smart_campaign_status: ( + gage_smart_campaign_status.SmartCampaignStatusEnum.SmartCampaignStatus + ) = proto.Field( + proto.ENUM, + number=1, + enum=gage_smart_campaign_status.SmartCampaignStatusEnum.SmartCampaignStatus, + ) + not_eligible_details: "SmartCampaignNotEligibleDetails" = proto.Field( + proto.MESSAGE, + number=2, + oneof="smart_campaign_status_details", + message="SmartCampaignNotEligibleDetails", + ) + eligible_details: "SmartCampaignEligibleDetails" = proto.Field( + proto.MESSAGE, + number=3, + oneof="smart_campaign_status_details", + message="SmartCampaignEligibleDetails", + ) + paused_details: "SmartCampaignPausedDetails" = proto.Field( + proto.MESSAGE, + number=4, + oneof="smart_campaign_status_details", + message="SmartCampaignPausedDetails", + ) + removed_details: "SmartCampaignRemovedDetails" = proto.Field( + proto.MESSAGE, + number=5, + oneof="smart_campaign_status_details", + message="SmartCampaignRemovedDetails", + ) + ended_details: "SmartCampaignEndedDetails" = proto.Field( + proto.MESSAGE, + number=6, + oneof="smart_campaign_status_details", + message="SmartCampaignEndedDetails", + ) + + +class MutateSmartCampaignSettingsRequest(proto.Message): + r"""Request message for + [SmartCampaignSettingService.MutateSmartCampaignSettings][google.ads.googleads.v24.services.SmartCampaignSettingService.MutateSmartCampaignSettings]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose Smart + campaign settings are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.SmartCampaignSettingOperation]): + Required. The list of operations to perform + on individual Smart campaign settings. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + response_content_type (google.ads.googleads.v24.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["SmartCampaignSettingOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="SmartCampaignSettingOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + response_content_type: ( + gage_response_content_type.ResponseContentTypeEnum.ResponseContentType + ) = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + + +class SmartCampaignSettingOperation(proto.Message): + r"""A single operation to update Smart campaign settings for a + campaign. + + Attributes: + update (google.ads.googleads.v24.resources.types.SmartCampaignSetting): + Update operation: The Smart campaign setting + must specify a valid resource name. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + """ + + update: gagr_smart_campaign_setting.SmartCampaignSetting = proto.Field( + proto.MESSAGE, + number=1, + message=gagr_smart_campaign_setting.SmartCampaignSetting, + ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=2, + message=field_mask_pb2.FieldMask, + ) + + +class MutateSmartCampaignSettingsResponse(proto.Message): + r"""Response message for campaign mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateSmartCampaignSettingResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + results: MutableSequence["MutateSmartCampaignSettingResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateSmartCampaignSettingResult", + ) + ) + + +class MutateSmartCampaignSettingResult(proto.Message): + r"""The result for the Smart campaign setting mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + smart_campaign_setting (google.ads.googleads.v24.resources.types.SmartCampaignSetting): + The mutated Smart campaign setting with only mutable fields + after mutate. The field will only be returned when + response_content_type is set to "MUTABLE_RESOURCE". + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + smart_campaign_setting: gagr_smart_campaign_setting.SmartCampaignSetting = ( + proto.Field( + proto.MESSAGE, + number=2, + message=gagr_smart_campaign_setting.SmartCampaignSetting, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/smart_campaign_suggest_service.py b/google/ads/googleads/v24/services/types/smart_campaign_suggest_service.py new file mode 100644 index 000000000..8a6c72e14 --- /dev/null +++ b/google/ads/googleads/v24/services/types/smart_campaign_suggest_service.py @@ -0,0 +1,429 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import ad_type_infos +from google.ads.googleads.v24.common.types import criteria +from google.ads.googleads.v24.resources.types import ( + keyword_theme_constant as gagr_keyword_theme_constant, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "SuggestSmartCampaignBudgetOptionsRequest", + "SmartCampaignSuggestionInfo", + "SuggestSmartCampaignBudgetOptionsResponse", + "SuggestSmartCampaignAdRequest", + "SuggestSmartCampaignAdResponse", + "SuggestKeywordThemesRequest", + "SuggestKeywordThemesResponse", + }, +) + + +class SuggestSmartCampaignBudgetOptionsRequest(proto.Message): + r"""Request message for + [SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions]. + + 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: + customer_id (str): + Required. The ID of the customer whose budget + options are to be suggested. + campaign (str): + Required. The resource name of the campaign + to get suggestion for. + + This field is a member of `oneof`_ ``suggestion_data``. + suggestion_info (google.ads.googleads.v24.services.types.SmartCampaignSuggestionInfo): + Required. Information needed to get budget + options + + This field is a member of `oneof`_ ``suggestion_data``. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + campaign: str = proto.Field( + proto.STRING, + number=2, + oneof="suggestion_data", + ) + suggestion_info: "SmartCampaignSuggestionInfo" = proto.Field( + proto.MESSAGE, + number=3, + oneof="suggestion_data", + message="SmartCampaignSuggestionInfo", + ) + + +class SmartCampaignSuggestionInfo(proto.Message): + r"""Information needed to get suggestion for Smart Campaign. More + information provided will help the system to derive better + suggestions. + + 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: + final_url (str): + Optional. Landing page URL of the campaign. + language_code (str): + Optional. The two letter advertising language + for the Smart campaign to be constructed, + default to 'en' if not set. + ad_schedules (MutableSequence[google.ads.googleads.v24.common.types.AdScheduleInfo]): + Optional. The business ad schedule. + keyword_themes (MutableSequence[google.ads.googleads.v24.common.types.KeywordThemeInfo]): + Optional. Smart campaign keyword themes. This + field may greatly improve suggestion accuracy + and we recommend always setting it if possible. + business_context (google.ads.googleads.v24.services.types.SmartCampaignSuggestionInfo.BusinessContext): + Optional. Context describing the business to + advertise. + + This field is a member of `oneof`_ ``business_setting``. + business_profile_location (str): + Optional. The resource name of a Business Profile location. + Business Profile location resource names can be fetched + through the Business Profile API and adhere to the following + format: ``locations/{locationId}``. + + See the [Business Profile API] + (https://developers.google.com/my-business/reference/businessinformation/rest/v1/accounts.locations) + for additional details. + + This field is a member of `oneof`_ ``business_setting``. + location_list (google.ads.googleads.v24.services.types.SmartCampaignSuggestionInfo.LocationList): + Optional. The targeting geo location by + locations. + + This field is a member of `oneof`_ ``geo_target``. + proximity (google.ads.googleads.v24.common.types.ProximityInfo): + Optional. The targeting geo location by + proximity. + + This field is a member of `oneof`_ ``geo_target``. + """ + + class LocationList(proto.Message): + r"""A list of locations. + + Attributes: + locations (MutableSequence[google.ads.googleads.v24.common.types.LocationInfo]): + Required. Locations. + """ + + locations: MutableSequence[criteria.LocationInfo] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=criteria.LocationInfo, + ) + + class BusinessContext(proto.Message): + r"""A context that describes a business. + + Attributes: + business_name (str): + Optional. The name of the business. + """ + + business_name: str = proto.Field( + proto.STRING, + number=1, + ) + + final_url: str = proto.Field( + proto.STRING, + number=1, + ) + language_code: str = proto.Field( + proto.STRING, + number=3, + ) + ad_schedules: MutableSequence[criteria.AdScheduleInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=6, + message=criteria.AdScheduleInfo, + ) + ) + keyword_themes: MutableSequence[criteria.KeywordThemeInfo] = ( + proto.RepeatedField( + proto.MESSAGE, + number=7, + message=criteria.KeywordThemeInfo, + ) + ) + business_context: BusinessContext = proto.Field( + proto.MESSAGE, + number=8, + oneof="business_setting", + message=BusinessContext, + ) + business_profile_location: str = proto.Field( + proto.STRING, + number=9, + oneof="business_setting", + ) + location_list: LocationList = proto.Field( + proto.MESSAGE, + number=4, + oneof="geo_target", + message=LocationList, + ) + proximity: criteria.ProximityInfo = proto.Field( + proto.MESSAGE, + number=5, + oneof="geo_target", + message=criteria.ProximityInfo, + ) + + +class SuggestSmartCampaignBudgetOptionsResponse(proto.Message): + r"""Response message for + [SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions]. + Depending on whether the system could suggest the options, either + all of the options or none of them might be returned. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + low (google.ads.googleads.v24.services.types.SuggestSmartCampaignBudgetOptionsResponse.BudgetOption): + Optional. The lowest budget option. + + This field is a member of `oneof`_ ``_low``. + recommended (google.ads.googleads.v24.services.types.SuggestSmartCampaignBudgetOptionsResponse.BudgetOption): + Optional. The recommended budget option. + + This field is a member of `oneof`_ ``_recommended``. + high (google.ads.googleads.v24.services.types.SuggestSmartCampaignBudgetOptionsResponse.BudgetOption): + Optional. The highest budget option. + + This field is a member of `oneof`_ ``_high``. + """ + + class Metrics(proto.Message): + r"""Performance metrics for a given budget option. + + Attributes: + min_daily_clicks (int): + The estimated min daily clicks. + max_daily_clicks (int): + The estimated max daily clicks. + """ + + min_daily_clicks: int = proto.Field( + proto.INT64, + number=1, + ) + max_daily_clicks: int = proto.Field( + proto.INT64, + number=2, + ) + + class BudgetOption(proto.Message): + r"""Smart Campaign budget option. + + Attributes: + daily_amount_micros (int): + The amount of the budget, in the local + currency for the account. Amount is specified in + micros, where one million is equivalent to one + currency unit. + metrics (google.ads.googleads.v24.services.types.SuggestSmartCampaignBudgetOptionsResponse.Metrics): + Metrics pertaining to the suggested budget, + could be empty if there is not enough + information to derive the estimates. + """ + + daily_amount_micros: int = proto.Field( + proto.INT64, + number=1, + ) + metrics: "SuggestSmartCampaignBudgetOptionsResponse.Metrics" = ( + proto.Field( + proto.MESSAGE, + number=2, + message="SuggestSmartCampaignBudgetOptionsResponse.Metrics", + ) + ) + + low: BudgetOption = proto.Field( + proto.MESSAGE, + number=1, + optional=True, + message=BudgetOption, + ) + recommended: BudgetOption = proto.Field( + proto.MESSAGE, + number=2, + optional=True, + message=BudgetOption, + ) + high: BudgetOption = proto.Field( + proto.MESSAGE, + number=3, + optional=True, + message=BudgetOption, + ) + + +class SuggestSmartCampaignAdRequest(proto.Message): + r"""Request message for + [SmartCampaignSuggestService.SuggestSmartCampaignAd][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestSmartCampaignAd]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + suggestion_info (google.ads.googleads.v24.services.types.SmartCampaignSuggestionInfo): + Required. Inputs used to suggest a Smart campaign ad. + Required fields: final_url, language_code, keyword_themes. + Optional but recommended fields to improve the quality of + the suggestion: business_setting and geo_target. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + suggestion_info: "SmartCampaignSuggestionInfo" = proto.Field( + proto.MESSAGE, + number=2, + message="SmartCampaignSuggestionInfo", + ) + + +class SuggestSmartCampaignAdResponse(proto.Message): + r"""Response message for + [SmartCampaignSuggestService.SuggestSmartCampaignAd][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestSmartCampaignAd]. + + Attributes: + ad_info (google.ads.googleads.v24.common.types.SmartCampaignAdInfo): + Optional. Ad info includes 3 creative + headlines and 2 creative descriptions. + """ + + ad_info: ad_type_infos.SmartCampaignAdInfo = proto.Field( + proto.MESSAGE, + number=1, + message=ad_type_infos.SmartCampaignAdInfo, + ) + + +class SuggestKeywordThemesRequest(proto.Message): + r"""Request message for + [SmartCampaignSuggestService.SuggestKeywordThemes][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestKeywordThemes]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + suggestion_info (google.ads.googleads.v24.services.types.SmartCampaignSuggestionInfo): + Required. Information to get keyword theme suggestions. + Required fields: + + - suggestion_info.final_url + - suggestion_info.language_code + - suggestion_info.geo_target + + Recommended fields: + + - suggestion_info.business_setting + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + suggestion_info: "SmartCampaignSuggestionInfo" = proto.Field( + proto.MESSAGE, + number=2, + message="SmartCampaignSuggestionInfo", + ) + + +class SuggestKeywordThemesResponse(proto.Message): + r"""Response message for + [SmartCampaignSuggestService.SuggestKeywordThemes][google.ads.googleads.v24.services.SmartCampaignSuggestService.SuggestKeywordThemes]. + + Attributes: + keyword_themes (MutableSequence[google.ads.googleads.v24.services.types.SuggestKeywordThemesResponse.KeywordTheme]): + Smart campaign keyword theme suggestions. + """ + + class KeywordTheme(proto.Message): + r"""A Smart campaign keyword theme suggestion. + + 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: + keyword_theme_constant (google.ads.googleads.v24.resources.types.KeywordThemeConstant): + A Smart campaign keyword theme constant. + + This field is a member of `oneof`_ ``keyword_theme``. + free_form_keyword_theme (str): + A free-form text keyword theme. + + This field is a member of `oneof`_ ``keyword_theme``. + """ + + keyword_theme_constant: ( + gagr_keyword_theme_constant.KeywordThemeConstant + ) = proto.Field( + proto.MESSAGE, + number=1, + oneof="keyword_theme", + message=gagr_keyword_theme_constant.KeywordThemeConstant, + ) + free_form_keyword_theme: str = proto.Field( + proto.STRING, + number=2, + oneof="keyword_theme", + ) + + keyword_themes: MutableSequence[KeywordTheme] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=KeywordTheme, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/third_party_app_analytics_link_service.py b/google/ads/googleads/v24/services/types/third_party_app_analytics_link_service.py new file mode 100644 index 000000000..a4a797a5f --- /dev/null +++ b/google/ads/googleads/v24/services/types/third_party_app_analytics_link_service.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "RegenerateShareableLinkIdRequest", + "RegenerateShareableLinkIdResponse", + }, +) + + +class RegenerateShareableLinkIdRequest(proto.Message): + r"""Request message for + [ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId][google.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId]. + + Attributes: + resource_name (str): + Resource name of the third party app + analytics link. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class RegenerateShareableLinkIdResponse(proto.Message): + r"""Response message for + [ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId][google.ads.googleads.v24.services.ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId]. + + """ + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/travel_asset_suggestion_service.py b/google/ads/googleads/v24/services/types/travel_asset_suggestion_service.py new file mode 100644 index 000000000..a77e9c52f --- /dev/null +++ b/google/ads/googleads/v24/services/types/travel_asset_suggestion_service.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.enums.types import ( + asset_field_type as gage_asset_field_type, +) +from google.ads.googleads.v24.enums.types import call_to_action_type +from google.ads.googleads.v24.enums.types import hotel_asset_suggestion_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "SuggestTravelAssetsRequest", + "SuggestTravelAssetsResponse", + "HotelAssetSuggestion", + "HotelTextAsset", + "HotelImageAsset", + }, +) + + +class SuggestTravelAssetsRequest(proto.Message): + r"""Request message for + [TravelAssetSuggestionService.SuggestTravelAssets][google.ads.googleads.v24.services.TravelAssetSuggestionService.SuggestTravelAssets]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + language_option (str): + Required. The language specifications in BCP + 47 format (for example, en-US, zh-CN, etc.) for + the asset suggestions. Text will be in this + language. Usually matches one of the campaign + target languages. + place_ids (MutableSequence[str]): + The Google Maps Place IDs of hotels for which + assets are requested. See + https://developers.google.com/places/web-service/place-id + for more information. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + language_option: str = proto.Field( + proto.STRING, + number=2, + ) + place_ids: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=4, + ) + + +class SuggestTravelAssetsResponse(proto.Message): + r"""Response message for + [TravelAssetSuggestionService.SuggestTravelAssets][google.ads.googleads.v24.services.TravelAssetSuggestionService.SuggestTravelAssets]. + + Attributes: + hotel_asset_suggestions (MutableSequence[google.ads.googleads.v24.services.types.HotelAssetSuggestion]): + Asset suggestions for each place ID submitted + in the request. + """ + + hotel_asset_suggestions: MutableSequence["HotelAssetSuggestion"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="HotelAssetSuggestion", + ) + ) + + +class HotelAssetSuggestion(proto.Message): + r"""Message containing the asset suggestions for a hotel. + + Attributes: + place_id (str): + Google Places ID of the hotel. + final_url (str): + Suggested final URL for an AssetGroup. + hotel_name (str): + Hotel name in requested language. + call_to_action (google.ads.googleads.v24.enums.types.CallToActionTypeEnum.CallToActionType): + Call to action type. + text_assets (MutableSequence[google.ads.googleads.v24.services.types.HotelTextAsset]): + Text assets such as headline, description, + etc. + image_assets (MutableSequence[google.ads.googleads.v24.services.types.HotelImageAsset]): + Image assets such as + landscape/portrait/square, etc. + status (google.ads.googleads.v24.enums.types.HotelAssetSuggestionStatusEnum.HotelAssetSuggestionStatus): + The status of the hotel asset suggestion. + """ + + place_id: str = proto.Field( + proto.STRING, + number=1, + ) + final_url: str = proto.Field( + proto.STRING, + number=2, + ) + hotel_name: str = proto.Field( + proto.STRING, + number=3, + ) + call_to_action: ( + call_to_action_type.CallToActionTypeEnum.CallToActionType + ) = proto.Field( + proto.ENUM, + number=4, + enum=call_to_action_type.CallToActionTypeEnum.CallToActionType, + ) + text_assets: MutableSequence["HotelTextAsset"] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="HotelTextAsset", + ) + image_assets: MutableSequence["HotelImageAsset"] = proto.RepeatedField( + proto.MESSAGE, + number=6, + message="HotelImageAsset", + ) + status: ( + hotel_asset_suggestion_status.HotelAssetSuggestionStatusEnum.HotelAssetSuggestionStatus + ) = proto.Field( + proto.ENUM, + number=7, + enum=hotel_asset_suggestion_status.HotelAssetSuggestionStatusEnum.HotelAssetSuggestionStatus, + ) + + +class HotelTextAsset(proto.Message): + r"""A single text asset suggestion for a hotel. + + Attributes: + text (str): + Asset text in requested language. + asset_field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + The text asset type. For example, HEADLINE, + DESCRIPTION, etc. + """ + + text: str = proto.Field( + proto.STRING, + number=1, + ) + asset_field_type: ( + gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + + +class HotelImageAsset(proto.Message): + r"""A single image asset suggestion for a hotel. + + Attributes: + uri (str): + URI for the image. + asset_field_type (google.ads.googleads.v24.enums.types.AssetFieldTypeEnum.AssetFieldType): + The Image asset type. For example, MARKETING_IMAGE, + PORTRAIT_MARKETING_IMAGE, etc. + """ + + uri: str = proto.Field( + proto.STRING, + number=1, + ) + asset_field_type: ( + gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType + ) = proto.Field( + proto.ENUM, + number=2, + enum=gage_asset_field_type.AssetFieldTypeEnum.AssetFieldType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/user_data_service.py b/google/ads/googleads/v24/services/types/user_data_service.py new file mode 100644 index 000000000..03db32707 --- /dev/null +++ b/google/ads/googleads/v24/services/types/user_data_service.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.common.types import offline_user_data + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "UploadUserDataRequest", + "UserDataOperation", + "UploadUserDataResponse", + }, +) + + +class UploadUserDataRequest(proto.Message): + r"""Request message for + [UserDataService.UploadUserData][google.ads.googleads.v24.services.UserDataService.UploadUserData] + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + customer_id (str): + Required. The ID of the customer for which to + update the user data. + operations (MutableSequence[google.ads.googleads.v24.services.types.UserDataOperation]): + Required. The list of operations to be done. + customer_match_user_list_metadata (google.ads.googleads.v24.common.types.CustomerMatchUserListMetadata): + Metadata for data updates to a Customer Match + user list. + + This field is a member of `oneof`_ ``metadata``. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["UserDataOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="UserDataOperation", + ) + customer_match_user_list_metadata: ( + offline_user_data.CustomerMatchUserListMetadata + ) = proto.Field( + proto.MESSAGE, + number=2, + oneof="metadata", + message=offline_user_data.CustomerMatchUserListMetadata, + ) + + +class UserDataOperation(proto.Message): + r"""Operation to be made for the UploadUserDataRequest. + + 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: + create (google.ads.googleads.v24.common.types.UserData): + The list of user data to be appended to the + user list. + + This field is a member of `oneof`_ ``operation``. + remove (google.ads.googleads.v24.common.types.UserData): + The list of user data to be removed from the + user list. + + This field is a member of `oneof`_ ``operation``. + """ + + create: offline_user_data.UserData = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=offline_user_data.UserData, + ) + remove: offline_user_data.UserData = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=offline_user_data.UserData, + ) + + +class UploadUserDataResponse(proto.Message): + r"""Response message for + [UserDataService.UploadUserData][google.ads.googleads.v24.services.UserDataService.UploadUserData] + Uploads made through this service will not be visible under the + 'Segment members' section for the Customer Match List in the Google + Ads UI. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + upload_date_time (str): + The date time at which the request was received by API, + formatted as "yyyy-mm-dd hh:mm:ss+\|-hh:mm", for example, + "2019-01-01 12:32:45-08:00". + + This field is a member of `oneof`_ ``_upload_date_time``. + received_operations_count (int): + Number of upload data operations received by + API. + + This field is a member of `oneof`_ ``_received_operations_count``. + """ + + upload_date_time: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + received_operations_count: int = proto.Field( + proto.INT32, + number=4, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/user_list_customer_type_service.py b/google/ads/googleads/v24/services/types/user_list_customer_type_service.py new file mode 100644 index 000000000..788070a89 --- /dev/null +++ b/google/ads/googleads/v24/services/types/user_list_customer_type_service.py @@ -0,0 +1,164 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import user_list_customer_type +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateUserListCustomerTypesRequest", + "UserListCustomerTypeOperation", + "MutateUserListCustomerTypesResponse", + "MutateUserListCustomerTypeResult", + }, +) + + +class MutateUserListCustomerTypesRequest(proto.Message): + r"""Request message for + [UserListCustomerTypeService.MutateUserListCustomerTypes][google.ads.googleads.v24.services.UserListCustomerTypeService.MutateUserListCustomerTypes]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose user + list customer types are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.UserListCustomerTypeOperation]): + Required. The list of operations to perform + on the user list customer types. + partial_failure (bool): + Optional. If true, successful operations will + be carried out and invalid operations will + return errors. If false, all operations will be + carried out in one transaction if and only if + they are all valid. Default is false. + validate_only (bool): + Optional. If true, the request is validated + but not executed. Only errors are returned, not + results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["UserListCustomerTypeOperation"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="UserListCustomerTypeOperation", + ) + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class UserListCustomerTypeOperation(proto.Message): + r"""A single mutate operation on the user list customer type. + + 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: + create (google.ads.googleads.v24.resources.types.UserListCustomerType): + Attach a user list customer type to a user + list. No resource name is expected for the new + user list customer type. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove an existing user list customer type. A resource name + for the removed user list customer type is expected, in this + format: + + ``customers/{customer_id}/userListCustomerTypes/{user_list_id}~{customer_type_category}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: user_list_customer_type.UserListCustomerType = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=user_list_customer_type.UserListCustomerType, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateUserListCustomerTypesResponse(proto.Message): + r"""Response message for a user list customer type mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateUserListCustomerTypeResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=1, + message=status_pb2.Status, + ) + results: MutableSequence["MutateUserListCustomerTypeResult"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateUserListCustomerTypeResult", + ) + ) + + +class MutateUserListCustomerTypeResult(proto.Message): + r"""The result for the user list customer type mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/user_list_service.py b/google/ads/googleads/v24/services/types/user_list_service.py new file mode 100644 index 000000000..08b007228 --- /dev/null +++ b/google/ads/googleads/v24/services/types/user_list_service.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import user_list +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "MutateUserListsRequest", + "UserListOperation", + "MutateUserListsResponse", + "MutateUserListResult", + }, +) + + +class MutateUserListsRequest(proto.Message): + r"""Request message for + [UserListService.MutateUserLists][google.ads.googleads.v24.services.UserListService.MutateUserLists]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose user + lists are being modified. + operations (MutableSequence[google.ads.googleads.v24.services.types.UserListOperation]): + Required. The list of operations to perform + on individual user lists. + partial_failure (bool): + If true, successful operations will be + carried out and invalid operations will return + errors. If false, all operations will be carried + out in one transaction if and only if they are + all valid. Default is false. + validate_only (bool): + If true, the request is validated but not + executed. Only errors are returned, not results. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["UserListOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="UserListOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class UserListOperation(proto.Message): + r"""A single operation (create, update) on a user list. + + 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v24.resources.types.UserList): + Create operation: No resource name is + expected for the new user list. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v24.resources.types.UserList): + Update operation: The user list is expected + to have a valid resource name. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed user list + is expected, in this format: + + ``customers/{customer_id}/userLists/{user_list_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + create: user_list.UserList = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=user_list.UserList, + ) + update: user_list.UserList = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=user_list.UserList, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateUserListsResponse(proto.Message): + r"""Response message for user list mutate. + + Attributes: + partial_failure_error (google.rpc.status_pb2.Status): + Errors that pertain to operation failures in the partial + failure mode. Returned only when partial_failure = true and + all errors occur inside the operations. If any errors occur + outside the operations (for example, auth errors), we return + an RPC level error. + results (MutableSequence[google.ads.googleads.v24.services.types.MutateUserListResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateUserListResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateUserListResult", + ) + + +class MutateUserListResult(proto.Message): + r"""The result for the user list mutate. + + Attributes: + resource_name (str): + Returned for successful operations. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v24/services/types/youtube_video_upload_service.py b/google/ads/googleads/v24/services/types/youtube_video_upload_service.py new file mode 100644 index 000000000..bff5cbee5 --- /dev/null +++ b/google/ads/googleads/v24/services/types/youtube_video_upload_service.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 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 MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v24.resources.types import youtube_video_upload +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v24.services", + marshal="google.ads.googleads.v24", + manifest={ + "CreateYouTubeVideoUploadRequest", + "CreateYouTubeVideoUploadResponse", + "UpdateYouTubeVideoUploadRequest", + "UpdateYouTubeVideoUploadResponse", + "RemoveYouTubeVideoUploadRequest", + "RemoveYouTubeVideoUploadResponse", + }, +) + + +class CreateYouTubeVideoUploadRequest(proto.Message): + r"""Request message for + [YouTubeVideoUploadService.CreateYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.CreateYouTubeVideoUpload]. + + Attributes: + customer_id (str): + Required. The customer ID requesting the + upload. Required. + you_tube_video_upload (google.ads.googleads.v24.resources.types.YouTubeVideoUpload): + Required. The initial details of the video to + upload. Required. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + you_tube_video_upload: youtube_video_upload.YouTubeVideoUpload = ( + proto.Field( + proto.MESSAGE, + number=2, + message=youtube_video_upload.YouTubeVideoUpload, + ) + ) + + +class CreateYouTubeVideoUploadResponse(proto.Message): + r"""Response message for + [YouTubeVideoUploadService.CreateYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.CreateYouTubeVideoUpload]. + + Attributes: + resource_name (str): + The resource name of the successfully created + YouTube video upload. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class UpdateYouTubeVideoUploadRequest(proto.Message): + r"""Request message for + [YouTubeVideoUploadService.UpdateYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.UpdateYouTubeVideoUpload]. + + Attributes: + customer_id (str): + Required. The customer ID requesting the + YouTube video upload update. Required. + you_tube_video_upload (google.ads.googleads.v24.resources.types.YouTubeVideoUpload): + Required. The YouTube video upload resource + to be updated. It's expected to have a valid + resource name. Required. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Required. FieldMask that determines which + resource fields are modified in an update. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + you_tube_video_upload: youtube_video_upload.YouTubeVideoUpload = ( + proto.Field( + proto.MESSAGE, + number=2, + message=youtube_video_upload.YouTubeVideoUpload, + ) + ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=3, + message=field_mask_pb2.FieldMask, + ) + + +class UpdateYouTubeVideoUploadResponse(proto.Message): + r"""Response message for + [YouTubeVideoUploadService.UpdateYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.UpdateYouTubeVideoUpload]. + + Attributes: + resource_name (str): + The resource name of the successfully updated + YouTube video upload. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class RemoveYouTubeVideoUploadRequest(proto.Message): + r"""Request message for + [YouTubeVideoUploadService.RemoveYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.RemoveYouTubeVideoUpload]. + + Attributes: + customer_id (str): + Required. The customer ID requesting the + YouTube video upload deletion. Required. + resource_names (MutableSequence[str]): + The resource names of the YouTube video + uploads to be removed. Required. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + resource_names: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=2, + ) + + +class RemoveYouTubeVideoUploadResponse(proto.Message): + r"""Response message for + [YouTubeVideoUploadService.RemoveYouTubeVideoUpload][google.ads.googleads.v24.services.YouTubeVideoUploadService.RemoveYouTubeVideoUpload]. + + Attributes: + resource_names (MutableSequence[str]): + The resource names of the successfully + removed YouTube video uploads. + """ + + resource_names: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/pyproject.toml b/pyproject.toml index f46fc7049..e6b7e2134 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ build-backend = "setuptools.build_meta" [project] name = "google-ads" -version = "30.0.0" +version = "30.1.0" description = "Client library for the Google Ads API" readme = "./README.rst" requires-python = ">=3.9, <3.15" @@ -55,8 +55,9 @@ dependencies = [ "proto-plus >= 1.22.3, < 2.0.0", "proto-plus >= 1.25.0, < 2.0.0; python_version >= '3.13'", "PyYAML >= 5.1, < 7.0", - "protobuf >= 4.25.0, < 7.0.0", - "protobuf >= 5.26.1, < 7.0.0; python_version >= '3.13'", + "protobuf >= 4.25.0, < 7.0.0; python_version < '3.10'", + "protobuf >= 4.25.0, < 8.0.0; python_version >= '3.10'", + "protobuf >= 5.26.1; python_version >= '3.13'", ] [project.optional-dependencies]